目次 #contents *課題説明 [#tf0f6ee4] 今回の課題は、紙に書かれた黒い線の上をなぞって進み、途中置かれている紙コップをつかみ指定の場所まで移動させゴールするという課題である。 *コース [#i3b3d179] #ref(2017b/Member/Masa/Mission2/ko-su.jpg,75%,コースの画像) このコースを使ってライントレースする。3つの経路のうち私は第1コースとなった。 第1コース -1. Aをスタート -2. Bを直進 -3. Cを右折 -4. Fを直進 -5. Rを左折(一時停止) -6. Pを直進 -7. X地点の紙コップを取得してコースに戻る -8. Qを左折 -9. Sを直進(一時停止) -10. Y地点に紙コップを置いてコースに戻る -11. Sを直進(一時停止) -12. Fを左折(一時停止) -13. Cを右折(一時停止) -14. D地点へ(ゴール) また、コースを作りで線を黒く塗るときに真ん中が一番黒くなるようにした。 *ロボット概要 [#bc29bc06] **ロボット本体 [#l1f7fb7f] #ref(2017b/Member/Masa/Mission2/torekitai1.jpg,150%,機体全体の画像) 今回は、前回の課題1のときより動く距離が長いためできるだけ小さくする方がよいと考えた。なので、動作に問題がなければ細かいところでしっかり固定したりはしないようにした。 **センサーについて [#k2fbf3a3] #ref(2017b/Member/Masa/Mission2/sensorkakudo.jpg,150%,センサーの取り付け角度) 最初センサーの値の計測をしたときに少し角度がつくようにして計測したためそのままセンサーは地面に対して少し角度がつくように取り付けた。試しに地面に垂直に取り付けてみたが、値が角度をつけたときと大きく変わって低くなり、変化する幅も小さくなったため難しそうだと判断した。(センサーと地面が近すぎだけかもしれない) **紙コップを取る機構 [#t91751e3] 紙コップを取るには紙コップを取れる位置まで移動しないといけないが、その調整が大変そうだったので紙コップの方を移動させることにした。 &ref(2017b/Member/Masa/Mission2/kamicp1.jpg,150%,紙コップを捕まえる工夫); 機体の前についた棒にはまるように紙コップを移動させ &ref(2017b/Member/Masa/Mission2/kamicp2.jpg,150%,紙コップをつかむ); 紙コップをつかむ *プログラムについて [#aa137803] **定義 [#mb6c9767] #define speedA 28 //モーターAの出力 #define speedB 26 //モーターBの出力 #define Cpower 20 //モーターCの出力 #define THRESHOLD 50 //しきい値 #define STEP 1 //1回の判定で進む時間 #define sA2 speedA/2 //Aの出力1/2 #define sB2 speedB/2 //Bの出力1/2 #define sA3 speedA/3 //Aの出力1/3 #define sB3 speedB/3 //Bの出力1/3 #define sA4 speedA/4 //Aの出力1/4 #define sB4 speedB/4 //Bの出力1/4 パワーが大きいと動きが速くなり反応しないことがあったので少し小さめにした **サブルーチン [#fd36586f] sub go_forward(int x,int y) //前進 { OnFwd(OUT_A,speedA-x);OnFwd(OUT_B,speedB-y); } sub go_back(int x,int y) //後進 { OnFwd(OUT_A,-speedA-x);OnFwd(OUT_B,-speedB-y); } sub go_right1(int x,int y) //右の車輪を軸に右へ { OnFwd(OUT_B,speedB-y);Off(OUT_A); } sub go_left1(int x,int y) //左の車輪を軸に左へ { OnFwd(OUT_A,speedA-x);Off(OUT_B); } sub go_right2(int x,int y) //その場で右へ { OnFwd(OUT_A,-speedA-x);OnFwd(OUT_B,speedB-y); } sub go_left2(int x,int y) //その場で左へ { OnFwd(OUT_A,speedA-x);OnFwd(OUT_B,-speedB-y); } 関数のx,yに数値を入れるとその分だけ遅くすることができるようにしてある。 sub gogo_b(int x,int y) //黒い線まで前進 { while (SENSOR_1 > THRESHOLD -9){ go_forward(x,y); Wait(STEP); } PlayTone(523,50); } sub gogo_w(int x,int y) //白い線まで前進 { while (SENSOR_1 < THRESHOLD -9){ go_forward(x,y); Wait(STEP); } PlayTone(523,50); } sub lele(int x,int y) //黒い線まで左回転 { while (SENSOR_1 < THRESHOLD -9){ go_left1(x,y); Wait(STEP); } PlayTone(523,50); } センサーが指定された値を読み取るまで動くようにした。また、動作が終わると音が鳴る。 sub r_left(int x,int y) //右側で左カーブ { int n = 0; while (n<400){ if (SENSOR_1 < THRESHOLD -13) { go_right2(x,y);n=n+1; } else if (SENSOR_1 < THRESHOLD -9) { go_forward(x,y);n=n+1; } else if (SENSOR_1 < THRESHOLD +10) { go_left1(x,y); } else { go_left2(x,y);n=0; } Wait(STEP); } PlayTone(587,50); } sub l_right(int x,int y) //左側で右カーブ { int n = 0; while (n<300){ if (SENSOR_1 < THRESHOLD -15) { go_left2(x,y);n=0; } else if (SENSOR_1 < THRESHOLD -13) { go_left1(x,y); } else if (SENSOR_1 < THRESHOLD -9) { go_forward(x,y);n=n+1; } else if (SENSOR_1 < THRESHOLD +10) { go_right1(x,y); } else { go_right2(x,y);n=0; } Wait(STEP); } PlayTone(587,50); } sub r_right(int x,int y) //右側で右カーブ { int n = 0; while (n < 300){ if (SENSOR_1 < THRESHOLD -15) { go_right2(x,y); n=0; } else if (SENSOR_1 < THRESHOLD -13) { go_right1(x,y); } else if (SENSOR_1 < THRESHOLD -9) { go_forward(x,y); n=n+1; } else if (SENSOR_1 < THRESHOLD +10) { go_left1(x,y); } else { go_left2(x,y); n=0; } Wait(STEP); } PlayTone(587,50); } sub l_straight1(int x,int y) //左側で直進1 { int n = 0; while (n<300){ if (SENSOR_1 < THRESHOLD -15) { go_left1(x,y);n=0; } else if (SENSOR_1 < THRESHOLD) { go_forward(x,y); } else { go_right1(x,y);n=n+1; } Wait(STEP); } PlayTone(523,50); } sub l_straight2(int x,int y) //左側で直進2 { int n = 0; while (n<300){ if (SENSOR_1 < THRESHOLD -15) { go_left1(x,y);n=n+1; } else if (SENSOR_1 < THRESHOLD) { go_forward(x,y); } else { go_right2(x,y);n=0; } Wait(STEP); } PlayTone(523,50); } sub l_straight3(int x,int y) //左側で直進3 { int n = 0; while (n < 250){ if (SENSOR_1 < THRESHOLD -15) { go_left1(x,y);n=n+1; } else if (SENSOR_1 < THRESHOLD -9) { go_forward(x,y); } else { go_right1(x,y);n=0; } Wait(STEP); } PlayTone(523,50); } sub l_straight4(int x,int y) //左側で直進4 { int n = 0; while (n<300){ if (SENSOR_1 < THRESHOLD -15) { go_left1(x,y);n=0; } else if (SENSOR_1 < THRESHOLD - 9) { go_forward(x,y); } else { go_right2(x,y);n=n+1; } Wait(STEP); } PlayTone(523,50); } sub r_straight1(int x,int y) //右側で直進1 { int n = 0; while (n < 300){ if (SENSOR_1 < THRESHOLD -13) { go_right2(0,0); n=n+1; } else if (SENSOR_1 < THRESHOLD) { go_forward(x,y); } else { go_left1(x,y); n=0; } Wait(STEP); } PlayTone(523,50); } sub r_straight2(int x,int y) //右側で直進2 { int n = 0; while (n < 300){ if (SENSOR_1 < THRESHOLD -13) { go_right2(0,0); n=0; } else if (SENSOR_1 < THRESHOLD) { go_forward(x,y); } else { go_left1(x,y); n=n+1; } Wait(STEP); } PlayTone(523,50); } sub r_straight3(int x,int y) //右側で直進3 { int n = 0; while (n < 300){ if (SENSOR_1 < THRESHOLD -13) { go_right1(0,0); n=0; } else if (SENSOR_1 < THRESHOLD) { go_forward(x,y); } else { go_left1(x,y); n=n+1; } Wait(STEP); } PlayTone(523,50); } sub r_straight4(int x,int y) //右側で直進4 { int n = 0; while (n < 250){ if (SENSOR_1 < THRESHOLD -13) { go_right2(0,0); n=n+1; } else if (SENSOR_1 < THRESHOLD) { go_forward(x,y); } else { go_left1(x,y); n=0; } Wait(STEP); } PlayTone(523,50); } sub l_w() //白くなるまで左へ1 { int n = 0; while (n<50){ if (SENSOR_1 < THRESHOLD +15) { go_left1(sA4,sB4); } else { go_left1(sA4,sB4);n=n+1; } Wait(STEP); } PlayTone(659,50); } sub l_w2() //白くなるまで左へ2 { int n = 0; while (n<50){ if (SENSOR_1 < THRESHOLD +15) { go_left2(sA4,sB4); } else { go_left1(sA4,sB4);n=n+1; } Wait(STEP); } PlayTone(659,50); } sub l_w3() //白くなるまで左へ3 { int n = 0; while (n<150){ if (SENSOR_1 < THRESHOLD +15) { go_left1(sA4,sB4); } else { go_left1(sA4,sB4);n=n+1; } Wait(STEP); } PlayTone(659,50); } sub r_w() //白くなるまで右へ1 { int n = 0; while (n<50){ if (SENSOR_1 < THRESHOLD +15) { go_right1(sA4,sB4); } else { go_right1(sA4,sB4);n=n+1; } Wait(STEP); } PlayTone(659,50); } sub r_w2() //白くなるまで右へ2 { int n = 0; while (n<50){ if (SENSOR_1 < THRESHOLD +15) { go_right2(sA4,sB4); } else { go_right1(sA4,sB4);n=n+1; } Wait(STEP); } PlayTone(659,50); } sub r_b() //黒くなるまで右へ1 { int n = 0; while (n<50){ if (SENSOR_1 > THRESHOLD - 9) { go_right1(sA4,sB4); } else { go_right1(sA4,sB4);n=n+1; } Wait(STEP); } PlayTone(659,50); } sub r_b2() //黒くなるまで右へ2 { int n = 0; while (n<50){ if (SENSOR_1 > THRESHOLD - 9) { go_right2(sA4,sB4); } else { go_right1(sA4,sB4);n=n+1; } Wait(STEP); } PlayTone(659,50); } sub l_b() //黒くなるまで左へ1 { int n = 0; while (n<50){ if (SENSOR_1 > THRESHOLD - 9) { go_left1(sA4,sB4); } else { go_left1(sA4,sB4);n=n+1; } Wait(STEP); } PlayTone(659,50); } sub l_b2() //黒くなるまで左へ2 { int n = 0; while (n<50){ if (SENSOR_1 > THRESHOLD - 9) { go_left2(sA4,sB4); } else { go_left1(sA4,sB4);n=n+1; } Wait(STEP); } PlayTone(659,50); } このライントレースでは、5段階または3段階で明るさを評価した。また、真ん中を一番黒くしているので線の右側を走るのと左側を走るプログラムを作った。ライントレースの方法は5段階もしくは3段階にわけた中にカウントを増やすプログラムとカウントをリセットするプログラムを作り、そのライントレースのプログラムで設定したカウント以上になるまでトレースし続けるというものにした。また、プログラムが終わると音が鳴るようにしてある。 sub c_ca() //紙コップをつかむ { OnFwd(OUT_C,Cpower);Wait(1100); Off(OUT_C); } sub c_re() //紙コップを放す { OnFwd(OUT_C,-Cpower);Wait(1100); Off(OUT_C); } **本文 [#mb4a6e33] 最初は枠の内側の右寄りに置いてスタートする。 task main() { SetSensorLight(S1); //端子1に光センサー gogo_b(0,0); //最初の枠から出る gogo_w(0,0); lele(0,0); r_straight1(0,0); //Bまで l_w(); //進路修正 r_straight1(0,0); //Cまで r_w(); r_straight1(0,0); //Fまで l_w(); //進路修正 ↑枠からでた後のトレースは右側を通っていきBのまがり角では黒の上にいる時間が多くなりプログラムが終了する。そのあとに白いところまで出ていきまたトレースを始める。 r_straight2(0,0); r_left(sA3,sB3);//カーブ1 l_w();//車線変更 l_straight4(0,0); PlayTone(523,50); l_right(sA3,sB3);//カーブ2 long t0 = CurrentTick(); while (CurrentTick() - t0 < 10000){ if (SENSOR_1 < THRESHOLD -15) { go_left1(0,0); } else if (SENSOR_1 < THRESHOLD -9) { go_forward(0,0); } else { go_right2(0,0); } Wait(STEP); } PlayTone(880,100); l_straight2(sA2,sB2); Off(OUT_AB);//Rまで Wait(1000); l_w(); //進路修正 l_straight2(0,0); r_w();//Pまで r_b(); ↑カーブは外側のラインをトレースしたかったので1つ目のカーブを曲がったあとに左側に車線変更している。また、Eの角を曲がるためにwhile文で一定の時間はライントレースさせ続けるようにした。 r_w2(); r_b2(); Off(OUT_AB);Wait(300); go_forward(0,0);Wait(500);Off(OUT_AB); c_ca(); //紙コップを取る Off(OUT_AB);Wait(300); go_back(0,0);Wait(450);Off(OUT_AB); go_left2(0,0);Wait(1500); //コースに戻る ↑これは、紙コップを回収するプログラムで、機体を回転させ棒で紙コップをよせてから回収している。 l_straight2(0,0); PlayTone(880,100); l_w3();//Qまで long t1 = CurrentTick(); while (CurrentTick() - t1 < 2000){ if (SENSOR_1 < THRESHOLD -15) { go_left1(0,0); } else if (SENSOR_1 < THRESHOLD -9) { go_forward(0,0); } else { go_right1(0,0); } Wait(STEP); } PlayTone(880,100); l_straight3(0,0); Off(OUT_AB);Wait(1000);//Sまで r_w(); //進路変更 r_straight3(0,0); r_straight4(0,0); ↑途中のwhile文はそこの部分の色の塗り方の問題でうまく反応しなかったため一定の時間トレースするようにしている。また、カーブをトレースするプログラムがうまくいかなかったので直進用に作ったプログラムを入れてみるとうまくいったのでそのまま使っている。 r_w2(); r_b2(); r_w2(); go_right2(0,0);Wait(800); Off(OUT_AB);Wait(300); c_re(); //紙コップを放す Off(OUT_AB);Wait(300); l_b2(); go_forward(0,0);Wait(1200); //コースに戻る go_left2(0,0);Wait(1800); ↑紙コップを放すプログラム。棒を取り付けた影響で紙コップを置いた後決まった方にしか回ることができなかった。 r_straight4(0,0); Off(OUT_AB);Wait(1000);//Sまで l_w(); //進路変更 l_straight3(sA4,sB4); Off(OUT_AB);Wait(1000);//Fまで l_w(); //進路変更 r_straight1(0,0); Off(OUT_AB);Wait(1000);//Cまで gogo_w(0,0); l_straight2(0,0); gogo_w(0,0); go_right2(0,0);Wait(750); //枠の中に入れる go_forward(0,0);Wait(1200); Off(OUT_AB); PlayTone(880,200); //ゴール } ↑最後に枠の中にゴールするまでのプログラム。ここではライントレースをしてゴールするだけなのでこれまでと違ったところはなかったが、1ヶ所安定しないところがあったので速度を遅くした。また、最後に枠の中に入れるところは時間で動かした。 *結果 [#x24738f3] 本番では、電池の消耗でプログラムがうまく動かず最初はダメだったが2回目ではうまく動いてくれた。電池が消耗しても速さを変えることで完璧にする予定だったが直前でうまく調整できなかったのが残念だった。 *感想 [#ld31eb27] 今回の課題ではカーブを曲がるところが難しく自分たちで作ったコースの色の塗り方が雑だったためカーブを上手く曲がれないことがあり苦戦した。もっと丁寧にコースを作るべきだったと後悔した。トレースのプログラム自体を途中で変えたので無駄な作業時間が多くとても時間がかかった。しかし、作業をしているときはそれほど時間を感じず楽しくできたし、達成感も大きかった。次の課題は期間が短くまた忙しい時期ではあるけれど、最後までしっかりやりきりたいと思う。