今回は、ついに、センサーとモーターを使って、前方に障害物があれば、それを回避する動作を行います。壁を乗り越えはしませんが、ぶち当たって止まることなく、回避して進むということが出来るようになります。
<今回やってみること>
それぞれ、他のBlogで接続図など詳細を記載していますので、よかったら覗いて見て下さい。
(青線のリンク参照下さい)
①ロボットを前進させる。(モーターを複数台(8個)同時に動かす)
②センサーで障害物を検知する。
③検知したら、ロボットを旋回させる。
④旋回後、障害物が無くなれば前進する。
1.よっしゃー!
尚、今回は、
●モーター :I2C通信、
●入力センサー :Arduinoと直接シリアル通信
で動作させます。
旋回の動画です。4倍速にしたら、ちょっとアニメっぽくなってしまいました。(笑)
2.いつものように接続図から
①Arduino Uno ~ モータードライバー ~サーボモーター :A4 ⇔ SDA、A5 ⇔ SCL
※サーボは、黄色のリード線と黄色のピンを合わせる。
②Arduino Uno ~ 赤外線距離センサーモジュール(GP2Y0A21YK0) :A0 ⇔ Vout
3.そして、スケッチ(プログラム)
<考え方>
①まず、今までやった、ロボットの歩行とセンサーの値による判定で次の動作を決めるプログラムです。
②センサーはあるタイミングで、障害物が目の前にないか確認。
③何もなければ、そのまま前進。
④もし、目の前に障害物があれば、横に移動するため、旋回動作に入ります。
⑤旋回後、何も無くなれば、そのまま前進。
⑥センサーでの測定値は、モニターできるように、シリアルモニターに表示させます。
⑦今回はWhileを使わず、そのまま、動作の行を複製しました。
(デバッグしやすいように。あと、旋回は2回にしています)
※簡単ですが、この繰り返しで連続で障害物を回避できると思います。
(実際は、もう少し複雑。センサーの位置や、旋回方向や角度などもう少し細かい調整が必要です)
さて、今回作成したスケッチ(プログラム)です。
(ちょっと、長いです)
//センサーの値で、方向転換(旋回)して歩く。
#include<Wire.h>
#include<Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
#define SERVOMIN 102 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX 492 // this is the 'maximum' pulse length count (out of 4096)
int val; //Sensorの入力をいれる変数
void setup(){
pwm.begin();
pwm.setPWMFreq(50); // Analog servos run at ~50 Hz updates
servo_write(0,90);
Serial.begin(9600); //シリアル通信の準備
}
void servo_write(int n, int ang){ // 動かすサーボと角度を引数に持つ
ang = map(ang, 0, 180, SERVOMIN, SERVOMAX); // 角度(0~180)をPWMのパルス幅(102~492)へ変換
pwm.setPWM(n, 0, ang);
}
void loop(){
//起動したら、まず、前方に障害物が無いか確認します。(センサー値読取)
val = analogRead(A0); // A0ピンの入力を読み、valにいれる(安定読取のため)
Serial.println(val); // シリアルモニタへ表示させます
// (注釈)開始した瞬間のセンサー値は不安定なので、少し時間をおいて、再度測定して判定します。(安定していれば、1回でOK)
delay(1000);
val = analogRead(A0); // A0ピンの入力を読み、valにいれる(判定測定用)
Serial.println(val); // シリアルモニタへ表示させます。
//旋回させる初期動作 旋回STEP1
//⓪-----<<脚を45°の位置に配置>>-----
//前進する時も、旋回する時も初期状態として、始めやすいのでここから始めます。
// 0番ピンのサーボに角度45度を指示
servo_write(0,45);
// 1番ピンのサーボに角度135度を指示
servo_write(1,135);
// 2番ピンのサーボに角度135度を指示
servo_write(2,135);
// 3番ピンのサーボに角度45度を指示
servo_write(3,45);
delay(1000);
//以下の文字の大きさが違う範囲が、障害物が無いと判定した時の、前進動作です。
if (val <300) {
//valの値が300より小さい時、前進動作します。
//digitalWrite(LED_PIN1, HIGH);
//動作させる前に、上の命令で、LEDなどで判定できているか確認する方法もあります。
//①-----<<前進歩き>>-----
//②-----<<準備動作>>-----
//3番ピンのサーボに角度90度を指示、5番ピンのサーボを少し持ち上げ
servo_write(5,70);
delay(500);
servo_write(1,90);
delay(1000);
servo_write(5,90);
delay(1000);
//③-----<<移動、前進>>-----
// 0番ピンのサーボに角度10度を指示
servo_write(0,10);
// 1番ピンのサーボに角度135度を指示
servo_write(1,135);
// 2番ピンのサーボに角度90度を指示
servo_write(2,90);
// 3番ピンのサーボに角度45度を指示
servo_write(3,45);
delay(1000);
//④-----<<準備動作>>-----
servo_write(6,70);
delay(500);
servo_write(2,170);
delay(1000);
servo_write(6,90);
delay(1000);
//⑤-----<<準備動作>>-----
servo_write(4,110);
delay(500);
servo_write(0,90);
delay(1000);
servo_write(4,90)
delay(1000);
val = analogRead(A0); //A0ピンの入力を読み、valにいれる (安定して読取るため)
Serial.println(val); //シリアルモニタへ表示させます
//⑥-----<<移動、前進>>-----
// 0番ピンのサーボに角度45度を指示
servo_write(0,45);
// 1番ピンのサーボに角度170度を指示
servo_write(1,170);
// 2番ピンのサーボに角度135度を指示
servo_write(2,135);
// 3番ピンのサーボに角度90度を指示
servo_write(3,90);
delay(1000);
//⑦-----<<準備動作①と同じ形にする>>-----
servo_write(7,110);
delay(500);
servo_write(3,10);
delay(1000);
servo_write(7,90);
delay(1000);
} else {
//valの値が300より大きい時、以下の旋回動作します。(障害物があるという判定)
//digitalWrite(LED_PIN1, LOW);
//LEDを消灯させれば、判定結果をモニターすることができます。
//以下、旋回動作になります。
// 1回目
//1-⓪’-----<<準備動作 :45°から胴体だけ旋回>>-----
// 0番ピンのサーボに角度10度を指示
servo_write(0,10);
// 1番ピンのサーボに角度90度を指示
servo_write(1,90);
// 2番ピンのサーボに角度90度を指示
servo_write(2,90);
// 3番ピンのサーボに角度10度を指示
servo_write(3,10);
delay(1000);
//1-①-----<<旋回のための STEP1>>-----
//5番ピンの脚(サーボ)を少し持ち上げて、1番ピンのサーボに角度90度→170度を指示、
servo_write(5,70);
delay(500);
servo_write(1,170);
delay(1000);
servo_write(5,90);
delay(1000);
//1-②-----<<旋回 STEP2>>-----
//同様に7番ピンの脚を少し持ち上げて、3番ピンのサーボに角度10度→90度を指示、
servo_write(7,110);
delay(500);
servo_write(3,90);
delay(1000);
servo_write(7,90);
delay(1000);
//1-③-----<<旋回 STEP3>>-----
servo_write(6,70);
delay(500);
servo_write(2,170);
delay(1000);
servo_write(6,90);
delay(1000);
//1-④-----<<旋回 STEP4>>-----
servo_write(4,110);
delay(500);
servo_write(0,90);
delay(1000);
servo_write(4,90);
delay(1000);
// 2回目
//2-①’-----<<45°から旋回>>-----
// 0番ピン
servo_write(0,10);
// 1番ピン
servo_write(1,90);
// 2番ピン
servo_write(2,90);
// 3番ピン
servo_write(3,10);
delay(1000);
//2-②-----<<旋回 STEP1>>-----
servo_write(5,70);
delay(500);
servo_write(1,170);
delay(1000);
servo_write(5,90);
delay(1000);
//2-③-----<<旋回 STEP2>>-----
servo_write(7,110);
delay(500);
servo_write(3,90);
delay(1000);
servo_write(7,90);
delay(1000);
//2-④-----<<旋回 STEP3>>-----
servo_write(6,70);
delay(500);
servo_write(2,170);
delay(1000);
servo_write(6,90);
delay(1000);
//2-⑤-----<<旋回 STEP4>>-----
servo_write(4,110);
delay(500);
servo_write(0,90);
delay(1000);
servo_write(4,90);
delay(1000);
4.ポイント
①今回は、以前に確認したプログラムの組合せなので、最初は、センサーの判定ができているか確認するために、IF文の後にLED点灯のプログラムを仕込んで、条件が成立した時に、判定されているか確認されてもいいと思います。(特にうまく行かなかった場合)
②センサーの測定値をモニタリングして、どの値になれば(どのくらい近づいたら)旋回させるか調整してください。
モニタリング(シリアルモニタ)で確認した例は下の様です。
5.最後に
なんとか、ロボットが判定して衝突を回避できそうです。正直、自分でもここまでできるか、不安な部分がありました。センサーを取り込んだことがないし、判定文でうまく分岐して動くだろうか?など未知の部分が沢山ありました。データの取り込み方や、その値の使い方、判定の仕方も、いろんな人のブログや論文など参考になんとかできました。やってみると、ロボットに剛性が必要な事がわかり、現在もバージョンアップ中です。(ちょっと、別の話ですね)
また、今は調べたら分かるのはスゴイことやと思います。いろいろやりやすいです。昔は調べても分からなかったです。情報がないように見えたし、どこにを調べたら出て来るか分からなかったです。
だから、皆さんもやってみたいことがあったら、とりあえず、やってみたら、何とかなりそうな気がします。マネージメントサイクルとしても、今は、情勢が短期間で変化するのですべてを計画立ててからだと時間が掛かるので、まず、目的を決めたり、必要な準備から始め(プレップ)、その準備に基づいて実際にやってみる(DO)。そして短期間でやってみた結果から分かったこと、次に向けて修正する必要があることなど、レビュー(そのままレビュー)するそうです。(PDRがあるそうです)
あと、以前の目標スペックにはまだ到達していない項目がありました・・。
<目標のスペック>
●四足で歩く。(駆動モーターは8個) →達成!
●電源は電池で、ワイヤレス。 → 電池は容量の大きな電池が必要ですが、バッテリーパックを使えばなんとかなりそうです。ワイヤレス化はパソコンとUSB接続は必要みたい(Arduino IDEと繋がっていないと動かなそう)なので、難しそうです。
●超音波センサーで障害物があれば、一定のアルゴリズムで避けて前進。 →赤外線センサーですが、達成!
●何かを目指して歩くようにしたい。(センサー類をまだ、決めていない) →これも目的地の示し方が超難しそう。
気長に考えていきます。歩行についてもう少し掘り下げて、いろんな歩行を試しにやってみたい気もします。
6足で歩く、クリーピングゲイトでなく馬などのような関節の使い方で歩く、両生類や爬虫類のように歩く。などです。
ラズパイを使った、IoT工作もやってみたいです。
フワフワした感じなので、もう少し調べて、まとめて何をするか決めていきます。
最後まで読んで頂きありがとうございました。みなさんが電子工作って面白そうやん。基板・はんだ付け簡単そうやんやってみよか?プログラミング、なんとかできるんちゃう?オレ、こんなん、作ってみたいけど、他に誰か作った人おらへんかな?とか思って頂けたら嬉しいです。そして、またこのブログも検索してみて下さい。ちょっとバージョンアップしてると思います。つづく。
今回使った部品のリストです。
品名 | 型名(製造元) | 個数 | |
1 | マイコン基板 | Arduino Uno Rev3 ATmega328 マイ コンボード A000066 | 1 |
2 | モータードライバー | PCA9685搭載16チャネル PW M/サーボ ドライバー ←個数注意 | 1 |
3 | サーボモーター | デジタル・マイクロサーボ SG90←個数注意 | 8 |
4 | 接続電線他 | 接続電線、USBケーブル、バルサ材、針金など | 1式 |