左センサ値をフィードバック制御し,壁から5cm〜10cmの距離を維持するように制御してみよ.基準値よりも壁に少し近づいたようならば左モータの速度を少し下げて,微妙に左へカーブをかけ,逆に壁から離れたようなら左モータの速度を微妙に上げて右へカーブをかけるようにする.そのような関数followLeft()を作成せよ.
int followLeft(int msec10, int sensor_thold); //引数は走行時間の指定(10ミリ秒単位)と,センサの基準値
ただし,forward()と同様に,もしも指定時間が0ならば無限に動作しつづけるものとする.
followLeft()の内部では,壁からの距離を調整するのにsencor.cで用意されているreadSensor()が利用できる.
前センサ ● ●範囲内であれば点灯 左センサ● ●右センサ
また、センサ値の反応が基準値の±10程度の場合に、ロボットに搭載したLED4個のうち,緑のLEDが点灯させるようにしておくとデバッグしやすい。また、followLeftの内部で、readSensor()だけでなく、checkSensor()を呼び出せば、それ以外の3個のLEDも点灯させられる。
次のプログラム例を参考にすること。
extern unsigned int optledbuf; // sensor.cの中で定義されているLED点灯用の変数
int followLeft(int msec, int sensor_thold)
{
int sensor, left, diff;
int target_R, target_L;
forward(1); //まず全速前進
for(;;)
{
wait()と同様の枠組みをここに書く。
指定時間が経過した→return 0;
sensor = checkSensor(sensor_thold-10); //壁からの距離を示す基準値
if(前方センサに反応があった)
return -1;
left = readSensor(2); //左センサ
diff = left - sensor_thold; // 基準値からの差
操作量 = diff や diffの累積値や前回のdiff値を使用してPIDの式
target_R = dutydata_R + 操作量;
target_L = dutydata_L - 操作量;
//dutydata_Rとdutydata_Lは、driveMotorで設定された現在のデューティを格納してある大域変数(課題7参照)
//右モータと左モータの片方を操作量だけ早くし、もう片方を操作量だけ遅くする。→ロボットを操作量の分だけカーブさせる
// 操作量はマイナスの値になる場合もある。その時は逆方向にカーブする。
driveMotor(target_R, target_L, sensor_thold-10);
if( -10 ≤ diff && diff ≤ 10 ) //もしもセンサ値の差が-10〜10の範囲内ならLEDを点灯
{
optledbuf = 0x00; //点灯
}
else
{
optledbuf = 0x08; //消灯
}
}
]
比例定数Kpは、適当に設定して調整せよ。最初は、次を参考にKpの桁を合わせること。
Kpの値を桁数を変化させて、大きすぎ→小さすぎ(または小さすぎ→大きすぎ)になった間のKpが目的の定数付近を示す。そうなったら後はKpの値を微調整せよ。
緊急停止は,次の関数を用意して呼び出せばよい.
int emergencyStop()
{
p1=ブレーキ
p3=ブレーキ
ta2 = モータ速度をいきなり0に
ta3 = モータ速度をいきなり0に
SetCpuBoardLED( ON );// CPUボードLED点灯
wait()でしばらく待機(※これがないと,LEDがすぐ消灯して気づかない)
SetCpuBoardLED( OFF );// CPUボードLEDオフ
}
SetCpuBoardLED()は,sensor.cの中に最初から用意されていた関数で,CPUボード上のLEDを制御する機能を提供している.