目次 #contents *メンバー [#k7050064] ・snowdrop…このページの執筆者。主にアームの改良と、ボールをつかんでアームを上げるまでの プログラムの作成を担当。 ・bosso…主にロボット本体を作るにあたってのアイディアを出してくれました。 ・bosoo…主にロボット本体を作るにあたってのアイディアを出してくれました。 ・saborijini…プログラム作成とロボット本体の方向性の決定・作成を担当。 ・hodaka…紙コップをどうつかめば良いか、課題をクリアするためのアイディア担当。この講義の前半ではとてもお世話になりました。 *課題について [#k52f08b6] [紙コップ収集ロボット] 2台のロボットで紙コップを収集し、同じ番号の書かれている紙コップに重ねる。 &ref(2014a/Member/snowdrop/Mission2/2014a-mission2.png,70%); [フィールドの説明]◦ 上図のように、フィールドは課題1で使用した紙を2枚つなぎ合わせる (詳細な図面は[[2014a/Mission1]]を参照のこと)。 図の右半分の黄色い地点には、その数字と同じ数字が書いてある紙コップが置かれている。 また左半分のA,B,Cの地点にも1から3までの数字が書かれている紙コップが置かれているが、 どのコップをどの地点に置くかは直前にサイコロを振ってランダムに決める。 [基本ルール] ◦競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。 ◦図の右上のスタートエリアからスタートする(課題1と同じ)。接地している部分がスタートエリア内に入って入ればよい。 ◦図の左半分にある紙コップを集めて、それぞれ右半分にある同じ番号の紙コップに重ねる。 ◦右半分の紙コップは10cm内の移動は認める。 ◦開始の合図から5秒以内にスタートボタンを押す作業を完了すること。 ◦競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。 ◦途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。 紙コップの位置の決め方、技術点の計算方法については[[2014a/Mission2]]を見てください。 *ロボット [#f46abbdd] **ロボット本体 [#d721ab8e] &ref(2014a/Member/snowdrop/Mission2/robot all.JPG,30%); ロボットの全体像です。 ロボットを2つ作り、それぞれを通信させるという案も最初に出ましたが それだとプログラムも2つ作らなければならないということで断念しました。 この完成形では、ロボット本体(はじめにボタンを押す部分)を2段重ねにして その2つを通信させることによって課題のクリアを目指します。 通信については後のプログラムで詳しく説明します。 **アーム [#yeb7f592] &ref(2014a/Member/snowdrop/Mission2/arm.JPG,30%); 私が一番力を注いだのがアームの改良です。上の写真は、紙コップをつかむアームを横から見た図です。 「コップをつかむ→つかんだ状態のままアームを上方に動かす」という動作が必要になるので コップをつかむためのモーターとそのモーターを上にあげるためのモーター2つを接続しました。 アームとモーターを合わせたものが意外と重たいため、問題点が二つありました。 �.灰奪廚鬚弔�む時、重力により上→下の動きが速すぎてコップを正確につかみづらい �▲灰奪廚鬚弔�んだ後、アームとモーターを上にあげることが困難 試行錯誤の結果、アームを動かすためのモーターとそのモータを動かすためのモーターに 輪ゴムを取り付けることで解決しました。(上の写真では右側にある、赤と黄色の輪ゴムです) ちなみに、輪ゴムは部品箱の中に入っていたものを使用しました。 これをつけることで、アームが下がるときは「上→下」の動作が抑制されてコップをつかみやすくなり、 アームを上げるときは伸びている輪ゴムの弾性力(もとに戻ろうとする力)が働いてアームが簡単に持ち上がるようになりました! &ref(2014a/Member/snowdrop/Mission2/catch.JPG,30%); 紙コップをつかんだ時の写真です。 初期は私のグループが課題1で作成した、左右から物体をはさむタイプのアームだったのですが(詳しくは[[2014a/Member/snowdrop/Mission1]]を参照) コップを3点でつかむのが安定していたためこの形になりました。(写真では見えませんが右側のタイヤの奥にもう一つタイヤがあります) コップをつかんでいる部分のタイヤは摩擦が大きいのでコップが滑らずにつかむことができます。 **センサー [#w091aa35] &ref(2014a/Member/snowdrop/Mission2/sensor.JPG,30%); 課題をクリアするにあたって、写真下方にあるライトセンサと情報にある超音波センサの2つを使用しました。 ライトセンサはロボットに黒線の上を移動させるためのものです。(課題1のライントレースを同じ要領) 超音波センサはこの課題で初めて使いましたが、コップがあるか無いかを識別するためのものです。 この課題では「どこにコップがあるのか」をロボットに認識させるのがとても重要になってくるので このセンサを利用しました。 &ref(2014a/Member/snowdrop/Mission2/light sensor.JPG,30%); 2つのセンサーを横から見た写真です。 コードが余ってしまったので、ロボットの動作の邪魔にならないようぐるぐる巻きつけています。 超音波センサの位置が若干高めなので、その高さにあった大きめの紙コップを用意しました。 *親機(マスター)のプログラム [#ta7d4e93] 今回、私はプログラムについてはほぼノータッチでした。 何とか理解はできましたが、詳しく知りたい方はsaborijiniのページ[[2014a/Member/saborijini/Mission2]]を見てもらったほうが良いと思います。 2台のロボット本体を使用して、その2つに通信させてロボットを動かすようなプログラムになっています。 最初は親機のプログラムについて説明します。 **定義 [#nb08e03e] まずは#defineで定義したものの確認です。 #define black 36 #define speed 35 #define A 38 #define B 65 blackは黒線と白線の境界値を示しています。課題1でやったライントレースと同じですね。 speedは遅めの35に設定しています。 また、今回は茶色い紙コップと白い紙コップ、その側面を黒く塗ったものの3種類を使いました。 Aは黒コップを茶コップの境界値、Bは茶コップと白コップの境界値を定義しています。 **センサー、変数 [#e0bb86a3] 今回使ったセンサーと変数の設定です。 task main() { SetSensorLight(S1); SetSensorLight(S4); SetSensorLowspeed(S3); 今回は光センサ2つと超音波センサを1つ使いました。 1にはライントレース用の光センサ、4には紙コップ側面の色を認識するセンサ(黒or白or茶色)、 3にはコップとロボットとの距離を判断するための超音波センサを配線してあります。 int msg; msgという変数を用いました。のちのプログラムで説明します。 **プログラム本体 [#lf011083] では、ロボットの動作に入っていきましょう。 until(BluetoothStatus(1) == NO_ERR); //子機との通信が上手くいっていると RemotePlayTone(1,440,1000); //ピーっと音が鳴る もし通信が切れていたら、ロボットはこれ以降の動作を実行しません。 ロボットどうしの通信状況を確認するのに良い手段だと思います。 Off(OUT_BC); //1.2秒ロボット停止 Wait(1200); 音が鳴っている間はロボットは動かないことになっています。 OnFwdSync(OUT_BC,speed,0); //2つのモータB,Cをシンクロさせて直進 until(SENSOR_1 < black); //黒線に到達したら PlaySound(SOUND_CLICK); //音が鳴る 事前に時間を決めてロボットを動かすのではなく、untilを利用することでより正確な動きが期待できます。 Off(OUT_BC); //0.5秒停止 Wait(500); OnFwdSync(OUT_BC,speed,0); //0.4秒前進 Wait(400); PlaySound(SOUND_CLICK); //ピッと音が鳴る これで最初(スタート位置)の黒線の枠を横断しました。 Off(OUT_BC); //0.5秒停止 Wait(500); OnFwdSync(OUT_BC,speed,0); //ロボット前進 until(SENSOR_1 < black); //黒線に到達するまで PlaySound(SOUND_CLICK); //到達するとピッと音が鳴る 2枚目の紙の黒線の枠に向かいます。 Off(OUT_BC); //音が鳴ったのち0.5秒停止 Wait(500); OnFwd(OUT_B,speed); //B(右タイヤ)が前転、C(左タイヤ)が後転→左旋回 OnRev(OUT_C,speed); until(SENSOR_1 < black); //黒線に到達するまで PlaySound(SOUND_CLICK); //到達するとピッと音が鳴る ロボットが黒線上にある状態で左旋回します。ほぼ90度旋回し、ロボットは左向きになります。 Off(OUT_BC); //0.7秒停止 Wait(700); OnFwd(OUT_B,speed); //0.18秒左旋回 OnRev(OUT_C,speed); Wait(180); PlaySound(SOUND_CLICK); //ピッと音が鳴る これは微調整のための旋回です。 Off(OUT_BC); //0.5秒停止 Wait(500); OnFwdSync(OUT_BC,speed,0); //1.1秒前進 Wait(1100); PlaySound(SOUND_CLICK); //ピッと音が鳴る 黒線の上にいるロボットを前進させて黒線の外に出します。 Off(OUT_BC); //0.5秒停止 Wait(500); OnFwdSync(OUT_BC,speed,0); //ロボット前進 until(SENSOR_1 < black); //黒線に到達するまで PlaySound(SOUND_CLICK); //到達したらピッと音が鳴る Off(OUT_BC); //0.5秒停止 Wait(500); OnFwdSync(OUT_BC,speed,0); //0.5秒前進 Wait(500); PlaySound(SOUND_CLICK); //ピッと音が鳴る ここまでで1回黒線を横断しています。 Off(OUT_BC); //0.5秒停止 Wait(500); OnFwdSync(OUT_BC,speed,0); //ロボット前進 until(SENSOR_1 < black); //黒線に到達するまで PlaySound(SOUND_CLICK); //到達したらピッと音が鳴る Off(OUT_BC); //音が鳴った後0.5秒停止 Wait(500); OnFwdSync(OUT_BC,speed,0); //0.6秒前進 Wait(600); PlaySound(SOUND_CLICK); //ピッと音が鳴る Off(OUT_BC); //0.5秒停止 Wait(500); これが2回めの黒線の横断になります。 この時点で、ロボットは2枚の紙を縦断している黒線上にあります。 OnFwd(OUT_B,speed); //左旋回 OnRev(OUT_C,speed); until(SENSOR_1 < black); //黒線上に来るまで PlaySound(SOUND_CLICK); //黒線上に到達したらピッと音が鳴る Off(OUT_BC); //0.5秒停止 Wait(500); これでコップの目の前までロボットが来ます。 OnRevSync(OUT_BC,speed,0); //2秒後進 Wait(2000); コップとの距離が近すぎるため、いったん下がります。 OnFwdSync(OUT_BC,speed,0); //コップとの距離が12センチ以下になるまで前進 until(SensorUS(S3) <= 12); 超音波センサを用いてコップをつかむのに最適な12センチまでロボットを前進させます。 Off(OUT_BC); //0.1秒停止 Wait(100); RemoteStartProgram(1,"z_slave.rxe"); //子機と通信 この後、親機と子機が通信してプログラム「z_slave.rxe」を子機に実行させます。 後に紹介する子機のプログラムを見ると分かりますが、これはアームを下げてコップをつかみ、 再びアームを上げる動作です。 while(msg != 11){ //子機から11というメッセージを受け取ったら ReceiveRemoteNumber(MAILBOX1,true,msg); //親機内のMAILBOX1を空にする(true) } PlaySound(SOUND_CLICK); //ピッと音が鳴る 子機がきちんと動作をしたことを音で確認して、次の動作に移ります。 以下は、コップの色によってロボットの動きが変わります。 if(SENSOR_4 < A){ //コップが黒だった時 OnFwdSync(OUT_BC,speed,0); //コップとの距離が18センチになるまで前進 until(SensorUS(S3) <= 18); Off(OUT_BC); //0.1秒停止 Wait(100); RemoteStartProgram(1,"z_slave-2.rxe"); //子機と通信 コップが黒の場合には1に運ぶので前進させ、プログラム「z_slave-2.rxe」を子機に実行させます。 これはコップを持ったアームを下げてコップを重ねる動作です。 while(msg != 12){ //12というメッセージを子機から受け取ったら ReceiveRemoteNumber(MAILBOX1,true,msg); //MAILBOX1を空にする } PlaySound(SOUND_CLICK); //ピッという音が鳴る }else if(SENSOR_4 < B){ //コップが茶色の時 OnFwdSync(OUT_BC,speed,0); //2秒前進 Wait(2000); PlaySound(SOUND_CLICK); //ピッと音が鳴る Off(OUT_BC); //0.5秒停止 Wait(500); OnFwd(OUT_B,speed); //コップとの距離が18センチになるまで左旋回 OnRev(OUT_C,speed); until(SensorUS(S3) < 18); PlaySound(SOUND_CLICK); //距離が18センチになったらピッと音が鳴る Off(OUT_BC); //0.1秒停止 Wait(100); RemoteStartProgram(1,"z_slave-2.rxe"); //子機と通信、コップを重ねる 茶色のコップの場合は左旋回して重ねるコップを探します。 while(msg != 12){ //子機から12というメッセージを受け取ったら ReceiveRemoteNumber(MAILBOX1,true,msg); //MAILBOX1を空にする } PlaySound(SOUND_CLICK); //ピッと音が鳴る }else{ //それ以外(コップが白)のとき OnFwdSync(OUT_BC,speed,0); //6秒前進 Wait(6000); OnFwd(OUT_B,speed); //コップとの距離が30センチになるまで旋回 OnRev(OUT_C,speed); until(SensorUS(S3) < 30); PlaySound(SOUND_CLICK); //30センチになったらピッと音が鳴る Off(OUT_BC); //0.1秒停止 Wait(100); OnFwdSync(OUT_BC,speed,0); //コップとの距離が18センチになるまで前進 until(SensorUS(S3) <= 18); //18センチになったらピッと音が鳴る Off(OUT_BC); //0.1秒停止 Wait(100); RemoteStartProgram(1,"z_slave-2.rxe"); //子機と通信 Off(OUT_BC); //0.1秒停止 Wait(100); RemoteStartProgram(1,"z_slave-2.rxe"); //子機と通信 while(msg != 12){ ReceiveRemoteNumber(MAILBOX1,true,msg); } PlaySound(SOUND_CLICK); } } コップが白い場合、図のコップ3をつかむためにロボットを動かします。 コップに近づいた後の動作はA.Bと同じです。 *スラーブ(子機)のプログラム [#adf47af3] task main() { PlaySound(SOUND_CLICK); //ピッと音が鳴る OnFwd(OUT_A,70); //2.8秒アームを下げる Wait(2800); Off(OUT_A); OnRev(OUT_C,20); //0.8秒でコップをつかむ動作 Wait(800); Off(OUT_C); OnRev(OUT_A,60); //2.8秒アームを上げる Wait(2800); Off(OUT_A); SendResponseNumber(MAILBOX1,11); //親機に11というメッセージを送る Wait(1000); PlaySound(SOUND_CLICK); //ピッと音が鳴る } これはコップをつかむ動作です。 task main() { PlaySound(SOUND_CLICK); //ピッと音が鳴る OnFwd(OUT_A,60); //0.9秒アームを下げる Wait(900); Off(OUT_A); OnFwd(OUT_C,20); //0.7秒でコップをアームから離す Wait(700); Off(OUT_C); OnRev(OUT_A,80); //1.8秒アームを上げる Wait(1800); Off(OUT_A); SendResponseNumber(MAILBOX1,12); //親機に12というメッセージを送る Wait(1000); PlaySound(SOUND_CLICK); //ピッと音が鳴る } これはコップを重ねる動作です。 *反省 [#n56a9213] 課題2では4人グループでの取り組みだったのですが、1人の人に負担をかぶせてしまい 自分が貢献できなかったのが大きな反省点です。期末試験の期間に入る前に4人全員で問題点を 整理し、一人ひとりの役割を明確にしておくべきだったと思います。 ロボット本体の作成と課題をこなすための改良はやっていてとても楽しかったです。 プログラミングの面では自分は不完全燃焼でしたが、来年以降の勉強にもこの講座で学んだことは 活かせるのではないかと思います。 大変なことも多かったですが、全体としてとても良い経験になったゼミでした。