1.セグウェイ風ロボットの作成 TOPへ 3.ETロボコンコースに挑戦

2.リモコンロボットの作成


今回は、操縦できるロボットを作ってみましょう。
送信用と、受信用の2台のNXTが必要です。
受信側には、基礎編で作ったロボットをそのまま使います。
送信側も、基礎編で作ったロボットをそのまま使います。また、前章の倒立ロボットでもかまいません。


1.受信側プログラム

受信側プログラムは、下の4つのファイルからなります。
makefile
nxt_config.h
remote_sla1.c
remote_sla1.oil

"remote_sla1.c"の記述は以下のようになっています。
remote_sla1.c
#include "kernel.h"
#include "kernel_id.h"
#include "ecrobot_interface.h"
#include "nxt_config.h"

/* NXT Bluetooth configuration */
#define BT_PASS_KEY		"1234"	/* bluetoothパスキー */
#define BT_RCV_BUF_SIZE 32		/* bluetooth受信バッファの大きさ */
U8 bt_receive_buf[BT_RCV_BUF_SIZE];	/* bluetooth受信バッファの宣言 */

int forward=0,turn=0;		//前進指令値、旋回値変数宣言
int pwm_L=0, pwm_R=0;		//PWM値格納変数宣言

DeclareCounter(SysTimerCnt);
DeclareTask(Task_bg);				/* Task_bgを宣言 */
DeclareTask(Task_drive);				/* Task_balanceを宣言 */
DeclareTask(Task_LCD);				/* Task_balanceを宣言 */

void ecrobot_device_initialize(){
	nxt_motor_set_speed(PORT_MOTOR_L, 0, 1);
	nxt_motor_set_speed(PORT_MOTOR_R, 0, 1);
	ecrobot_init_bt_slave(BT_PASS_KEY);	/* スレーブとして初期化 */
}

void ecrobot_device_terminate(){
	nxt_motor_set_speed(PORT_MOTOR_L, 0, 1);
	nxt_motor_set_speed(PORT_MOTOR_R, 0, 1);
	ecrobot_term_bt_connection();		/* bluetooth通信終了 */
}

void user_1ms_isr_type2(void) {
    StatusType ercd;
    ercd = SignalCounter(SysTimerCnt);
    if (ercd != E_OK)
    {
        ShutdownOS(ercd);
    }
}

TASK(Task_drive){		//走るタスク

	pwm_L = forward + turn;
	if(pwm_L > 100)
		pwm_L = 100;
	if(pwm_L < -100)
		pwm_L = -100;
		
	pwm_R = forward - turn;
	if(pwm_R > 100)
		pwm_R = 100;
	if(pwm_R < -100)
		pwm_R = -100;
	
	nxt_motor_set_speed(PORT_MOTOR_L, pwm_L, 1);	//モータに指令を出す
	nxt_motor_set_speed(PORT_MOTOR_R, pwm_R, 1);
	
	TerminateTask();
}

TASK(Task_LCD){
	
	display_clear(0);
	display_goto_xy(0,1);
	display_string("fwd=");		/* 変数の内容を表示 */
	display_goto_xy(8,1);
	display_int((S8)bt_receive_buf[0], 4);
	display_update();
	
	display_goto_xy(0,2);
	display_string("trn=");		/* 変数の内容を表示 */
	display_goto_xy(8,2);
	display_int((S8)bt_receive_buf[1], 4);
	display_update();
	
	TerminateTask();
}

TASK(Task_bg){

	nxt_motor_set_count(PORT_MOTOR_L, 0);
	nxt_motor_set_count(PORT_MOTOR_R, 0);
	
	while(1){
		ecrobot_read_bt_packet(bt_receive_buf, BT_RCV_BUF_SIZE);	/* 受信したものを受信バッファに代入 */
		forward=(S8)bt_receive_buf[0];
		turn=(S8)bt_receive_buf[1];
		systick_wait_ms(1);
	}
	TerminateTask();
}

受信用プログラムです。




2.送信側プログラム

送信側プログラムは、下の4つのファイルからなります。
makefile
nxt_config.h
remote_mas.c
remote_mas.oil

"remote_mas.c"の記述は以下のようになっています。
remote_mas.c
#include "kernel.h"
#include "kernel_id.h"
#include "ecrobot_interface.h"
#include "nxt_config.h"

