送信用と、受信用の2台のNXTが必要です。
受信側には、基礎編で作ったロボットをそのまま使います。
送信側も、基礎編で作ったロボットをそのまま使います。また、前章の倒立ロボットでもかまいません。
1.受信側プログラム
受信側プログラムは、下の4つのファイルからなります。
makefile
nxt_config.h
remote_sla1.c
remote_sla1.oil
"remote_sla1.c"の記述は以下のようになっています。
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"の記述は以下のようになっています。
送信側ロボットのタイヤを手で回してみましょう。ロボットが走ったり、曲がったりします。
タイヤが自動的に中心に戻るようにしていますが、出来が微妙です。
是非、改良しましょう。
ロータリーエンコーダだけでなく、他のセンサ(加速度センサなど)を使って操縦できるようにしてみましょう。
makefile
nxt_config.h
remote_mas.c
remote_mas.oil
"remote_mas.c"の記述は以下のようになっています。
remote_mas.c
Bluetooth通信を用いているので、受信側(スレーブ)から先に起動し、画面に<BT>の表示が出てから実行してください。
#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(); /* 処理終了 */ } |
送信側ロボットのタイヤを手で回してみましょう。ロボットが走ったり、曲がったりします。
タイヤが自動的に中心に戻るようにしていますが、出来が微妙です。
是非、改良しましょう。
ロータリーエンコーダだけでなく、他のセンサ(加速度センサなど)を使って操縦できるようにしてみましょう。
※おまけ.倒立ロボットの操縦
倒立ロボットを操縦できるプログラムを以下に示します。
送信側プログラムは、上のものがそのまま使えますが、入力倍率などを変更したほうが良いかもしれません。
動作させるには以下のファイルが必要です。
makefile
balancer_param.c
nxt_config.h
remote_sla2.c
remote_sla2.oil
ソースファイルはこのようになっています。
送信側プログラムは、上のものがそのまま使えますが、入力倍率などを変更したほうが良いかもしれません。
動作させるには以下のファイルが必要です。
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(); } |