1.走行体の作成
左右にモータを1つずつ使用した走行体を作成します。
例として、ここではNXT付属のロボット組立て図に記載された標準走行体(以下、走行体)を用います。(p8・2参照)
ー
モータを組み立てたら、モータ動作確認ページに従って左右のモータ動作を確認してみて下さい。
例として、ここではNXT付属のロボット組立て図に記載された標準走行体(以下、走行体)を用います。(p8・2参照)
ー
モータを組み立てたら、モータ動作確認ページに従って左右のモータ動作を確認してみて下さい。
2.走行体を直進させる
次にプログラムを作成します。
ここでは2秒前進してから、2秒後退して止まるプログラムを作成します。 次のプログラムを作成してください。ここでは作成プログラムを motor1 とします。
oilファイルとMakefileは前回と同じ内容のものを使います。ただしファイル名を修正してください。
このプログラムの解説をします。
プログラムのコンパイル・転送・実行を参考にプログラムをダウンロードし、動作させて下さい。
Makefile で変更を必要とするのは、TARGET名と、TARGET_SOUCES のファイル名です。TOPPERS_OSEK_OIL_SOURCESの指定は変更しないで下さい。その際、TARGET名やTARGET_SOUCESのファイル名の後ろに、space コードが入っているとコンパイルエラーになるので注意して下さい。
また、このプログラムをそのまま動作させると、直進するはずがどちらに曲がってしまうかもしれません。 これは左右のモータの個体差により、同じduty比の指定を行っても、それぞれのモータのトルクが異なり、結果的にモータの回転速度が異なってしまうからです。 そのような場合は左右のモータのduty比を調整して、直進するようにさせる必要があります。
これで走行体を真っ直ぐに前進・後退させることができます。
ここでは2秒前進してから、2秒後退して止まるプログラムを作成します。 次のプログラムを作成してください。ここでは作成プログラムを motor1 とします。
oilファイルとMakefileは前回と同じ内容のものを使います。ただしファイル名を修正してください。
motor1.c
#include "kernel.h" #include "kernel_id.h" #include "ecrobot_interface.h" DeclareTask(Task1); /* Task1を宣言 */ void ecrobot_device_initialize(){ /* OSEK起動時の処理(モータ停止)*/ nxt_motor_set_speed(NXT_PORT_B,0,1); nxt_motor_set_speed(NXT_PORT_C,0,1); } void ecrobot_device_terminate(){ /* OSEK終了時の処理(モータ停止)*/ nxt_motor_set_speed(NXT_PORT_B,0,1); nxt_motor_set_speed(NXT_PORT_C,0,1); } void user_1ms_isr_type2(void){} TASK(Task1) { //2秒前進 nxt_motor_set_speed(NXT_PORT_B,60,1); nxt_motor_set_speed(NXT_PORT_C,60,1); systick_wait_ms(2000); //1秒停止 nxt_motor_set_speed(NXT_PORT_B,0,1); nxt_motor_set_speed(NXT_PORT_C,0,1); systick_wait_ms(1000); //2秒後退 nxt_motor_set_speed(NXT_PORT_B,-60,1); nxt_motor_set_speed(NXT_PORT_C,-60,1); systick_wait_ms(2000); //1秒停止 nxt_motor_set_speed(NXT_PORT_B,0,1); nxt_motor_set_speed(NXT_PORT_C,0,1); display_string("THAT'S ALL !"); /* メッセージを表示する */ display_update(); TerminateTask(); /* 処理終了 */ } |
このプログラムの解説をします。
nxt_motor_set_speed(NXT_PORT_B, 60, 1);
systick_wait_ms(2000);
この関数はNXTの出力ポートBのモータのパワー(=モータの動作電圧)の大きさを指定する命令で、ここではPWM制御の duty比を 60% に指定しています。
また、モータのフロートモード(解放)とブレーキモードについては、例えばMindstoms RCX ブレーキ制御調査を参照して下さい。
走行時のブレーキモードとフロートモードは停止時とは異なる意味を持ちますが、それについてはPWM制御の実験のページを参照して下さい。 ここではモータ停止時(PWM値をゼロに指定する場合)も走行時(0以外のPWM値を指定する場合)は常にブレーキモード 1 を使用することにします。
- 一番目の引数をNXT_PORT_Aにすると出力ポートAに、NXT_PORT_Cにすれと出力ポートCのモータに指令を与えます。
- 二番目の引数の値を変えることでパワー(正確にはduty比)を指定します。 指定できる値は-100から100で、+側で正回転,-側で逆回転となります。
- 三番目の引数で 0(フロートモード) か 1(ブレーキモード)を指定します。
また、モータのフロートモード(解放)とブレーキモードについては、例えばMindstoms RCX ブレーキ制御調査を参照して下さい。
走行時のブレーキモードとフロートモードは停止時とは異なる意味を持ちますが、それについてはPWM制御の実験のページを参照して下さい。 ここではモータ停止時(PWM値をゼロに指定する場合)も走行時(0以外のPWM値を指定する場合)は常にブレーキモード 1 を使用することにします。
systick_wait_ms(2000);
2000msec = 2sec 動作を待機させます。
プログラムのコンパイル・転送・実行を参考にプログラムをダウンロードし、動作させて下さい。
Makefile で変更を必要とするのは、TARGET名と、TARGET_SOUCES のファイル名です。TOPPERS_OSEK_OIL_SOURCESの指定は変更しないで下さい。その際、TARGET名やTARGET_SOUCESのファイル名の後ろに、space コードが入っているとコンパイルエラーになるので注意して下さい。
また、このプログラムをそのまま動作させると、直進するはずがどちらに曲がってしまうかもしれません。 これは左右のモータの個体差により、同じduty比の指定を行っても、それぞれのモータのトルクが異なり、結果的にモータの回転速度が異なってしまうからです。 そのような場合は左右のモータのduty比を調整して、直進するようにさせる必要があります。
これで走行体を真っ直ぐに前進・後退させることができます。
3.正方形を描くように動作させる
次に、走行体が正方形を描くように動作するプログラムを作成します。この動作を実現するには『 前進→90度回転→前進→… 』という動作の繰り返しが必要になります。
繰り返し動作を行うにはfor文を用います。
また90度回転させるために何秒間その動作を続けるのかが重要となります。
正方形の一辺の距離が指定された場合は、同様に直進動作を継続する時間を調整する必要があります。
それでは次のプログラムを作成してください。ここでは作成プログラムをmotor2.cとします。
以下のプログラムでは上記の回転時間と直進時間をマクロ変数(TURN\_TIMEとMOVE\_TIME)で与えています。
このプログラムを回転時間を適当に与えていますのので、正確に90度回転させるためには、回転時間(TURN_TIME)を調整する必要があります。 また、同様に指定された距離を直進するようにするには前進時間(MOVE_TIME)の調整を行う必要があります。
そのようなパラメータ調整を行う場合は、直接数値を与えるよりも、変数を定義してその値を調整するようにした方がプログラムが見やすくなります。またその値を使う場所が複数ある場合は一か所の変更で済むため効率的です。 そのため、このプログラムの場合は wait1Msec()の引数を、変数(この場合はマクロ変数)で与えるうにしています。
それでは次のプログラムを作成してください。ここでは作成プログラムをmotor2.cとします。
以下のプログラムでは上記の回転時間と直進時間をマクロ変数(TURN\_TIMEとMOVE\_TIME)で与えています。
motor2.c
#include "kernel.h" #include "kernel_id.h" #include "ecrobot_interface.h" #define TURN_TIME 220 /* 回転時間を指定するマクロ */ #define MOVE_TIME 750 /* 直進時間を指定するマクロ */ #define STOP_TIME 100 DeclareTask(Task1); /* Task1を宣言 */ void ecrobot_device_initialize(){ /* OSEK起動時の処理(モータ停止)*/ nxt_motor_set_speed(NXT_PORT_B,0,1); nxt_motor_set_speed(NXT_PORT_C,0,1); } void ecrobot_device_terminate(){ /* OSEK終了時の処理(モータ停止)*/ nxt_motor_set_speed(NXT_PORT_B,0,1); nxt_motor_set_speed(NXT_PORT_C,0,1); } void user_1ms_isr_type2(void){} TASK(Task1) { int i; for(i=0;i<4;i++){ //直進 nxt_motor_set_speed(NXT_PORT_B,60,1); nxt_motor_set_speed(NXT_PORT_C,60,1); systick_wait_ms(MOVE_TIME); //停止 nxt_motor_set_speed(NXT_PORT_B,0,1); nxt_motor_set_speed(NXT_PORT_C,0,1); systick_wait_ms(STOP_TIME); //回転 nxt_motor_set_speed(NXT_PORT_B,-40,1); nxt_motor_set_speed(NXT_PORT_C,40,1); systick_wait_ms(TURN_TIME); //停止 nxt_motor_set_speed(NXT_PORT_B,0,1); nxt_motor_set_speed(NXT_PORT_C,0,1); systick_wait_ms(STOP_TIME); } nxt_motor_set_speed(NXT_PORT_B,0,1); nxt_motor_set_speed(NXT_PORT_C,0,1); display_string("THAT'S ALL !"); /* メッセージを表示する */ display_update(); TerminateTask(); /* 処理終了 */ } |
このプログラムを回転時間を適当に与えていますのので、正確に90度回転させるためには、回転時間(TURN_TIME)を調整する必要があります。 また、同様に指定された距離を直進するようにするには前進時間(MOVE_TIME)の調整を行う必要があります。
そのようなパラメータ調整を行う場合は、直接数値を与えるよりも、変数を定義してその値を調整するようにした方がプログラムが見やすくなります。またその値を使う場所が複数ある場合は一か所の変更で済むため効率的です。 そのため、このプログラムの場合は wait1Msec()の引数を、変数(この場合はマクロ変数)で与えるうにしています。
なお、この値(時間)は一度調整しても電池の消耗度合によって変わってくるので、調整後時間を置いてしまうと再調整が必要になる場合があることに留意して下さい。
4.課題
1.motor1.c を用いて、走行体がほぼ直進するように左右のモータのduty比を調整する。
2.motor2.c を用いて、MOVE_TIMEとTURN_TIMEおよび左右のduty比を調整して、一辺が45cmの正方形を描く走行を実現する。このとき、(少なくても)直進部では1のduty比の調整結果も用いること。
2.motor2.c を用いて、MOVE_TIMEとTURN_TIMEおよび左右のduty比を調整して、一辺が45cmの正方形を描く走行を実現する。このとき、(少なくても)直進部では1のduty比の調整結果も用いること。