/* NXT Bluetooth configuration */
#define BT_PASS_KEY		"1234"	/* bluetoothパスキー */
#define BT_SNV_BUF_SIZE 32		/* bluetooth送信バッファの大きさ */

const U8 BD_ADDR[7] = {0x00,0x16,0x53,0x06,0x89,0xB5,0x00};	/* スレーブNXTのデバイスアドレス */
//const U8 BD_ADDR[7] = {0x00,0x16,0x53,0x01,0x85,0x83,0x00};	/* スレーブNXTのデバイスアドレス */
U8 bt_send_buf[BT_SNV_BUF_SIZE];	/* bluetooth送信バッファの宣言 */
int forward,turn,rev_l,rev_r;


DeclareCounter(SysTimerCnt);		/* SysTimerCntを宣言 */
DeclareTask(Task_Feedback);				/* Task_Feedbackを宣言 */
DeclareTask(Task_LCD);				/* Task_LCDを宣言 */
DeclareTask(Task_Ctrl);				/* Task_Ctrlを宣言 */

void ecrobot_device_initialize(){
	ecrobot_init_bt_master(BD_ADDR, BT_PASS_KEY);	/* マスターとして初期化 */
}

void ecrobot_device_terminate(){
	ecrobot_term_bt_connection();		/* bluetooth通信終了 */
}

void user_1ms_isr_type2(void){
    StatusType ercd;
    ercd = SignalCounter(SysTimerCnt);
    if (ercd != E_OK)
    {
        ShutdownOS(ercd);
    }
}
TASK(Task_Feedback){		/* つまみが自動で中央に戻る */
	rev_l=nxt_motor_get_count(PORT_MOTOR_L);
	if(rev_l>=-5||rev_l<=5)
		nxt_motor_set_speed(PORT_MOTOR_L, 0, 0);
	if(rev_l>5)
		nxt_motor_set_speed(PORT_MOTOR_L, -55, 0);
	if(rev_l<-5)
		nxt_motor_set_speed(PORT_MOTOR_L, 55, 0);

	rev_r=nxt_motor_get_count(PORT_MOTOR_R);
	if(rev_r>=-5||rev_r<=5)
		nxt_motor_set_speed(PORT_MOTOR_R, 0, 0);
	if(rev_r>5)
		nxt_motor_set_speed(PORT_MOTOR_R, -55, 0);
	if(rev_r<-5)
		nxt_motor_set_speed(PORT_MOTOR_R, 55, 0);
	
	TerminateTask();
}

TASK(Task_LCD){
	display_clear(0);
	display_goto_xy(0,1);
	display_string("fwd= ");		/* 変数の内容を表示 */
	display_int((S8)bt_send_buf[0], 4);
	display_goto_xy(0,2);
	display_string("trn= ");		/* 変数の内容を表示 */
	display_int((S8)bt_send_buf[1], 4);
	display_update();
	
	TerminateTask();					/* 処理終了 */
}

TASK(Task_Ctrl)
{
	nxt_motor_set_count(PORT_MOTOR_L, 0);
	nxt_motor_set_count(PORT_MOTOR_R, 0);	
	
	while(1){
		forward = nxt_motor_get_count(PORT_MOTOR_L);		/* 入力倍率 = 1 */
		if(forward>100){
			forward=100;
			nxt_motor_set_count(PORT_MOTOR_L, 100);			/* 100〜-100におさめる */
		}
		if(forward<-100){
			forward=-100;
			nxt_motor_set_count(PORT_MOTOR_L, -100);
		}
		turn = nxt_motor_get_count(PORT_MOTOR_R)/2;		/* 入力倍率 = 1/2 */
		if(turn>100){
			turn=100;
			nxt_motor_set_count(PORT_MOTOR_R, 200);			/* 100〜-100におさめる */
		}
		if(turn<-100){
			turn=-100;
			nxt_motor_set_count(PORT_MOTOR_R, -200);
		}
		
		bt_send_buf[0]=forward;		/* 送信バッファに代入 */
		bt_send_buf[1]=turn;
		
		ecrobot_send_bt_packet(bt_send_buf, BT_SNV_BUF_SIZE);	/* 送信バッファの中身を送信 */	
		
		systick_wait_ms(5);
	}
	TerminateTask();					/* 処理終了 */
}

Bluetooth通信を用いているので、受信側(スレーブ)から先に起動し、画面に<BT>の表示が出てから実行してください。

送信側ロボットのタイヤを手で回してみましょう。ロボットが走ったり、曲がったりします。

