今回の課題 †リンク参照 課題2 メンバー紹介 †saborijini(ハード・ソフト主に製作しました) bosoo hodaka snowdrop ロボット解説 †
プログラム解説 † ここで同じようなプログラム[PlaySound(SOUND_CLICK);やOff(OUT_BC);Wait(500);]が使われています。これはある動作が完了したことを示すためにピッという音を鳴らし、各動作をはっきりさせるために一旦停止をしています。 マスター(親機)のプログラム †ここからのプログラム解説は上の図を参考にしながら見て下さい。 #define black 36 #define speed 35 #define A 38 #define B 65 定数の定義をしています。電池の種類・消耗次第でスピードが、照明次第でセンサーの感度が変わってくるのでよく調整する数値は代わりとなる文字に置き換えて作業を効率良くしています。 task main() { SetSensorLight(S1); SetSensorLight(S4); SetSensorLowspeed(S3); センサーの定義をしています。1にはライントレース用の光センサー、3にはコップ認識用の光センサー、4にはコップとの距離認識用の光センサーをつないだことを示しています。2には配線するのが困難であったため使っていません。 int msg; msgという変数を用いることを示しています。これは後で使います。 until(BluetoothStatus(1) == NO_ERR); RemotePlayTone(1,440,1000); 子機との通信が出来ているか確認して上手くいっているとピーっと音を鳴らすようにしています。実行前にセッティングは済ませていましたが、念のため組み込むました。もし通信が切れていたらロボットはこれ以降の動作を実行しません。個人的にはロボットの起動音みたいで気に入っています。 Off(OUT_BC); Wait(1200); ピーっと鳴らしている間はロボットは止まっているようにして、すぐには動き出しません。急に動き出すと、起動ボタンは下の親機にあるため指が引っかかる可能性があるからです。 OnFwdSync(OUT_BC,speed,0); until(SENSOR_1 < black); PlaySound(SOUND_CLICK); ここからロボットが動き出します。OnFwdSyncを用いて直進しています。モーター2つの力が等しいとは限らないので、2つを同期させることで真っ直ぐ進めるようになります。 Off(OUT_BC);Wait(500); OnFwdSync(OUT_BC,speed,0); Wait(400); PlaySound(SOUND_CLICK); スタート位置の黒線の枠を横断します Off(OUT_BC);Wait(500); OnFwdSync(OUT_BC,speed,0); until(SENSOR_1 < black); PlaySound(SOUND_CLICK); 次の黒線に当たるまで直進します Off(OUT_BC);Wait(500); OnFwdSync(OUT_BC,speed,0); Wait(500); PlaySound(SOUND_CLICK); 黒線の枠を横断します。ここでロボットは枠内に半分ほど入ります。 Off(OUT_BC);Wait(500); OnFwd(OUT_B,speed); OnRev(OUT_C,speed); until(SENSOR_1 < black); PlaySound(SOUND_CLICK); ロボットが黒線上にいる状態で方向転換(左へ旋回)します。この旋回を始めWait();を使い調節して動かそうとしていました。しかしいくら時間を費やしても成功せず、その上電池の消耗で安定しなくなりました。そこでここにもuntilを用いました。黒線に当たるまで旋回させると、ほぼ90度旋回に成功しました。 Off(OUT_BC);Wait(700); OnFwd(OUT_B,speed); OnRev(OUT_C,speed); Wait(180); PlaySound(SOUND_CLICK); 前の動作でほぼ旋回できているのでここでは微調整として少し旋回させています。1秒もしない時間ならWait();を使っても誤差は感じられません。 Off(OUT_BC);Wait(500); OnFwdSync(OUT_BC,speed,0); Wait(1100); PlaySound(SOUND_CLICK); 旋回が終わるとロボットは黒線の枠上にあるので光センサーを再び使うために黒線から出るくらいの距離を前進します。ここをuntilにしても良かったのですが、必ずしもロボットが黒線上にいるとは限らないので使っていません。 Off(OUT_BC);Wait(500); OnFwdSync(OUT_BC,speed,0); until(SENSOR_1 < black); PlaySound(SOUND_CLICK); Off(OUT_BC);Wait(500); OnFwdSync(OUT_BC,speed,0); Wait(500); PlaySound(SOUND_CLICK); Off(OUT_BC);Wait(500); OnFwdSync(OUT_BC,speed,0); until(SENSOR_1 < black); PlaySound(SOUND_CLICK); Off(OUT_BC);Wait(500); OnFwdSync(OUT_BC,speed,0); Wait(600); PlaySound(SOUND_CLICK); Off(OUT_BC);Wait(500); 図から分かるように旋回した地点からすると、コップは黒線2本目のところにあります。そのため黒線まで直進、横断を2回しています。 OnFwd(OUT_B,speed); OnRev(OUT_C,speed); until(SENSOR_1 < black); PlaySound(SOUND_CLICK); Off(OUT_BC);Wait(500); ここは前述の方向転換と同じです。これでコップがロボットの目の前にあるところまで来ました。 OnRevSync(OUT_BC,speed,0); Wait(2000); ここで一旦バックして下がります。あまりにもコップとの距離が近すぎるからです。 OnFwdSync(OUT_BC,speed,0); until(SensorUS(S3) <= 12); コップとの距離が12cm以下になるまで前進します。この12cmは別に練習プログラムを組んでベストな位置を測りました。 Off(OUT_BC); Wait(100); RemoteStartProgram(1,"z_slave.rxe"); ベストポジションに来たので親機からプログラム「z_slave.rxe」を子機に実行するように命令します。この命令を始め親機が子機に数字を送ってやろうとしていました。この場合、子機はifを用いてそれぞれの数字ごとの行動をプログラムしなければなりません。しかしプログラムを指定して子機にそれを起動させる通信方法はプログラミングする方にも作業が簡単になる利点があります。なのでその方法を採用しました。 while(msg != 11){ ReceiveRemoteNumber(MAILBOX1,true,msg); } PlaySound(SOUND_CLICK); 子機から「11」というメッセージが来るまで待ちます。このメッセージは子機が親機の命令を終えたことを知らせるために送ります。親機はMAILBOX1にメッセージを受け取り、それをmsgに置き換えます。trueは受け取ったらMAILBOX1を空にすることを示します。この後にもメッセージをもらうので空にさせました。始めはuntilを使って「11」が来るまで、をプログラムしました。しかし上手くいきませんでした。until()内の条件文が出来ていなかったからだと思います。ここではwhile(msg != 11)を採用しました。これはmsgが11でないならば受け取り続ける(待ち続ける)ことを示しています。whileまたはuntilで繰り返さないと、メッセージを受け取らなくてもプログラムが進んでしまいます。 if(SENSOR_4 < A){ OnFwdSync(OUT_BC,speed,0); until(SensorUS(S3) <= 18); Off(OUT_BC); Wait(100); RemoteStartProgram(1,"z_slave-2.rxe"); while(msg != 12){ ReceiveRemoteNumber(MAILBOX1,true,msg); } PlaySound(SOUND_CLICK); もしコップがAだとしたら1まで運ぶのでコップとの距離18cm以下になるまで前進して、親機がプログラム「z_slave2.rxe」を子機に起動させます。子機からのメッセージを受け取り次第ピッと鳴らして終了。2個目以降は戻って掴んで認識、重ねるを繰り返すつもりでした。 }else if(SENSOR_4 < B){ OnFwdSync(OUT_BC,speed,0); Wait(2000); PlaySound(SOUND_CLICK); Off(OUT_BC);Wait(500); OnFwd(OUT_B,speed); OnRev(OUT_C,speed); until(SensorUS(S3) < 18); PlaySound(SOUND_CLICK); Off(OUT_BC); Wait(100); RemoteStartProgram(1,"z_slave-2.rxe"); while(msg != 12){ ReceiveRemoteNumber(MAILBOX1,true,msg); } PlaySound(SOUND_CLICK); もしコップがBだとしたら超音波センサーでコップを認識するまで左に旋回、コップまで前進、以降はAの場合と同じです。 }else{ OnFwdSync(OUT_BC,speed,0); Wait(6000); OnFwd(OUT_B,speed); OnRev(OUT_C,speed); until(SensorUS(S3) < 30); PlaySound(SOUND_CLICK); Off(OUT_BC); Wait(100); OnFwdSync(OUT_BC,speed,0); until(SensorUS(S3) <= 18); Off(OUT_BC); Wait(100); RemoteStartProgram(1,"z_slave-2.rxe"); Off(OUT_BC); Wait(100); RemoteStartProgram(1,"z_slave-2.rxe"); while(msg != 12){ ReceiveRemoteNumber(MAILBOX1,true,msg); } PlaySound(SOUND_CLICK); } } もしコップがCだとしたらコップ3が真横に来るように前進、右に旋回、コップまで前進、以降はAの場合と同じです。 スラーブ(子機)のプログラム †task main() { PlaySound(SOUND_CLICK); OnFwd(OUT_A,70);Wait(2800);Off(OUT_A); OnRev(OUT_C,20);Wait(800);Off(OUT_C); OnRev(OUT_A,60);Wait(2800);Off(OUT_A); SendResponseNumber(MAILBOX1,11); Wait(1000); PlaySound(SOUND_CLICK); } アームを下げて掴んでアームを上げます。そして親機にメッセージを送ります。 task main() { PlaySound(SOUND_CLICK); OnFwd(OUT_A,60);Wait(900);Off(OUT_A); OnFwd(OUT_C,20);Wait(700);Off(OUT_C); OnRev(OUT_A,80);Wait(1800);Off(OUT_A); SendResponseNumber(MAILBOX1,12); Wait(1000); PlaySound(SOUND_CLICK); } アームを下げて離してアームを上げます。そして親機にメッセージを送ります。 反省と感想 † ロボコンの結果は4位/9チーム中でした。プログラミングで1個までしかできていないのに、その1個も成功しない始末…。(そのコップがAだったら良かったのに…)でも掴みはしました。チーム内で集まる時間を作れなかったのが原因です。期末期間で1人で出来ることなんて微々たるものでした。1人で完成なんてありえません。第一に反省すべき点です。 |