次のいずれかのコースで黒い線に沿って動き、350mlの空き缶(黄色で表示)を移動させるロボットを製作せよ.そのためロボットに光センサーとアームを取り付けた.
1.AをスタートしCで交差点を認識して止まる 2.CをスタートしDで交差点を認識して止まる 3.Xから缶を取る 4.DをスタートしGで交差点を認識して止まる 5.GからスタートしてHで交差点を認識して止まる 6.HをスタートしてJで交差点を認識して止まる 7.Yに缶を置く 8.JをスタートしてAに戻る
上の写真のとおりである
一回目の課題で特にロボットに工夫を凝らさず,プログラミングを作ることが非常にてこずったため,今度はロボットにも力を入れプログラミングがなるべく楽になるようにした.
光センサーの位置を二つのタイヤの真ん中に取り付け,さらに回転軸にも近づけた.
そのことによりロボットが回転しても,センサーの位置のブレが少なく急なカーブも曲がることができるようになった
正直このかだいのなかで一番難しかったのがアームである.
小さすぎても入らないし,大きすぎても重くなり動きが悪くなってしまう.
作っては作り直しを繰り返し今の形に至った.
アームを上下させ缶をとらえる.
まず#defineで必要なものを定義した
動くためのプログラミングを5つ定義したことで滑らかな動きをすることを実現することができた.
#define gehen1 OnFwd(OUT_B,40);OnFwd(OUT_C,-30); //左に大きく動く #define gehen2 OnFwd(OUT_B,30);OnFwd(OUT_C,-20); //左に少し動く #define gehen3 OnFwd(OUT_B,40);OnFwd(OUT_C,40); //まっすぐ動く #define gehen4 OnFwd(OUT_B,-20);OnFwd(OUT_C,30); //右に少し動く #define gehen5 OnFwd(OUT_B,-30);OnFwd(OUT_C,40); //右に大きく動く #define STEP 1
ちなみにgehenとはドイツ語で行くという意味である
最初は光センサーが黒と認識したら右,白と認識したら左と二つしか動きを設定していなかった.
しかし,それだけだと時間がかなりかかり無駄も多い.そのため動きを上で挙げたように5つ設定し,改良した.
「線の中心の黒」「線の中心と端の間の黒」「線の端」「端と白の間」「白紙」.この五つに分けた
改良したため無駄が省かれ滑らかな動きをすることが可能になった.
交差点に差し掛かった時,必ず一番黒が濃い真ん中を通る.そのためその一番濃い部分を通る時間を計測してその時間が設定した秒数より多くなった時に止まるように設定した
細かくはそれぞれのプログラミングで説明する
下のプログラミングはwhile()の中の条件が満たされる限り永遠に繰り返される
下のプログラミングの中で置かれているzeitはドイツ語で時間という意味である
task main () { SetSensorLight(S3); while(true) } if(SENSOR_3<30)//センサーが30以下の値をとるときgehen1する { gehen1; } else if(SENSOR_3<35)//センサーが35以下の値をとるときgehen2する { gehen2; } else if(SENSOR_3<45)//センサーが45以下の値をとるときgehen3する { gehen3; } else if(SENSOR_3<53)//センサーが53以下の値をとるときgehen4する { gehen4; } else//センサーが54以上の値をとるときgehen5する { gehen5; } Wait(STEP); } Off(OUT_BC); }
task main () { SetSensorLight(S3); while(true) { if(SENSOR_3<30)//センサーが30以下の値をとるときgehen5する { gehen5; } else if(SENSOR_3<35)//センサーが35以下の値をとるときgehen4する { gehen4; } else if(SENSOR_3<45)//センサーが45以下の値をとるときgehen3する { gehen3; } else if(SENSOR_3<53)//センサーが53以下の値をとるときgehen2する { gehen2; } else//センサーが54以上の値をとるときgehen1する { gehen1; } Wait(STEP); } Off(OUT_BC); }
task main () { SetSensorLight(S3); int zeit = 0; while(zeit<100)//zeitが0.1秒記録されたらwhile()を終了 { if(SENSOR_3<30) { gehen1; zeit++;//zeitを計測開始 } else if(SENSOR_3<35) { gehen2; zeit = 0;//zeitの記録をリセット } else if(SENSOR_3<45) { gehen3; zeit = 0;//zeitの記録をリセット } else if(SENSOR_3<53) { gehen4; zeit = 0;//zeitの記録をリセット } else { gehen5; zeit = 0;//zeitの記録をリセット } Wait(STEP); } Off(OUT_BC); zeit = 0;//zeitの記録をリセット }
gehen1の状態で0.1秒動いたら止まる
task main () { SetSensorLight(S3); int zeit = 0; while(zeit<100) { if(SENSOR_3<30) { gehen5; zeit++; } else if(SENSOR_3<35) { gehen4; zeit = 0; } else if(SENSOR_3<45) { gehen3; zeit = 0; } else if(SENSOR_3<53) { gehen2; zeit = 0; } else { gehen1; zeit = 0; } Wait(STEP); } Off(OUT_BC); zeit = 0; }
gehen5の状態で0.1秒で動いたら止まる
全体のプログラムは上で説明した「軸となるプログラミング」を用いて,交差点を通る順番に沿って製作した.
下で製作してあるそれぞれのプログラミングをすべてサブルーチンで置くことで task main() の中のプログラミングを非常に楽にすることができた.
「左側を認識して,交差点を認識する」プログラミングを使用した.
次に前に進みたいので一時停止した後,傾きを戻した.
gehen1を0,1秒記録したら交差点と認識して止まる.
基本線の左側をライントレースさせる
task main () { SetSensorLight(S3); int zeit = 0; while(zeit<100) { if(SENSOR_3<31) { gehen1; zeit++; } else if(SENSOR_3<35) { gehen2; zeit = 0; } else if(SENSOR_3<45) { gehen3; zeit = 0; } else if(SENSOR_3<53) { gehen4; zeit = 0; } else { gehen5; zeit = 0; } Wait(STEP); } Off(OUT_BC); Wait(1000);//交差点を認識して一秒と止まる gehen5;//少し傾きを戻す Wait(100); gehen3; Wait(150); Off(OUT_BC); zeit = 0; }
CからDにかけて一回直角カーブがあるのでそこで一度交差点と認識し,回転させてからまたライントレースを開始させ,Dで止まるようにした.
gehen2を0,2秒記録したら直角カーブだと認識し,左側をライントレースできるようにすすむ
次にgehen2を0,1秒記録したら交差点だと認識し止まる
基本線の左側をライントレースさせる.
task main () { SetSensorLight(S3); int zeit = 0; while(zeit<200) { if(SENSOR_3<30) { gehen1; zeit = 0; } else if(SENSOR_3<35) { gehen2; zeit++; } else if(SENSOR_3<45) { gehen3; zeit = 0; } else if(SENSOR_3<53) { gehen4; zeit = 0; } else { gehen5; zeit = 0; } Wait(STEP); } Off(OUT_BC); zeit = 0; gehen1; Wait(1000); while(zeit<100) { if(SENSOR_3<30) { gehen1; zeit = 0; } else if(SENSOR_3<35) { gehen2; zeit++; } else if(SENSOR_3<45) { gehen3; zeit = 0; } else if(SENSOR_3<53) { gehen4; zeit = 0; } else { gehen5; zeit = 0; } Wait(STEP); } Off(OUT_BC); zeit = 0; }
少し前にうごかし,アームを下げて戻ってくる
task main() { OnFwd(OUT_BC,30);//前に進む Wait(500); Off(OUT_BC); OnFwd(OUT_A,20);//アームを下げる Wait(700); Off(OUT_A); OnRev(OUT_BC,30);//元の位置に戻る Wait(500); Off(OUT_BC); }
これも基本的に左をライントレースさせる.
一度交差点を横切るがその時にプログラミングを次に進めるようにしている.
gehen1を0,1秒記録したら交差点と認識して止まる
task main () { gehen1; Wait(1000); SetSensorLight(S3); int zeit = 0; while(zeit<100) { if(SENSOR_3<30) { gehen1; zeit++; } else if(SENSOR_3<35) { gehen2; zeit++; } else if(SENSOR_3<45) { gehen3; zeit = 0; } else if(SENSOR_3<53) { gehen4; zeit = 0; } else { gehen5; zeit = 0; } Wait(STEP); } Off(OUT_BC); zeit = 0; gehen4; Wait(400); Off(OUT_BC); while(zeit<100) { if(SENSOR_3<30) { gehen1; zeit++; } else if(SENSOR_3<35) { gehen2; zeit++; } else if(SENSOR_3<45) { gehen3; zeit = 0; } else if(SENSOR_3<53) { gehen4; zeit = 0; } else { gehen5; zeit = 0; } Wait(STEP); } Off(OUT_BC); zeit = 0; gehen1; Wait(600); while(zeit<100) { if(SENSOR_3<30) { gehen1; zeit++; } else if(SENSOR_3<35) { gehen2; zeit = 0; } else if(SENSOR_3<45) { gehen3; zeit = 0; } else if(SENSOR_3<53) { gehen4; zeit = 0; } else { gehen5; zeit = 0; } Wait(STEP); } Off(OUT_BC); zeit = 0; gehen3; Wait(200); Off(OUT_BC); }
このコースは急カーブが二つ存在し曲がりきることができないので,一度右側からライントレースし,二回目の急カーブでラインを横断させ右側でライントレースさせている.
そうすることにより急カーブをさせることに成功させた.
一度目の急カーブでgehen5を0,1秒記録したら交差点だと認識し止まる
次に少し移動してgehen1を0,1秒記録したら交差点だと認識して止まる
task main () { SetSensorLight(S3); int zeit = 0; while(zeit<100) { if(SENSOR_3<31) { gehen5; zeit++; } else if(SENSOR_3<35) { gehen4; zeit++; } else if(SENSOR_3<45) { gehen3; zeit = 0; } else if(SENSOR_3<53) { gehen2; zeit = 0; } else { gehen1; zeit = 0; } Wait(STEP); } Off(OUT_BC); zeit = 0; gehen5; Wait(800); Off(OUT_BC); while(zeit<100) { if(SENSOR_3<31) { gehen5; zeit++; } else if(SENSOR_3<35) { gehen4; zeit = 0; } else if(SENSOR_3<45) { gehen3; zeit = 0; } else if(SENSOR_3<53) { gehen2; zeit = 0; } else { gehen1; zeit = 0; } Wait(STEP); } Off(OUT_BC); zeit = 0; gehen3; Wait(300); while(zeit<100) { if(SENSOR_3<30) { gehen1; zeit++; } else if(SENSOR_3<35) { gehen2; zeit = 0; } else if(SENSOR_3<45) { gehen3; zeit = 0; } else if(SENSOR_3<53) { gehen4; zeit = 0; } else { gehen5; zeit = 0; } Wait(STEP); } Off(OUT_BC); zeit = 0; } }
二回交差点を通過するので,そこで止まらないようにプログラミングを作った 一回目はgehen5を0,15秒記録したら交差点だと認識して次に進む 二回目もgehen5を0,15秒記録したら交差点だと認識して次に進む 最後にgehen5を0,15秒記録したら交差点だと認識して止まる
task main () { SetSensorLight(S3); int zeit = 0; while(zeit<150) { if(SENSOR_3<30) { gehen5; zeit++; } else if(SENSOR_3<35) { gehen4; zeit = 0; } else if(SENSOR_3<45) { gehen3; zeit = 0; } else if(SENSOR_3<53) { gehen2; zeit = 0; } else { gehen1; zeit = 0; } Wait(STEP); } Off(OUT_BC); zeit = 0 gehen3; Wait(300); Off(OUT_BC); while(zeit<150) { if(SENSOR_3<30) { gehen5; zeit++; } else if(SENSOR_3<35) { gehen4; zeit = 0; } else if(SENSOR_3<45) { gehen3; zeit = 0; } else if(SENSOR_3<53) { gehen2; zeit = 0; } else { gehen1; zeit = 0; } Wait(STEP); } Off(OUT_BC); zeit = 0 gehen3; Wait(300); while(zeit<150) { if(SENSOR_3<30) { gehen5; zeit++; } else if(SENSOR_3<35) { gehen4; zeit = 0; } else if(SENSOR_3<45) { gehen3; zeit = 0; } else if(SENSOR_3<53) { gehen2; zeit = 0; } else { gehen1; zeit = 0; } Wait(STEP); } Off(OUT_BC); zeit = 0 }
まず機体を直角に回転させ,中心まで行き,缶を離して元に戻る
task main() { OnFwd(OUT_B,50); OnRev(OUT_C,50); Wait(430); Off(OUT_BC); OnFwd(OUT_BC,40); Wait(380); Off(OUT_BC); OnRev(OUT_A,30); Wait(500); Off(OUT_A); OnRev(OUT_BC,40); Wait(380); Off(OUT_BC); }
まず進行方向に対して後ろを向いているので180度回転させ,左側をライントレースさせた後,Bの直角を認識して少し曲がりその後も左側を認識しAまで戻る. 直角交差点でgehen2を0,2秒記録したら交差点だと認識して,左側をライントレースする Aに戻るときにgehen2を0,1秒記録したら交差点と認識し,Aの中に入る
task main() { OnFwd(OUT_B,40); OnRev(OUT_C,40); Wait(800); SetSensorLight(S3); int zeit = 0; while(zeit<200) { if(SENSOR_3<30) { gehen1; zeit = 0; } else if(SENSOR_3<35) { gehen2; zeit++; } else if(SENSOR_3<45) { gehen3; zeit = 0; } else if(SENSOR_3<53) { gehen4; zeit = 0; } else { gehen5; zeit = 0; } Wait(STEP); } Off(OUT_BC); zeit = 0; gehen1; Wait(1000); while(zeit<100) { if(SENSOR_3<30) { gehen1; zeit = 0; } else if(SENSOR_3<35) { gehen2; zeit++; } else if(SENSOR_3<45) { gehen3; zeit = 0; } else if(SENSOR_3<53) { gehen4; zeit = 0; } else { gehen5; zeit = 0; } Wait(STEP); } Off(OUT_BC); gehen3; Wait(500); zeit = 0; }
うえで説明したプログラムをすべてサブルーチンで置き換えることにより下のようになる.
task main() { AC(); CD(); tukamu; DG(); GH(); HJ(); hanasu; JA(); }
率直な感想,ここまで時間がかかるとは思わなかった.
今回は機体の製作にもちからを入れたことより,プログラミングづくりが非常に楽であった.
しかし,楽といっても時間はかなりかかり,空きコマや放課後をうまく使い仕上げた.
微妙な調整やプログラミング同士をつなぎあわせることに一番時間がかかった.
次回の課題では機体も工夫しつつ,より効率の良い方法を探していきたい.