[[2019a/Member]]
#contents
*課題3 [#j79b8fec]
#ref(2019a/Member/aoto/Mission3/2019a-mission3.png,80%,robot)
上のコースの上に置かれたピンポン玉を掴んでコースの左側のトレーの中に入れるロボットを作る.
フィールドの説明、ルールについては[[2019a/Mission3]]を参照
*作戦 [#bef88d2d]
まずポイントの大きいかごの中のボールを運ぶように狙いを絞った。
2個目以降のボールは試行することができなかった。

*ロボット [#v464a713]
**全体 [#t5fed61c]
#ref(2019a/Member/aoto/Mission3/003.jpg,80%,robot)
コンセプトはコンパクトである。部品を最小に抑え、かつ左右対称と見た目も美しく仕上がった(^^)
**光センサー [#ibb787a5]
#ref(2019a/Member/aoto/Mission3/001.jpg,80%,robot)
課題2では前輪よりも後ろに取り付けたため、うまくライントレースすることができなかった。今回はその反省を生かして前輪上に取り付けるように意識した。
**アーム [#rbb793a8]
#ref(2019a/Member/aoto/Mission3/002.jpg,80%,robot)
アームはモーターを2つ使った。上げ下げと掴む離すである。
上げ下げはマジックアームの要領である。頂点を1点接合した四角形を使い、モーターの回転によって上下に動くようにした。
掴む離すはモーターに直接ギアを付け、モーター外に同じギアを付けてさらにギア同士を噛み合わせることで左右に同じだけ広げることができるようにした。
*プログラム [#r075f150]
今回はモーターを4つ使用したため2台の本体をBluetoothを用いて連動させた。
ライントレースなど移動の操作を"master"、アームの操作を"slave"として動作させる。

**定義(master) [#m28cd119]
まず以下のように定義をした
 #define black 34                                 //完全に黒のときの値
 #define white 52                                 //完全に白のときの値
 #define CONN 1                                   //スレイブの番号
 #define SIGNAL1 11                               //スレイブとやり取りする信号の番号                            
 #define SIGNAL2 12                               //同上
 #define SIGNAL3 13                               //同上
 #define SIGNAL4 14                               //同上
 #define migi0 OnFwd(OUT_C,33);OnFwd(OUT_B,18);   //右折
 #define hidari0 OnFwd(OUT_B,33);OnFwd(OUT_C,18); //左折
 #define migi1 OnFwd(OUT_C,36);OnRev(OUT_B,18);   //右旋回
 #define hidari1 OnFwd(OUT_B,36);OnRev(OUT_C,18); //左旋回
 #define migi2 OnFwd(OUT_C,40);OnRev(OUT_B,20);   //右急旋回
 #define hidari2 OnFwd(OUT_B,40);OnRev(OUT_C,30); //左急旋回
 #define tyokusinn OnFwd(OUT_BC,35);              //直進
 #define kousinn OnRev(OUT_BC,35);                //後進
**定義(slave) [#f6560474]
 #define SIGNAL1 11                       //masterに合わせる
 #define SIGNAL2 12
 #define SIGNAL3 13
 #define SIGNAL4 14
 #define tukamu OnRev(OUT_A,20);Wait(800);//ボールを掴む
 #define hanasu OnFwd(OUT_A,20);Wait(300);//ボールを落とす
 #define up OnFwd(OUT_B,50);Wait(1800);   //アームを上げる
 #define down OnRev(OUT_B,50);Wait(900);  //アームを下ろす

 
**通信するサブルーチン(ボールの掴む:離す) [#h7c7d32b]
slaveに信号を送るタイミングは、ボールを掴むときと離すときである。
+masterがslaveに信号を送る
+slaveが動作を行う、終わったらmasterに信号を送る
+次のプログラムに移行する

上記の通りに行うため、master側ではwhileを用いた
***master側 [#rf5a9439]
 void catch()
 {
     int msg1;                                    //msg1を定義する
     SendRemoteNumber(CONN,MAILBOX1,SIGNAL1);     //CONN(ここではスレイブ1)にMAILX1を通してSIGNAL1(ここではボール前についたことを知らせる信号)を送信する
     while(msg1!=SIGNAL2){                        //msg1の値がSIGNAL2(ここでは掴む動作が終了したことを知らせる信号)になったらループを抜ける
         ReceiveRemoteNumber(MAILBOX1,true,msg1); //MAILBOX1でスレイブから信号を受け取る
         Off(OUT_BC);                             //ループの間(掴む動作が終了したことを知らせる信号がスレイブから帰ってくるまで)機体を停止させる
     }  
 }
 void release()
 {
     int msg2;                                   //msg2を定義する
     SendRemoteNumber(CONN,MAILBOX2,SIGNAL3);    //スレイブにMAILBOX2を通してSIGNAL3(ここではゴールの箱の前についたことを知らせる信号)を送信する
     while(msg2!=SIGNAL4){                       //msg2の値がSIGNAL4(ここではボールを離す動作が終了したことを知らせる信号)になったらループを抜ける
         ReceiveRemoteNumber(MAILBOX2,true,msg2);//MAILBOX2でスレイブから信号を受け取る
         Off(OUT_BC);                            //ループの間(離す動作が終了したことを知らせる信号がスレイブから帰ってくるまで)機体を停止させる
     }  
 }
***slave側 [#kefda03a]
こちらのプログラムはメインプログラムになる

 task main ()
 {
     int msg1;  // 受け取った値を格納する変数
     int msg2;
     while(true){
         ReceiveRemoteNumber(MAILBOX1,true,msg1);  
         ReceiveRemoteNumber(MAILBOX2,true,msg2); 
         if(msg1==SIGNAL1){
             down;   
             tukamu;
             up;
             Off(OUT_AB);
             SendResponseNumber(MAILBOX1,SIGNAL2);//マスター側のMAILBOX1にSIGNAL2を送る
         }
         if(msg2==SIGNAL3){
             hanasu;
             Off(OUT_A);
             SendResponseNumber(MAILBOX2,SIGNAL4);//マスター側のMAILBOX2にSIGNAL4を送る
         }
     }  
 }

**ライントレース [#y26cda2e]
***交差点で停止する [#f33ea491]
交差点で停止する仕組みは課題2と同様である

黒が0.1秒以上続けばwhileを抜けてプログラムを終了する

詳しくは[[2019a/Member/aoto/Mission2]]を参照
 void line_traceS()               //左のライントレース
 {
     SetSensorLight(S3);          
     long t0;                     //long型でt0を定義
     t0=CurrentTick();            //t0に現在の時間を代入
     while(CurrentTick()-t0<100){ //今からt0になるまで0.1秒経つまでの間プログラムを行う
         if(SENSOR_3>55){         //明るさ56以上(真っ白)が測定されると
             migi1;               //右旋回
             t0=CurrentTick();    //t0を更新
         }else if(SENSOR_3>50){   //明るさ51〜55(白よりの境界線)が測定されると
             migi0;               //右折
             t0=CurrentTick();    //t0を更新
         }else if(SENSOR_3>43){   //明るさ44〜50(白と黒の境界線)が測定されると
             tyokusinn;           //直進
             t0=CurrentTick();    //t0を更新
         }else if(SENSOR_3>34){   //明るさ35〜43(黒よりの境界線)が測定されると
             hidari0;             //左折
             t0=CurrentTick();    //t0を更新     
         }else{                   //明るさ34以下が測定されると
             hidari1;             //左旋回       
         }   
     }
 }
***交差点を渡る [#q114d146]
 void crossline()
 {
     tyokusinn;              //直進
     until(SENSOR_3>white-5);//白よりのグレーまで
     migi1;                  //機体をまっすぐにする
     until(SENSOR_3<black);  //黒寄りのグレーまで
 }
 
***ライントレース時の右左折 [#h2350711]
白になるまで行うことで、様々な場所の対応することができるようにした
 void Lcurve()             //左折
 {
     hidari2;
     until(SENSOR_3>white);//白になるまで          
 }

 void Rcurve()             //右折
 {
     migi2;                
     until(SENSOR_3>white);//白になるまで  
 }
**メインプログラム [#m98b4cfb]
 task main()
 {
     SetSensorLight(S3);
     tyokusinn;          //ライン上に移動
     linetraceS();       //M to K
     Lcurve();           //箱の方に向きを変える
     linetraceS();       //K to J
     OnRev(OUT_C,20);    //向きの微調整
     Wait(500);          //上に同じ
     catch();            //ボールを掴む
     linetraceS();       //J to I
     Lcurve();           //Iの方に向きを変える
     linetraceS();       //I to C
     Lcurve();           //Bの方に向きを変える
     linetraceS();       //C to B
     Rcurve();           //中央の線の方に向きを変える
     linetraceS();       //B to 中央の線
     Rcurve();           //A'の方に向きを変える
     linetraceS();       //to A'
     Lcurve();           //B'の方に向きを変える
     linetraceS();       //to B'
     Lcurve();           //C'の方に向きを変える
     linetraceS();       //B' to D'
     Rcurve();           //H'の方に向きを変える
     linetraceS();       //D' to H'
     OnRev(OUT_C,20);    //向きの微調整
     Wait(500);          //上に同じ
     release();          //ボールをはなす
     kousinn;            //2つ目のボール(仮想)
     Wait(2000);
     OnFwd(OUT_C,20);OnRev(OUT_B,10);
     until(SENSOR_3>white-5);
     linetraceS();
     crossline();
     linetraceS();
     Lcurve();
     linetraceS();
     Rcurve();
     linetraceS();
     Lcurve();
     linetraceS();
     crossline();
     OnFwd(OUT_BC,30);Wait(2900);Off(OUT_BC);
     catch();
     OnRev(OUT_BC,30);Wait(2900);Off(OUT_BC);
     Lcurve();
     linetraceS();
     release();
     kousinn;             //3つ目のボール(仮想)
     Wait(2000);
     OnFwd(OUT_C,20);OnRev(OUT_B,10);
     until(SENSOR_3>white-5);
     linetraceS();
     Rcurve();
     linetraceS();
     Rcurve();
     linetraceS();
     Lcurve();
     linetraceS();
     crossline();
     linetraceS();
     Lcurve();
     linetraceS();
     crossline();      
     linetraceS();        
     Wait(2900);          
     catch();              
     kaiten();            
     linetraceS();
     Rcurve();
     linetraceS();
     Lcurve();
     linetraceS();
     Rcurve();
     linetraceS();
     Lcurve();
     linetraceS();
     Lcurve();
     linetraceS();
     Rcurve();
     linetraceS();
     release();
     kousinn;
 } 

*まとめ [#ac6d7983]
-テストと重なってしまいあまり試行できなかった。
-ロボコンでは得点を得ることはできなかった。
-光センサーの値の調整が難しかった。部屋の明るさ、コースのちょっとした明暗も影響してくるため今回のようなプログラムでは、特に難しかった。
-3回の課題を終えて、プログラミングは簡単ではないということを強く実感することができた。また、日常に広がっているプログラミングを用いた機構について、視野を広げる事ができたと感じている。


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS