こんにちは、メカ旦那です!
Arduinoを使ってなんか作品を作りたい!できれば生活の役に立つものが良い!
そう思った私は、ルンバのようなお掃除ロボットを作ることにしました。今回は後編です。前編はこちらで解説しているので、まだ読まれていない方はぜひチェックしてくださいね。
電気回路
回路図
回路図はこんな感じです。(中央にあるモータードライバーはfritzingにパーツ登録が無かったので、別のもので描きました。なので若干配線が違いますが、大まかにはこんな感じです。)
配線が複雑なので、丁寧に解説していきます!
モータードライバー
まずはArduinoとL293Dモータードライバーシールドを配線します。Arduinoのソケットにドライバーのピンを挿すだけで終わりです。デジタルピン、アナログピン、電源ピンそれぞれ正しいソケットに挿入してくださいね。
このモータードライバーってどんな役割があるんですか?ドライバー無しでモーターを直接Arduinoに接続してはダメなんですか?
一般的にモーターの消費電流は、Arduinoの出力電流より大きいです(今回使うモーター「RE-260」の消費電流は700 mA、Arduinoの出力電流は40 mAです)。そのため、直接繋ぐとArduinoが無理に電流を流そうとして、壊れてしまいます!そこで、モーターへの給電は代わりにドライバーから行うことで、Arduinoの故障を防ぎます。ちなみにArduinoからはドライバーに制御信号を出力し、給電タイミングを制御します。
合体することでArduinoのソケットは全て埋まったので、他の機器はドライバーに繋ぎます。Arduinoはドライバー経由で他の機器と信号をやり取りします。
モーター
続いて、モーターをドライバーに接続します。今回はM1、M4の端子を使いました。こちらで解説したように、QIコネクタを圧着しておくと、接続が容易になります。
超音波センサ
障害物検知のため、前方に超音波センサ(HC-SR04)を3つ付けました。
今回のセンサ「HC-SR04」はトランスミッタから超音波を送信し、前方の物体に当たって跳ね返ってきたものをレシーバで受信することで、その物体との距離を測定します。基板から20~4000 mm の距離、15度の角度まで超音波が届きます。
15度ということで、センサ1つだけだと検知範囲が狭いので、3つ付けてみました。
配線について、HC-SR04は4ピンあります。VccとGndは電源供給のためのピンで、Arduino側ではそれぞれ5VとGNDに接続します。Trig(トリガー)は超音波送信の合図信号を出すピンです。超音波は常に出している訳ではなく、Arduinoから一定間隔で合図信号をTrigに送り、トランスミッタから超音波を送信しています。この合図信号は、IT用語ではトリガ信号と呼ばれています。なので、センサのピン名もTrigとなっている訳ですね。このピンはArduinoの14ピンに接続しました。また、Echo(エコー)は超音波を送信した後、返ってくるまでHighになるピンです。このHighの時間を使って障害物との距離を測定します。詳しくはソースコードで解説しますね。EchoはArduinoの16ピンに接続しました。
ちなみに、Arduino側はピンを挿入するだけだと固定が弱いので、はんだづけをしました。
今回は3つのセンサを付けるんですよね。1センサ当たり4ピンあるということは、計12本配線をArduinoに接続するという事ですよね・・・なんかゴチャゴチャしそうですね・・・
下図のように、Arduinoから中央のブレッドボードに4本繋いで、そこから左右のブレッドボード(センサ)に4本ずつ繋ぐようにしました。これにより、Arduinoへの12本接続が不要になり、スッキリしますね!
電池・スイッチ
電池はモータードライバーの動作電圧が4.5~25Vである事と、何回も使用できるように、9Vの充電池を使いました。またスイッチはON・OFFがしやすいように、ロッカースイッチを用いました。配線は下図のようにドライバーの外部電源端子にそれぞれ繋いでいます。どちらもロボットの上面に設置することで、充電のための取り外しと、操作が簡単になるようにしました。
ソースコード
全体
ソースコードはこちらになります!長いので1つ1つ解説します。
// Adafruit Motor Shield library - Version: Latest
#include <AFMotor.h>
//モータードライバーシールド
AF_DCMotor motorRight(1); // モーター(進行方向の右輪)をモーター端子1に接続
AF_DCMotor motorLeft(4); // モーター(進行方向の左輪)をモーター端子4に接続
//超音波センサ
#define trigPin 14 //TrigPinの定義。今回は14ピンに設定。文末の;は不要。
#define echoPin 16 //EchoPinの定義。今回は16ピンに設定。文末の;は不要。
//変数
float echoHigh = 0; //Echo出力のHigh期間を格納
float distance = 0; //計算した距離を格納する変数
const int speed = 100 ; //モータースピード値を格納
void setup(){
//超音波センサ
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
void loop(){
digitalWrite(trigPin, LOW); //trigPinからLOWを出力
delayMicroseconds(10); //10us待機
//超音波を出力するためのトリガ信号発信
digitalWrite(trigPin, HIGH); //トリガ信号HIGH
delayMicroseconds(10); //トリガ信号パルス幅10 usを生成
digitalWrite(trigPin, LOW); //トリガ信号Low
echoHigh = pulseIn(echoPin, HIGH); //echoPinのHigh時間を格納。pulseIn(パルスを入力するピン番号、測定するパルスの種類、タイムアウトまでの時間(省略可))
distance = 340 * echoHigh / 2 / 1000; //音速340m/sを用いて距離計算。echoHighは往復の距離(μm)であるため、2で割り片道に、1000で割りmmに直す
if(distance > 30){ //もし障害物との距離が30 mm 以上なら直進
motorRight.setSpeed(speed); // モータースピード(0~255の範囲)
motorLeft.setSpeed(speed);
motorRight.run(FORWARD); // モーター1とモーター2を正回転させる
motorLeft.run(FORWARD);
}
if(distance <= 30){ //もし障害物との距離が30 mm 以下なら旋回
motorRight.run(RELEASE); // モーターを停止させる(ブレーキ)
motorLeft.run(RELEASE);
delay(1000);
distance = 50; //距離測定を一時停止
motorRight.setSpeed(speed); // 後進
motorLeft.setSpeed(speed);
motorRight.run(BACKWARD);
motorLeft.run(BACKWARD);
delay(1000);
motorRight.setSpeed(speed); //90°旋回
motorLeft.setSpeed(speed);
motorRight.run(FORWARD);
motorLeft.run(BACKWARD);
delay(500);
distance = 340 * echoHigh / 2 / 1000; //距離測定再開
}
}
ライブラリ宣言
まずは冒頭のこちらです!
// Adafruit Motor Shield library - Version: Latest
#include <AFMotor.h>
こちらは、ライブラリである「Adafruit Motor Shield library」の使用宣言です。1から複雑なコードを作成しなくとも、このライブラリを使うことで、簡単にドライバー、モーターを動かすことが可能です。エディターによってライブラリの使用方法が若干異なるので解説します。
エディターが Web editor の場合
先ほどのコードをそのままエディターにコピペするだけでOKです。ただ、せっかくですので、ライブラリを探す方法についても解説します。
1. サイドバーから「Libraries」を選択
2. 「LIBRARY MANAGER」を選択
3.「motor shield」と検索
4.「ADAFRUIT MOTOR SHIELD LIBRARY」の☆をクリック(その下のV2ではないので注意してください!)
5. 先ほどのライブラリが「FAVORITES」に登録されました。こちらをクリック
6. 「INCLUDE」をクリック
7. 「#include <AFMotor.h>」が入力されました。こちらでライブラリ宣言は完了です!
Arduino IDEでは後述の通りライブラリをPCにインストールする必要がありますが、Web editorは不要です。PC容量も消費せずオススメです!
エディターが Arduino IDE の場合
1.「スケッチ」を選択
2.「ライブラリをインクルード」を選択
3.「ライブラリを管理」を選択
4.「motor shield」で検索
5.「Adafruit Motor Shield library」の「インストール」をクリック(その下のV2ではないので注意してください!)
6.インストール完了すると「INSTALLED」と表示されます
7.「#include <AFmotor.h>」と入力。こちらでライブラリ宣言は完了です!
ちなみに、Web editorでは前述の通りインストール不要で「#include <AFmotor.h>」のコピペで終わるので非常に楽です。是非活用を検討してみて下さい!
定義
次は変数の定義です!
AF_DCMotor motorRight(1);
AF_DCMotor motorLeft(4);
モータードライバーの端子1には右輪用モーターを、端子4には左輪用モーターを接続しており、それぞれ、「motorRight」「motorLeft」と定義しています。
#define trigPin 14
#define echoPin 16
Arduinoの14ピンは超音波センサのtrigに繋がっているので「trigPin」、16ピンはechoに繋がっているので「echoPin」と定義しています。 ちなみに、#defineは文末の;は不要です。
float echoHigh = 0;
float distance = 0;
const int speed = 100 ;
echoPin(16ピン)のHigh時間を格納する変数を「echoHigh」、その値を元に物体との距離計算した値を格納する変数を「distance」と定義しました。最初はまだ測定していないので0を格納しています。また、モーターのrpm(毎分の回転速度)を格納する定数を「speed」と定義しました。後述するsetSpeed関数にこのspeedを格納して、回転速度を指定します。0~255の範囲で入力でき、今回は試しに100を入れてみました。
void setup(){
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
trigPinを出力ピン(OUTPUT)、echoPinを入力ピン(INPUT)に定義しています。
超音波センサ
続いて、センサから超音波を送信します。超音波を送信するためには、トリガ信号を出す必要があります。
void loop(){
digitalWrite(trigPin, LOW);
delayMicroseconds(10);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
まず、trigPinをLOWにして、10 μs 維持します。その後、HIGHにして10 μs 維持します。そしてLOWにします。LOWにした瞬間超音波が送信されます。
echoHigh = pulseIn(echoPin, HIGH);
pulseIn関数を使って、echoPinのHIGH時間をechoHighに格納します。
distance = 340 * echoHigh / 2 / 1000;
echoHighは単位が時間 [μs] なので、音速340m/sを掛けて距離に変換します。また、往復になっているので、2で割って片道にし、更に1000で割って [mm] に直します
モーター
最後に、超音波センサで算出した障害物との距離に応じて、モーターを制御します。その前に、重要な関数を2つご紹介します!
離れている場合(障害物との距離が 30 mm 以上)
if(distance > 30){
motorRight.setSpeed(speed);
motorLeft.setSpeed(speed);
motorRight.run(FORWARD);
motorLeft.run(FORWARD);
}
もし障害物と十分離れている場合(距離が30 mm 以上)、両輪とも正回転させて、前進させます。冒頭定義したspeed(rpm : 100)で回転させます。
近い場合(障害物との距離が 30 mm 以下)
if(distance <= 30){
motorRight.run(RELEASE);
motorLeft.run(RELEASE);
delay(1000);
もし障害物と近い場合(距離が30 mm 以下)、まずモーターを停止させて、1000 μs(1 s)維持します。
distance = 50;
次に、距離測定を一時停止すべく、一旦50をdistanceに格納します。(もし一時停止しない場合、この後の後進で距離が30 mm以上になった際に前進し、また障害物に近づく事になるため、それを防止します)
motorRight.setSpeed(speed);
motorLeft.setSpeed(speed);
motorRight.run(BACKWARD);
motorLeft.run(BACKWARD);
delay(1000);
motorRight.setSpeed(speed);
motorLeft.setSpeed(speed);
motorRight.run(FORWARD);
motorLeft.run(BACKWARD);
delay(500);
その後、1000 μs(1 s)後進します。そして、500 μs(0.5 s)右輪を正回転、左輪を逆回転させて旋回します。大体90°回転するように、回転時間は調整しました。
distance = 340 * echoHigh / 2 / 1000;
}
}
旋回が完了した後、距離測定を再開させ、障害物と離れている事を確認したら前進します。まだ近い場合は再度後進・旋回を行います。
まとめ
作り方の説明は以上です!実際に走らせた様子はこちらです。
よかったら参考にしてみて下さい!
コメント