コース上に配置された空き缶をGOALの位置に多く積むというもの。
走行中はアームを高位置に固定させ、ライトセンサで缶を見つけたらアームを下ろし缶を掴み、そのままアームを上げて進む。
次に別の缶を見つけたらその上に缶を置き、アームを下ろして下の缶を掴む。そしてまたアームを上げて進む。
これを繰り返すことで缶をいくつも積んだ状態で運ぶことが可能となる。
アームのモーターのパワーを調整していった結果、安定して4個まで積み上げることが出来た。
重心がかなり前に来るため、駆動輪は前に設置。
今回は上図の左半分のエリアの缶の回収を目標とする。
#define OPEN 1 // 缶を発見したことを知らせる #define GO 2 // 缶を掴んだことを知らせる #define PUT 3 // GOALに到着したことを知らせる #define BACK 4 // GOALに缶を置いたことを知らせる #define THERESHOLD 47 // 閾値 #define HIGHPOWER 3 // 直進用パワー #define LOWPOWER 2 // カーブ用パワー #define set_power_H SetPower(OUT_AC,HIGHPOWER); #define set_power_L SetPower(OUT_AC,LOWPOWER); #define go_forward set_power_H; OnRev(OUT_AC); // 直進 #define turn_left1 set_power_L; OnFwd(OUT_A); OnRev(OUT_C); // 左旋回 #define turn_left0 set_power_L; OnRev(OUT_C); Off(OUT_A); // 左折 #define turn_right0 set_power_L; OnRev(OUT_A); Off(OUT_C); // 右折 #define turn_right1 set_power_L; OnFwd(OUT_C); OnRev(OUT_A); // 右旋回 #define STEP 1 #define nMAX 35 // 通常のカーブとみなす時間の上限 #define short_break Off(OUT_AC); Wait(100); // 小休止 #define cross_line go_forward set_power_H; OnFwd(OUT_AC); Wait(20); short_break; // 交差点通過
task main() { SetSensor(SENSOR_1,SENSOR_LIGHT); SetSensor(SENSOR_3,SENSOR_LIGHT); int nOnline=0; ClearTimer(1);
最初の缶へは直進で向かう。
while (FastTimer(1) <= 500) { go_forward; if (SENSOR_3 > 48) { // 缶を発見 SendMessage(OPEN); // アームを動かすように指示 Off(OUT_AC); } until (Message() == GO); // アームの動作が終了したら go_forward; // 再び直進 }
開始から5秒経ったらライトセンサが黒線上に来るので、ライントレースを開始させる。
交差点の判別には前回と同様に、黒を連続で認識する時間の上限を設定する方法を採用。
又、これより交差点を判別する際に、カウンタが1進む。
ClearTimer(0); while (true) { while (FastTimer(0) < nMAX) { if (SENSOR_1 < THERESHOLD -4) { turn_right1; } else { if (SENSOR_1 < THERESHOLD -2) { turn_right0; } else if (SENSOR_1 < THERESHOLD +2) { go_forward; } else if (SENSOR_1 < THERESHOLD +4) { turn_left0; } else { turn_left1; } // ライントレース ClearTimer(0); } Wait(STEP); } turn_left1; Wait(nMAX*STEP); cross_line; // 交差点を判別・通過 nOnline++; // カウンタを進める PlaySound(SOUND_CLICK); ClearTimer(0); if (SENSOR_3 > 48) { SendMessage(OPEN); // 缶を発見 Off(OUT_AC); } (*) until (Message() == GO); // アームの動作が終了したら while (FastTimer(0) < nMAX) { // ライントレース再開 if (SENSOR_1 < THERESHOLD -4) { turn_right1; } else { if (SENSOR_1 < THERESHOLD -2) { turn_right0; } else if (SENSOR_1 < THERESHOLD +2) { go_forward; } else if (SENSOR_1 < THERESHOLD +4) { turn_left0; } else { turn_left1; } ClearTimer(0); } Wait(STEP); } turn_left1; Wait(nMAX*STEP); cross_line; // 交差点を判別・通過 nOnline++; PlaySound(SOUND_CLICK); ClearTimer(0); if (SENSOR_3 > 48) { // 缶を発見 SendMessage(OPEN); // アームを動かすように指示 Off(OUT_AC); }
交差点を8回判別したとき、ロボットは左側のコースを1周し、GOALの位置に到達している。
(黒線の左側を走るため、右側のエリアに繋がる丁字路も交差点とみなしている。)
if (nOnline == 8) { OnFwd(OUT_A); OnRev(OUT_C); // ロボットの向きを調整 Wait(70); SendMessage(PUT); // 缶を置くように指示 }
上のプログラムは(*)の位置に入る。
缶が置かれたら、少し後退して終了。
until (Message() == BACK); OnRev(OUT_AC); Wait(100); } }
#define OPEN 1 #define GO 2 #define PUT 3 #define BACK 4 #define PowerA SetPower(OUT_A,0); // アームを開ける為のパワー #define PowerB SetPower(OUT_A,7); // アームを閉じ、缶を掴み続ける為のパワー #define PowerC SetPower(OUT_C,0); // アームを下ろすのと、アームを上で固定する為のパワー #define PowerD SetPower(OUT_C,10); // アームを上げる為のパワー
アームの開閉用モーターはA、昇降用モーターはCに接続。
task main() { ClearMessage(); while (true) { PowerC; OnFwd(OUT_C); // アームを上に固定する為、常にモーターを上に回す until (Message() == OPEN); // 缶を発見したら PowerA; OnRev(OUT_A); // アームを開く Wait(40); PowerC; OnRev(OUT_C); // アームを下ろす Wait(90); PowerB; OnFwd(OUT_A); // アームを閉じる Wait(40); PowerD; OnFwd(OUT_C); // アームを上げる Wait(160); SendMessage(GO); // ライントレースを再開するように指示 PowerC; OnFwd(OUT_C); // 再びアームを上に固定し続ける
until (Message() == PUT); // GOALに到着したら PowerC; OnRev(OUT_C); // アームを下ろす Wait(50); PowerA; OnRev(OUT_A); // アームを開く Wait(40); SendMessage(BACK); // 少し後退するように指示 } Wait(10); }
尚、ここには書いていないが、缶を取ったら、FC用ゲームソフト「メトロイド」のアイテムゲット音が鳴るようにプログラムを入れてある。
(♪桃屋のキムチは良いキムチ〜)
今回、私はロボットの重量や重心等のことを考えずに、前回と同じように走行プログラムを書いてしまったので、
最後までロボットがうまくライントレースできないままで仕様を大幅にカットせざるを得なくなってしまった。
(最初に直進して缶を掴み、そのまま直進し続けてGOALに缶を1個置いて終了することとなった。)
なので私ももっと組み立てに関わり、ロボットの構造をよく理解したうえでライントレース用プログラムを書けたらと思った。
3班の皆さん本当スミマセン。そして、ありがとうございました。