Japaninoロボ Ep.3 障害物回避 避けるとは何か①
2015/10/24
前回エントリでは、JapaninoでRE-260を制御して動く物体を作成することに成功した。
今回は搭載されている二つの赤外線距離センサーでの障害物回避に挑む。
A.ほら、廊下って、たくさん生徒歩いているじゃん…。 …聞くなっっ!
このお話の主人公 赤外線距離センサー(正確には測距モジュール、というのか)GP2Y0A21YKにつきまして。非接触でおよそ10cm~80cmを測ることができる。
(中部大学自由研究発表会ポスターより)
返ってくる電圧は3V位上限。analogReadで読めば、(5Vまでを1024段階で読むので)25cmで200、5cmで700といった値が返ってくる。5cm以上は近づきたくない。といった感じ。探査機の前方左右に配された2つのセンサからのこの値だけを頼りに、いかにして障害物を避けるのか。考案したスケッチの紹介。
・「避け方」の概要・
「障害物にぶつからないようにしたい」と考えたときに一番基本的な動作は、障害物を見つけたら止まること。その後落ち着いて後退し、方向を変えて進む。それを具現化した(、ある意味潔く分かりやすい)スケッチ。
・スケッチ・
int dis_L = 0; int dis_R = 0; void setup(){ pinMode(3,OUTPUT); pinMode(4,OUTPUT); pinMode(5,OUTPUT); pinMode(8,OUTPUT); pinMode(9,OUTPUT); pinMode(13,OUTPUT); analogWrite(6,100); analogWrite(10,100); Serial.begin(9600); delay(100); } void loop(){ digitalWrite(4,LOW); digitalWrite(5,HIGH); digitalWrite(8,LOW); digitalWrite(9,HIGH); int dis_L = analogRead(0); int dis_R = analogRead(1); Serial.print("L:"); Serial.print(dis_L); Serial.print(" R:"); Serial.println(dis_R); if(dis_L > 450){ digitalWrite(13,HIGH); digitalWrite(4,HIGH); //stop digitalWrite(5,LOW); digitalWrite(8,HIGH); digitalWrite(9,LOW); delay(200); digitalWrite(4,LOW); //stop digitalWrite(5,LOW); digitalWrite(8,LOW); digitalWrite(9,LOW); delay(1000); digitalWrite(4,HIGH); //back digitalWrite(5,LOW); digitalWrite(8,HIGH); digitalWrite(9,LOW); delay(500); digitalWrite(4,LOW); //turn digitalWrite(5,HIGH); digitalWrite(8,HIGH); digitalWrite(9,LOW); delay(300); digitalWrite(13,LOW); } if(dis_R > 450){ digitalWrite(13,HIGH); digitalWrite(4,HIGH); //stop digitalWrite(5,LOW); digitalWrite(8,HIGH); digitalWrite(9,LOW); delay(200); digitalWrite(4,LOW); //stop digitalWrite(5,LOW); digitalWrite(8,LOW); digitalWrite(9,LOW); delay(1000); digitalWrite(4,HIGH); //back digitalWrite(5,LOW); digitalWrite(8,HIGH); digitalWrite(9,LOW); delay(500); digitalWrite(4,HIGH); //turn digitalWrite(5,LOW); digitalWrite(8,LOW); digitalWrite(9,HIGH); delay(300); digitalWrite(13,LOW); } }
Arduino起動。Japaninoに書き込みます。
・動作の様子・(自動で走行しています。)
なんとか寸止めで、壁に衝突せずに進んでいます。軽く感動です。
このように、動き方考える → フローチャート → プログラミング → 実際に動かす で、最初と最後が一致したときの達成感は、相当なもんです。
・備忘録・
1.最初期に作成されたスケッチであるため、「センサーの値をもとに、モーターを制御できているか」というチェックの意味で、「まず停止する」という動作が挿入されている。(とにかくこのスケッチにたどりつくまで、無反応で壁に突撃し、メンバーが頭を抱える姿が頻繁に目撃された。)
2.当初は割り込み(attachInterrupt)でスケッチを製作しようと試みたが、それだとdelay()を使えないということが判明し、少なくともこの時点でのプログラミング能力では有効なスケッチを作れなかった。(指導もできなかった…。)
3.スケッチ作成の前に、図のような流れ図(簡易フローチャート)を作成することは非常に有効。思いついた当人のみならず複数の班員で議論できる。条件分岐が多くなるスケッチを、整理、確認しながら作成できるのでミスが減る。
4.13番のHIGH/LOWは基板上のLEDでチェックできるので有効活用
5.前進状態から障害物を見つけて停止するときは、2つのモーターをSTOPさせるのではなく、一瞬逆転させるようにプログラムすることで、ピタリと止まる。
6.どちらのセンサーが反応したかで旋回の方向がかわるようになっている。それは、一方にのみ旋回するプログラムでは、複数回障害物に反応した場合一巡して元の位置に戻ってきてしまうからである。
(ダンゴムシの交替性転向反応のようなものを模索した結果であった。…らしい。)
・FAQ よくある質問・
A.メンバーの名前の頭文字です。実際にはSASAHARAと呼ばれていました。
A.次回エントリ エピソード4をお楽しみに。
・内部リンク・
エピソード4: 障害物回避②工事中
Japaninoを用いたマイコンロボット製作に戻る
スケッチがなんだか野暮ったい?
次のようにしてもいい、かもしれない。
int dis_L = 0; int dis_R = 0; void setup(){ pinMode(3,OUTPUT); pinMode(4,OUTPUT); pinMode(5,OUTPUT); pinMode(8,OUTPUT); pinMode(9,OUTPUT); pinMode(13,OUTPUT); analogWrite(6,100); analogWrite(10,100); delay(100); } void loop(){ go_st(0); if(dis_L > 450){ digitalWrite(13,HIGH); back(200); stopping(1000); back(500); turn_right(300); digitalWrite(13,LOW); } if(dis_R > 450){ digitalWrite(13,HIGH); back(200); stopping(1000); back(500); turn_left(300); digitalWrite(13,LOW); } } void go_st(int i){ digitalWrite(4,LOW); digitalWrite(5,HIGH); digitalWrite(8,LOW); digitalWrite(9,HIGH); delay(i); } void back(int i){ digitalWrite(4,HIGH); digitalWrite(5,LOW); digitalWrite(8,HIGH); digitalWrite(9,LOW); delay(i); } void turn_left(int i){ digitalWrite(4,HIGH); digitalWrite(5,LOW); digitalWrite(8,LOW); digitalWrite(9,HIGH); delay(i); } void turn_right(int i){ digitalWrite(4,LOW); digitalWrite(5,HIGH); digitalWrite(8,HIGH); digitalWrite(9,LOW); delay(i); } void stopping(int i){ digitalWrite(4,LOW); digitalWrite(5,LOW); digitalWrite(8,LOW); digitalWrite(9,LOW); delay(i); }
…未検証です。