前回まででON-OFF制御器を作成し、その挙動をパラメータによって調整できるようにしました。ラインを捉えることはできるものの、前に進んでいませんでした。今回から前に進むようにします。
前進しながら左右方向に旋回もするという動作をわかりやすく記述するため、今回からMtr_Run関数に左右の車輪の速度(モーターのduty比)を明示的に書くのではなく、「前進速度」と「回転速度」とに分けて指定するようにします。サンプルプログラムではrunという関数がこれを行います。
void run(int speed, int turn_speed) { int d1 = speed - turn_speed; // (1) int d2 = speed + turn_speed; // 絶対値が127(100%)を超えないようにする (2) // duty比が0のとき、Mtr_Runに渡す数は0x80にしてブレーキ動作にする if(d1 > 127) d1 = 127; else if(d1 < -127) d1 = -127; else if(d1 == 0) d1 = 0x80; // brake
(3)
if(d2 > 127) d2 = 127; else if(d2 < -127) d2 = -127; else if(d2 == 0) d2 = 0x80; // brake Mtr_Run(-d1, d2, 0, 0); // (4) }
(1)の部分で左右の車輪の速度を計算します。
例えば前進速度80、回転速度30の時は左右の車輪の速度は上の計算式よりそれぞれ50、110となります。こうすると左に旋回しながら前進することになります。
(4)では実際にMtr_Run関数を呼び出してモーターの出力を変えます。左右の車輪でモーターは逆向きになるので1番目の引数は-d1として回転方向を逆、つまりd1が正のとき左モーターがロボットを前進させる方向に回るようにしています。このあたりはロボットの機械設計と電気配線に合わせて変更する必要があります。 ※とはいえ実は旋回速度や前進速度に負の値を設定することでつじつまあわせができてしまいますが。 run(80, 30)とすると最終的に、Mtr_Run(-50, 110, 0, 0)を実行することになります。
(2)は、speed=100、turn_speed=100のような大きな値を指定した時にd1やd2の値が127を超えてしまう場合、127で頭打ちにするための処理です。マイナス方向も同様です。頭打ちにした場合、厳密には回転速度、前進速度ともに希望した値になりません。ゆっくり走る場合は影響しませんが、留意しておいてください。
(3)はMtr_Runの仕様上の特別処理です。第3回 の余談として書いたことですが、Mtr_Runの仕様では0はフリー、0x80はブレーキとなっているのでd1やd2の計算結果が0になったときは0x80に直します。
このrun関数を使うとON-OFF制御によるライントレース部分はこのように書けます。なお、speedという変数を追加してあります。旋回も直進も第1引数が共通になっていることに注目してください。
if(line_pos < -deadband) { // ラインが左側にあるとき
run(speed, turn_speed); // 左回転(反時計回り)しながら進む
} else if(deadband < line_pos) { // ラインが右側にあるとき
run(speed, -turn_speed); // 右回転(時計回り)しながら進む
} else { // ラインが大体真ん中にあるとき
run(speed, 0); // まっすぐ進む
}
使い方は前回とほぼ同じです。パラメータ調整画面に前進速度speedを追加し、また上の説明を反映してline_trace関数の仕様を変更しました。第3引数に前進速度speedを指定するようになっています。
パラメータを変えて挙動の違いを見てください。Aギア(減速比12.7:1)、電源4.8Vの条件で試したところではspeedが30くらいまではうまく走ることができました。
ラインから外れた場合の処理は入っていません。コースからある程度以上外れると大抵は直進して暴走しますので気をつけてください。本来は線から外れたら停止するか、線に復帰するようにすべきです。本講座でも余裕があれば後からいくつかの方法を説明します。
次回はPID制御の考え方を取り入れたライントレースについて説明します。
山口辰久