でかい、おもい、とろい、の三拍子そろった素敵な造形。 路面の状況が悪いと、自重により前進が困難になる。 アームを動かすためのギアが大きいため、必然的にロボット全体が巨大化した。 重量があるため、機動性が著しく悪い。
先代の反省を生かし、ギアボックスのダウンサイジングを行い、また、それに伴いアーム自体の構造も、両手でつかむような構造から、片手でつかむようなものへ変更した。
さらなる軽量化、小型化を求め、ついにギアボックスを排除し、アームをモーターに直結するという奇抜なアイディアにより生み出された完成形
図のように3つの区間に分けて考えた。 プログラムの概要としては、ライントレースをするタスク、超音波センサーのタスク、メインタスクの3つと、缶をつかんで排除する動作のサブルーチンといった3つタスクと1つのサブルーチンによって構成されている。
#define MS OnFwd(OUT_C,33);OnRev(OUT_B,33); #define HS OnFwd(OUT_B,33);OnRev(OUT_C,33); #define right OnFwd(OUT_B,30);OnRev(OUT_C,30); #define left OnRev(OUT_B,30);OnFwd(OUT_C,30); #define right2 OnFwd(OUT_B,40);OnRev(OUT_C,0); #define left2 OnRev(OUT_B,0);OnFwd(OUT_C,40); #define right3 OnFwd(OUT_B,40);OnRev(OUT_C,40); #define left3 OnRev(OUT_B,40);OnFwd(OUT_C,40); #define SHIKI 50
right,leftの1,2,3は、それぞれ区間の1,2,3に対応している。
sub arm() { Off(OUT_BC); PlaySound(SOUND_UP); Wait(2000); RotateMotor(OUT_A,-75,90);//アーム開く Off(OUT_A); OnFwdSync(OUT_BC,30,0); Wait(1600);//ちょい進む Off(OUT_BC); RotateMotor(OUT_A,75,90);//アームでつかむ Off(OUT_A); MS;Wait(2800);//右旋回 Off(OUT_BC); OnRevSync(OUT_BC,35,0); Wait(2700);//持ったままちょい下がる Off(OUT_BC); RotateMotor(OUT_A,-75,90);//アーム開く OnRevSync(OUT_BC,30,0); Wait(1500);//はなしてちょい下がる Off(OUT_BC); HS;Wait(2800);//左旋回 Off(OUT_BC); RotateMotor(OUT_A,75,90);//アームを閉じる OnRevSync(OUT_BC,40,0);Wait(700); }
缶を排除する一連の動作は複雑なので、ひとつのサブルーチンとしてまとめた。
task line() { long t0=CurrentTick(); PlaySound(SOUND_DOWN); Wait(2000);
区間1のヘアピンカーブを曲がり切れるように、ライントレース時の左右のモータの出力を等しくして、旋回に近い動きをできるようにしている。
while(CurrentTick()-t0<=13000){ if(SENSOR_2<SHIKI-12){ right; }else if(SENSOR_2<SHIKI){ OnFwd(OUT_BC,30); }else{ left; } Wait(1); } PlaySound(SOUND_CLICK);
上で定めた区間2では交差点が2つある。この2つを認識して直進する必要があるのだが、センサー位置とモータの出力を以下の様に調節することにより、交差点を直進することを可能にした。
while(CurrentTick()-t0<45000){ if(SENSOR_2<SHIKI-12){ right2; }else if(SENSOR_2<SHIKI){ OnFwd(OUT_BC,40); }else{ left2; } Wait(1); } PlaySound(SOUND_CLICK);
区間2の交差点を直進するモータの出力では、区間3の90度のカーブを認識できないので、左右のモータの出力を近づけて、急なカーブでも曲がり切れるように調整した。
while(CurrentTick()-t0<1000000){ if(SENSOR_2<SHIKI-12){ right3; }else if(SENSOR_2<SHIKI){ OnFwd(OUT_BC,25); }else{ left3; } Wait(1); } PlaySound(SOUND_CLICK); }
task sonic() { while(true){ if(SensorUS(S1)<20){ stop line; arm(); start line; } } }
障害物が20cm以内に近づくと、ライントレースの タスクを終了させ、障害物(缶)を排除するサブルーチンを開始する。
task main() { SetSensorLowspeed(S1); SetSensorLight(S2); start sonic; start line; }
メインタスク。 超音波のタスクとライントレースのタスクを並列して走らせている。
今回の課題で、基本的に私はプログラミングの担当をしたわけだが、最大の難関はプログラム自体を軽量化する事であった。ひとつひとつは単純なプログラムでも、それが積み重なることで、予想しないようなところで不具合が起きたり、命令が競合してしまうような事が何度も起き、作業の多くの時間をデバッグ等に割いたわけだが、ただ単純にプログラムの無駄な部分を探したり、まとめたりするだけではどうしても限界があり、そこでハードの面でも調整をしてもらい、何とか課題をクリアすることができた。どこまでを本体の改良で、どこからをプログラミングでというのは非常に難しい線引きではあるが、その点で私は相方に恵まれたので、心置きなくプログラムを最小限まで単純化し、結果として双方のバランスをとることができた。