ピンポン玉と紙コップを別々に回収して所定の場所に運ぶ。
詳しくは⇒ 課題3
紙コップをY地点で重ねるのは難しいと感じたので紙コップを重ねながらピンポン玉をX地点に置きに行き、最後に3つ重ねた紙コップをY地点に置く、という構想である。この構想では紙コップを重ねることができ、時間も短縮できるが、一つでも紙コップを掴めなかったらプログラミングが狂ってしまうというリスクがある。よって正確性が非常に重要となる。
今回の課題では紙コップを持ち上げて重ねることが必要となるため、紙コップをつかむアーム部分をエレベーター式で真上に上げることができるようにした。真上に上げることで安定して紙コップを重ねることができる。モーターは、アームの掴む部分、アームの上下、前輪右、前輪左の4つに利用した。
アーム部分では紙コップを掴み続ける必要があるので白いギアを用いた。このギアは必要以上の力が加わると、本体ではなく中が回るようになるので、アームに無理な力を加えずに掴み続けることができる。
写真の赤いギザギザ線のところがかみ合う。実際にモーターとつながっているギアは上のギアだけであり、下のギアはアーム部分を安定させる役割を果たしている。
紙コップを探すのとライントレースをするのに光センサーを用いた。前のセンサーで紙コップを探し、下向きのセンサーでライントレースをする。紙コップは認識しやすいように黒く塗りつぶした。
モーターを多く用いるのでRISを二台用いて通信できるようにした。RISを背中合わせの状態で通信すると上手く通信できないことが分かったので、縦に並べるようにした。
始めは紙コップをなかなか掴むことができず苦戦したが、光センサーの前に写真のような棒をつけることで、紙コップの位置を調整し、確実にアームの前に持ってくることができた。 この部分によって紙コップをつかむ、重ねる動作に確実性がかなり増した。
RISを2台用いたので今回は送信側(土台の車部分とつながっているほう)と受信側(アームとつながっているほう)という名前で区別した。(結局どちらのRISも送信、受信は行う...) また、必要のないプログラムがあったり、整理できなかった部分がある。
まず以下のように定義した。
#define GO_AHEAD 10 //使わなかった。 #define MOTION_END 20 //使わなかった。 #define OWARI 30 //使わなかった。 #define CYOI 40 //実際に使用したメッセージ #define mae(w) ;OnRev(OUT_AC);Wait(w);Off(OUT_AC); //前にw秒進む #define zennsinn OnRev(OUT_AC); //前進 #define usiro(g) OnFwd(OUT_AC);Wait(g);Off(OUT_AC); //後ろにg秒進む #define SHIKIICHI 870 //紙コップを探す用のしきい値 #define migisennkai(s) set_power_L;OnFwd(OUT_A);OnRev(OUT_C);Wait(s);Off(OUT_AC); #define hidarisennkai(n) set_power_L;OnFwd(OUT_C);OnRev(OUT_A);Wait(n);Off(OUT_AC); #define shikiichi 48 //ライントレース用のしきい値 #define turn_left1 set_power_L;OnFwd(OUT_A);OnRev(OUT_C); //左旋回 #define turn_right1 set_power_L;OnRev(OUT_A);OnFwd(OUT_C); //右旋回 #define turn_left2 set_power_L;Off(OUT_A);OnRev(OUT_C); //左に回る #define turn_right2 set_power_L;Off(OUT_C);OnRev(OUT_A); //右に回る #define LOWPOWER 1 #define HIGHPOWER 4 //使わなかった。 #define set_power_H SetPower(OUT_AC,HIGHPOWER); //使わなかった。 #define set_power_L SetPower(OUT_AC,LOWPOWER);
次にサブルーチンを用いて様々なプログラムを作成した。 まず、2つ目の紙コップを見つけるためのプログラムである。
sub search3() { SetSensor(SENSOR_1,SENSOR_LIGHT); SetSensorMode(SENSOR_1,SENSOR_MODE_RAW); //光センサーの精度を上げる while(SENSOR_1 < SHIKIICHI -40){ //明るさが830以上になるまで前に進む mae(10); //前に進む時間を長くしすぎると紙コップに 当たってしまう } Off(OUT_AC); Wait(100); hidarisennkai(20); Wait(100); mae(30); //紙コップを見つけてから左旋回、前進を行うことで Wait(300); 位置を調整する。 ClearMessage(); SendMessage(OWARI); //いらなかった。 }
次に3つ目の紙コップを見つけるプログラムである。基本的には上と同じである。
sub search4() { SetSensor(SENSOR_1,SENSOR_LIGHT); SetSensorMode(SENSOR_1,SENSOR_MODE_RAW); while(SENSOR_1 < SHIKIICHI -40){ mae(020); migisennkai(010); //ここを前進、右旋回にすることで曲がりながら } 紙コップを見つける。 Off(OUT_AC); Wait(100); hidarisennkai(20); Wait(100); mae(30); Wait(300); ClearMessage(); SendMessage(OWARI); //いらない }
次にライントレースのプログラムである。課題2で用いたプログラムを再利用した。
sub line_l() //5.5秒間ライントレース { SetSensor(SENSOR_2,SENSOR_LIGHT); ClearTimer(0); while(FastTimer(0)<=550){ if(SENSOR_2 < shikiichi -7){ turn_right2; } else if (SENSOR_2 < shikiichi -4 ){ turn_right2; } else if (SENSOR_2 < shikiichi -1){ zennsinn; } else if (SENSOR_2 < shikiichi ){ turn_left2; } else { turn_left2; } } PlaySound(SOUND_CLICK); Off(OUT_AC); }
sub line_ll() //3秒間ライントレース { SetSensor(SENSOR_2,SENSOR_LIGHT); ClearTimer(0); while(FastTimer(0)<=300){ if(SENSOR_2 < shikiichi -7){ turn_right1; } else if (SENSOR_2 < shikiichi -4 ){ turn_right2; } else if (SENSOR_2 < shikiichi -1){ zennsinn; } else if (SENSOR_2 < shikiichi ){ turn_left2; } else { turn_left1; } } PlaySound(SOUND_CLICK); Off(OUT_AC); }
次のプログラムは障害物となる紙コップを見つけるのとライントレースを同時に行っている。
sub line_lll() { SetSensor(SENSOR_2,SENSOR_LIGHT); ClearTimer(0); while(SENSOR_1 < SHIKIICHI -40){ //紙コップを見つけるまでライントレースを行う。 if(SENSOR_2 < shikiichi -7){ turn_right1; } else if (SENSOR_2 < shikiichi -4 ){ turn_right2; } else if (SENSOR_2 < shikiichi -1){ zennsinn; } else if (SENSOR_2 < shikiichi ){ turn_left2; } else { turn_left2; } } PlaySound(SOUND_CLICK); Off(OUT_AC); }
次は障害物を避けるプログラムである。
sub shougaibutsu() { SetSensor(SENSOR_1,SENSOR_LIGHT); SetSensorMode(SENSOR_1,SENSOR_MODE_RAW); while(SENSOR_1 < SHIKIICHI -130){ mae(10); } //この部分は前のプログラムですでに紙コップを見つけて いるので必要なかった。 Off(OUT_AC); Wait(100); usiro(200); //後ろに下がり障害物を避ける。 Wait(300); ClearMessage(); SendMessage(OWARI); //いらない }
成功すると↑のように紙コップをよけることができる。
次は交差点判断のためのプログラム。一回しか使用しないが、ここで交差点を判断できないとすべて狂ってしまうので、確実に判断する必要がある。
sub line_k() { SetSensor(SENSOR_2,SENSOR_LIGHT); ClearTimer(0); while(FastTimer(0)<=25){ //左旋回が0.25秒以下ならライントレースを続ける if(SENSOR_2 < shikiichi-6){ turn_right1; } else if (SENSOR_2 < shikiichi -4){ turn_right2; ClearTimer(0); } else if (SENSOR_2 < shikiichi -1){ zennsinn; ClearTimer(0); } else if (SENSOR_2 < shikiichi ){ turn_left2; ClearTimer(0); } else { turn_left2; ClearTimer(0); } } PlaySound(SOUND_CLICK); Off(OUT_AC); }
次がメインのプログラムである。かなり長くなってしまった。送受信の後に書いてある番号は受信側(アーム側)と対応している。1つ目の紙コップは直線上にあるためセンサーを使わずに見つけた。
task main() { SetSensor(SENSOR_1,SENSOR_LIGHT); SetSensorMode(SENSOR_1,SENSOR_MODE_RAW); mae(050); line_l(); Wait(100); mae(40); //1つめの紙コップの前まで移動 SendMessage(CYOI);//1 Wait(50); mae(30); migisennkai(250); line_ll(); line_k(); hidarisennkai(140); //X地点の前まで移動 SendMessage(CYOI);//2 ClearMessage(); until(Message() == CYOI);//3 mae(160); Wait(100); ClearMessage(); SendMessage(CYOI);//4 until(Message() == CYOI);//4.5 usiro(180); ClearMessage(); hidarisennkai(100); line_lll(); shougaibutsu(); //障害物をよける migisennkai(60); search3(); //2つ目の紙コップを見つける mae(030); Wait(100); SendMessage(CYOI);//5 until(Message() == CYOI);//6 SendMessage(CYOI);//7 migisennkai(150); mae(050); //X地点の前まで移動 SendMessage(CYOI);//8 ClearMessage(); until(Message() == CYOI);//9 usiro(060); Wait(50); ClearMessage(); hidarisennkai(120); mae(300); migisennkai(050); mae(060); search4(); //3つ目の紙コップを見つける Wait(50); mae(020); migisennkai(040); mae(020); SendMessage(CYOI);//10 until(Message() == CYOI);//11 ClearMessage(); usiro(100); migisennkai(180); mae(080); SendMessage(CYOI);//12 until(Message() == CYOI);//13 ClearMessage(); mae(130); //X地点の前まで移動 SendMessage(CYOI);//14 until(Message() == CYOI);//15 ClearMessage(); usiro(100); migisennkai(280); mae(030); //Y地点の前まで移動 SendMessage(CYOI);//16 until(Message() == CYOI);//17 usiro(070); //紙コップを放した後、紙コップに当たらないように下がる }
まず、以下のように定義した。
#define GO_AHEAD 10 //使わなかった。 #define MOTION_END 20 //使わなかった。 #define OWARI 30 //使わなかった。 #define CYOI 40 //実際に使用したメッセージ #define tsukamu OnFwd(OUT_C); //アームを閉じる #define hanasu Off(OUT_C); //アームの力を0にする #define ageru OnFwd(OUT_B); Wait(230); Off(OUT_B); //アーム部分を上げる #define sageru OnRev(OUT_B); Wait(160); Off(OUT_B); //アーム部分を下げる #define up(z) OnFwd(OUT_B); Wait(z); Off(OUT_B); //アーム部分をz秒上げる #define down(y) OnRev(OUT_B); Wait(y); Off(OUT_B); //アーム部分をy秒下げる #define hiraku OnRev(OUT_C); Wait(008);Off(OUT_C); //アーム部分を開く
アームの力を0にすることで紙コップを離すことはできるが、最後のY地点で離すとき、それだけだときれいに離すことができないので「hiraku」を作った。
次にメインのプログラム。送信側と対応している。
task main() { until(Message() == CYOI);//1 tsukamu; //1つ目の紙コップを掴む ClearMessage(); until(Message() == CYOI);//2 ClearMessage(); up(30); //少し紙コップを上げることで割りばしとの接触を避け Wait(100); る SendMessage(CYOI);//3 until(Message() == CYOI);//4 up(180); //X地点で紙コップを上げる ClearMessage(); SendMessage(CYOI);//4.5 until(Message() == CYOI);//5 down(180); //2つ目の紙コップに1つ目の紙コップを重ねる ClearMessage(); SendMessage(CYOI);//6 ClearMessage(); until(Message() == CYOI);//7 up(50); //少し紙コップを上げることで割りばしとの接触を ClearMessage(); 避ける until(Message() == CYOI);//8 Wait(100); down(50); //少し下に押し付けしっかりと紙コップを重ねる Wait(100); hanasu; //一回離してから掴むことでさらにしっかりと紙コップ Wait(100); を重ねる tsukamu; Wait(50); up(200); //X地点で紙コップを上げる ClearMessage(); SendMessage(CYOI);//9 ClearMessage(); until(Message() == CYOI);//10 ClearMessage(); Wait(100); sageru; //3つ目の紙コップに重ねる SendMessage(CYOI);//11 until(Message() == CYOI);//12 down(040); //下に押し付けしっかりと紙コップを重ねる up(050); ClearMessage(); SendMessage(CYOI);//13 until(Message() == CYOI);//14 down(030); //さらに下に押し付けしっかりと紙コップを重ねる up(100); //X地点で紙コップを上げる ClearMessage(); SendMessage(CYOI);//15 until(Message() == CYOI);//16 down(050); hiraku; //Y地点で紙コップを離す SendMessage(CYOI);//17 }
紙コップをしっかりと重ねないと途中で落ちてしまうので、紙コップを重ねた状態で下に押し付ける ことで安定して重ねることができた。
↓X地点に入る前に紙コップを少し上げることでピンポン玉だけ割りばしの中に入れることが可能になる。
基本点30点 技術点19.7点 計49.7点 第一位!!
今回の課題は試験期間と重なり、実際に課題のために動き始めたのは本番の5日前だった。かなり苦戦したが、前回、前々回の課題での経験を活かし何とか本番に間に合わせることができた。本番前に上手く動かなくなるというハプニングもあったが、結果としては優勝することができ、同じグループの仲間と苦労した甲斐があったなと感じた。また、本番前の調整は非常に重要であると感じた。大学に入ってから一番忙しい授業だったがとてもいい経験になった。