タイヤが自動的に中心に戻るようにしていますが、出来が微妙です。
是非、改良しましょう。

ロータリーエンコーダだけでなく、他のセンサ(加速度センサなど)を使って操縦できるようにしてみましょう。



※おまけ.倒立ロボットの操縦

倒立ロボットを操縦できるプログラムを以下に示します。
送信側プログラムは、上のものがそのまま使えますが、入力倍率などを変更したほうが良いかもしれません。
動作させるには以下のファイルが必要です。
makefile
balancer_param.c
nxt_config.h
remote_sla2.c
remote_sla2.oil

ソースファイルはこのようになっています。
remote_sla2.c
#include "kernel.h"
#include "kernel_id.h"
#include "ecrobot_interface.h"
#include "balancer.h"
#include "nxt_config.h"

/* NXT Bluetooth configuration */
#define BT_PASS_KEY		"1234"	/* bluetoothパスキー */
#define BT_RCV_BUF_SIZE 32		/* bluetooth受信バッファの大きさ */
U8 bt_receive_buf[BT_RCV_BUF_SIZE];	/* bluetooth受信バッファの宣言 */

int forward=0,turn=0;		//前進指令値、旋回値変数宣言
signed char pwm_L=0, pwm_R=0;		//PWM値格納変数宣言
int gyro_offset=0;		//ジャイロオフセット値格納変数宣言

DeclareCounter(SysTimerCnt);
DeclareTask(Task_bg);				/* Task_bgを宣言 */
DeclareTask(Task_balance);				/* Task_balanceを宣言 */
DeclareTask(Task_LCD);				/* Task_balanceを宣言 */

void ecrobot_device_initialize(){
	nxt_motor_set_speed(PORT_MOTOR_L, 0, 1);
	nxt_motor_set_speed(PORT_MOTOR_R, 0, 1);
	ecrobot_init_bt_slave(BT_PASS_KEY);	/* スレーブとして初期化 */
}

void ecrobot_device_terminate(){
	nxt_motor_set_speed(PORT_MOTOR_L, 0, 1);
	nxt_motor_set_speed(PORT_MOTOR_R, 0, 1);
	ecrobot_term_bt_connection();		/* bluetooth通信終了 */
}

void user_1ms_isr_type2(void) {
    StatusType ercd;
    ercd = SignalCounter(SysTimerCnt);
    if (ercd != E_OK)
    {
        ShutdownOS(ercd);
    }
}

TASK(Task_blance){		//バランスタスク

	balance_control(		//バランサAPIの呼び出し
		(float)forward,
		(float)turn,
		(float)ecrobot_get_gyro_sensor(PORT_GYRO),
		(float)gyro_offset,
		(float)nxt_motor_get_count(PORT_MOTOR_L),
		(float)nxt_motor_get_count(PORT_MOTOR_R),
		(float)ecrobot_get_battery_voltage(),
		&pwm_L,
		&pwm_R
	);
	
	nxt_motor_set_speed(PORT_MOTOR_L, pwm_L, 1);	//モータに指令を出す
	nxt_motor_set_speed(PORT_MOTOR_R, pwm_R, 1);
	
	TerminateTask();
}

TASK(Task_LCD){
	
	display_clear(0);
	display_goto_xy(0,1);
	display_string("fwd=");		/* 変数の内容を表示 */
	display_goto_xy(8,1);
	display_int((S8)bt_receive_buf[0], 4);
	display_update();
	
	display_goto_xy(0,2);
	display_string("trn=");		/* 変数の内容を表示 */
	display_goto_xy(8,2);
	display_int((S8)bt_receive_buf[1], 4);
	display_update();
	
	TerminateTask();
}

TASK(Task_bg){

	gyro_offset = ecrobot_get_gyro_sensor(PORT_GYRO); //ジャイロの初期値補正

	balance_init();		//バランサAPIの初期化
	nxt_motor_set_count(PORT_MOTOR_L, 0);
	nxt_motor_set_count(PORT_MOTOR_R, 0);
	
	while(1){
		ecrobot_read_bt_packet(bt_receive_buf, BT_RCV_BUF_SIZE);	/* 受信したものを受信バッファに代入 */
		forward=(S8)bt_receive_buf[0];
		turn=(S8)bt_receive_buf[1];
		systick_wait_ms(1);
	}
	TerminateTask();
}






1.セグウェイ風ロボットの作成 TOPへ 3.ETロボコンコースに挑戦