7月15日 こうしろうがMinervaロボットのプログラムを入力する。




#define TURNAROUND_TIME 395
int i;
task main() {
 SetSensor(SENSOR_3,SENSOR_LIGHT);
 SetPower(OUT_A+OUT_C,OUT_FULL);

 calibrate();
 i = 0;
 while (i < 5){
  retrieve();
  i += 1;
 }
 Off(OUT_A+OUT_C);
}
#define NUMBER_OF_SAMPLES 10
int runningTotal;
int threshold;
sub calibrate() {
 //Take an average light reading.
 i = 0;
 runningTotal = 0;
 while (i < NUMBER_OF_SAMPLES) {
  runningTotal += SENSOR_3;
  Wait(10);
  i += 1;
 }
 threshold = runningTotal / NUMBER_OF_SAMPLES;
}

void grab() {
 // Run the moter until we hit the limit switch.
 OnFwd(OUT_A);
 until(SENSOR_3 == 100);
 // Back off from the switch.
 OnRev(OUT_A);
 until(SENSOR_3 != 100);
 Off(OUT_A);
}

void release() {
 // Run the moter until we hit the limit switch.
 OnRev(OUT_A);
 until (SENSOR_3 == 100);
 // Back off from the switch.
 OnFwd(OUT_A);
 until (SENSOR_3 != 100);
 Off(OUT_A);
}
int returnTime;

sub retrieve() {
 // Drive forward until we see something.
 OnFwd(OUT_C);
 ClearTimer(0);
 until(SENSOR_3 < threshold - 3);
 Wait(20); // Move up on it a little.
 returnTime = Timer(0);
 Off(OUT_C);

 grab();

 // Trun around(roughly).
 OnRev(OUT_C);
 Wait(TURNAROUND_TIME);

 // Drive back.
 OnFwd(OUT_C);
 ClearTimer(0);
 until(Timer(0) >= returnTime);
 Off(OUT_C);
 release();

 //Turn around.
 OnRev(OUT_C);
 Wait(TURNAROUND_TIME);


 中学生になって,英単語を入力するスピードが,かなり速くなったこうしろうである。

 さて,今回のプログラムは説明のしがいがある。まず,mainタスクでは,SetSensor命令で入力ポート3につないであるセンサーがライトセンサーであるとRCXに教えている(実は,タッチセンサーも入力ポート3につながっているのであるが,それは後述する)。次にSetPower命令でA,C双方のモーターをフルパワーに設定している。とは言っても,タイヤとモーターの連動にはウォームギヤを介しているのでロボットはゆっくりと前進する。もう一方のアームを動かすモーターはプーリーで回転を伝えている。

 calibrateというサブルーチンでは,ライトセンサーが返す値を10回取得し,その平均値を求めている。このロボットは床に落ちているものを見つけ拾うのであるが,あらかじめ何もない状態で床が返す光の反射量の平均値を計算しているのである。(かしこい!)

 whileで5回繰り返されるretrieveサブルーチンがこのプログラムのメインとなる処理である。まず,Minervaはゆっくりと前進する。ClearTimer命令でタイマー0を初期化しているのは,何かを見つけるまでにかかった移動時間を求めるためだ。

 平均値(threshold)を下回る値をライトセンサーが返したら,(until(SENSOR_3 < threshold - 3);の部分)grab関数を呼び出す。grab関数はアームを動かし,物をつかむ。同時にアーム下部に配置したカムがアーム自体を押し上げる。この動作はSENSOR_3が100を返すまで続けられる(until (SENSOR_3 == 100);)。この関数内のSENSOR_3はライトセンサーではなく,アームと本体の衝突を感知するタッチセンサーである。タッチセンサーは押された状態では100を返す。「どうして,1つのポートにライトセンサーとタッチセンサー付けられるのかな,こうしろう」,「うーん。」答えは,タッチセンサーは押されない限り,ライトセンサーが返す値に何も影響を与えないから,らしい。

 grab関数で何かをつかみ持ち上げた後,定数TURNAROUND_TIMEで定義された時間,Minervaは旋回する。床の材質を考慮し180度回転するようにTURNAROUND_TIMEを調整すれば,Minervaは出発地点に帰ってくる。タイマー0で計った時間分,戻ってくるからだ。帰ってきたら,release関数を実行し,拾ってきたものを床に置くのだ。

 長文にお付き合いいただきありがとうございました。画像を見れば,即納得(^^)



今から,出発します。



ケチャップを見つけ,拾い上げました。



旋回しています。



戻ってきて,ケチャップを降ろしました。