[[2014a/Member]]
*今回の課題 [#r01000e4]
 リンク参照
 [[課題2:http://yakushi.shinshu-u.ac.jp/robotics/?2014a%2FMission2#p66feff7]]
*メンバー紹介 [#n9d003ed]
 saborijini(ハード・ソフト主に製作しました)
 bosoo
 hodaka
 snowdrop
*ロボット解説 [#i707f0d4]
&ref(IMG_0243.JPG);~
ライントレース用のセンサーは少し上げています。これは2枚の紙の境目にまで反応してしまったため、センサーを上げることで精密性を下げて境目に反応するのを避けました。~
&ref(IMG_0244.JPG);~
超音波センサーはロボットの真正面に配置しました。コップに対してロボットが正面に来るようにするためです。縦に付けた方がより正確に計れたと思います。~
&ref(IMG_0245.JPG);~
これはアームを上に挙げた状態です。子機親機を二段重ねにすることでロボットの大きさをコンパクトにしました。アームが少し高い位置にき過ぎた気がします。~
&ref(IMG_0246.JPG);~
アームにはセンサーを取り付けました。始めは超音波センサーの横に付けていましたが、確実に読み取るためにアームに付けました。~
&ref(IMG_0247.JPG);
&ref(IMG_0248.JPG);~
これはアームを下した状態です。ゴムをアームの補助として使っています。またタイヤはすべり止めとして使っています。回転はしません。コップの上部を掴んでしまっているので重ねる時にコップが当たってしまいました。終わってから思えば持ち上げてから深く掴みなおせば良かったと思います。
*プログラム解説 [#w0ae5ed8]
 ここで同じようなプログラム[PlaySound(SOUND_CLICK);やOff(OUT_BC);Wait(500);]が使われています。これはある動作が完了したことを示すためにピッという音を鳴らし、各動作をはっきりさせるために一旦停止をしています。~
また今回の課題に余り時間をかけられなかったので1個のコップの運搬までしかプログラミングが出来ていません。ご了承下さい。~
コップは茶色のコップを使用し、白黒の着色で区別しました~
図に示したような動作をするつもりでした。~
&ref(2014a-mission2.png);
**マスター(親機)のプログラム [#kef749ae]
ここからのプログラム解説は上の図を参考にしながら見て下さい。
 #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つを同期させることで真っ直ぐ進めるようになります。~
また今回ロボットの移動にWait();を使うのを控えました。これは先にも述べたように電池の状態次第で移動時間を調節する必要があるからです。そこでuntilを用いて移動時間を決めました。「黒線に当たるまで」というようにしました。これならどんなスピードでも決まった距離を進めます。
 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で繰り返さないと、メッセージを受け取らなくてもプログラムが進んでしまいます。~
~
ルールにあるようにコップはランダムに置かれます。コップはA1/B2/C3のよう対になっています。
 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の場合と同じです。
**スラーブ(子機)のプログラム [#aebee944]
 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);
 }

アームを下げて離してアームを上げます。そして親機にメッセージを送ります。
*反省と感想 [#z863eb64]
 ロボコンの結果は4位/9チーム中でした。プログラミングで1個までしかできていないのに、その1個も成功しない始末…。(そのコップがAだったら良かったのに…)でも掴みはしました。チーム内で集まる時間を作れなかったのが原因です。期末期間で1人で出来ることなんて微々たるものでした。第一に反省すべき点です。~
 ではロボットについての感想を述べたいと思います。完成した時はかなりいいのが出来たと思いました。その時配線もテストもしていなかったからでしょう、僕は気が付かなかったのです。まず直面したのがアームが上がらないということです。モーターがモーター1個上げられなかったのです。当初のアームは腕が長かったのでそれが原因だと思いましたがそれでも上げられませんでした。この問題にはゴムを付けて対処しました。(この後アームが下がらない問題が生じましたがアームのスピードを上げてゴリ押しました)
 ロボコンの結果は4位/9チーム中でした。プログラミングで1個までしかできていないのに、その1個も成功しない始末…。(そのコップがAだったら良かったのに…)でも掴みはしました。チーム内で集まる時間を作れなかったのが原因です。期末期間で1人で出来ることなんて微々たるものでした。1人で完成なんてありえません。第一に反省すべき点です。~
 ではロボットについての感想を述べたいと思います。完成した時はかなりいいのが出来たと思いました。その時配線もテストもしていなかったからでしょう、僕は気が付かなかったのです。まず直面したのがアームが上がらないということです。モーターがモーター1個上げられなかったのです。当初のアームは腕が長かったのでそれが原因だと思いましたがそれでも上げられませんでした。この問題にはゴムを付けて対処しました。(この後アームが下がらない問題が生じましたがアームのスピードを上げてゴリ押しました)次に直面したのが起動ボタンが押しにくいことです。隙間を広げましたが最後まで押しにくいままになってしまいました。~
 そしてプログラムについて、ただただ協力と時間が足りなかったの一言です。時間のかけ方はハード<<<ソフトです。~
 最後にゼミを通しての感想はいろいろ難題にぶつかりましたがとても楽しめたと思います。最高に面白く大変なゼミでした。



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