超音波センサーと赤外線センサーを使用して、自動的に障害物を回避して動く車を製作してみました。
低い位置にある障害物を2つの赤外線センサーで感知し、高い位置にある障害物を超音波センサーで
感知するようにしました。
自動障害物回避車と言っても、ただ単に障害物を避けて動く車ということで、AI車ではありません。
いろいろとアルゴリズムを考えながら製作してみましたが、まだまだ改良の余地があるようです。
まずは、製作1号車として下記のように作りました。
車体を真横から見た状態
車体の裏側から見た状態
完成した自動障害物回避車の起動動画です。
下記に回路図を表示しておきます。
モーターの駆動電源は6P型の9V電池を使用し、Arduinoやセンサー類は5Vのリチウムイオン電池
を使用しています。
プログラムのアルゴリズムを次のように考えました。
1.2つの赤外線センサーの障害物チェック
R_IRは右赤外線センサーの読み取り値、L_IRは左赤外線センサーの読み取り値です。
次の流れが良いかどうか分かりませんが、今後、改良していきたいと思っています。
2.超音波センサーの右、左、前の障害物チェック
実際のプログラムでは、distanceの値の範囲は調整して変えています。
(1)右方向のチェック
(2)左方向のチェック
(3)前方向のチェック
上記のアルゴリズムを考えて、次のようなプログラムにしました。
今後も改良していきたいと思います。
#include <Servo.h> const int trigPin = 4; const int echoPin = 5; const int motorL1Pin = 7; const int motorL2Pin = 8; const int motorR1Pin = 9; const int motorR2Pin = 10; const int L_PWM_Pin = 6; //左モーターへのPWM出力 const int R_PWM_Pin = 11; //右モーターへのPWM出力 long duration; // echoPinの読み込み値 int distance; //障害物までの距離、単位cm int R_distance; //右方向の障害物までの距離 int L_distance; //左方向の障害物までの距離 int F_distance; //前方向の障害物までの距離 Servo myServo; void setup() { pinMode(motorL1Pin, OUTPUT); pinMode(motorL2Pin, OUTPUT); pinMode(motorR1Pin, OUTPUT); pinMode(motorR2Pin, OUTPUT); pinMode(L_PWM_Pin, OUTPUT); pinMode(R_PWM_Pin, OUTPUT); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); myServo.attach(3); //3ピンにサーボモーターを取り付ける } void loop() { IRcheck(); //赤外線センサーによる障害物のチェックと動作 UltraRcheck(); //超音波センサー右方向の障害物のチェックと動作 IRcheck(); UltraFcheck(); //超音波センサー前方向の障害物のチェックと動作 IRcheck(); UltraLcheck(); //超音波センサー左方向の障害物のチェックと動作 IRcheck(); UltraFcheck(); //超音波センサー前方向の障害物のチェックと動作 forward(135,120,130); //障害物がない場合は直進、左右のdutyは直進するように調整 } void forward(int Lduty, int Rduty, int keeptime){ analogWrite(L_PWM_Pin,Lduty); analogWrite(R_PWM_Pin,Rduty); digitalWrite(motorL1Pin,HIGH); digitalWrite(motorL2Pin,LOW); digitalWrite(motorR1Pin,HIGH); digitalWrite(motorR2Pin,LOW); delay(keeptime); } void back(int Lduty, int Rduty, int keeptime){ analogWrite(L_PWM_Pin,Lduty); analogWrite(R_PWM_Pin,Rduty); digitalWrite(motorL1Pin,LOW); digitalWrite(motorL2Pin,HIGH); digitalWrite(motorR1Pin,LOW); digitalWrite(motorR2Pin,HIGH); delay(keeptime); } void right(int Lduty, int Rduty, int keeptime){ analogWrite(L_PWM_Pin,Lduty); analogWrite(R_PWM_Pin,Rduty); digitalWrite(motorL1Pin,HIGH); digitalWrite(motorL2Pin,LOW); digitalWrite(motorR1Pin,LOW); digitalWrite(motorR2Pin,HIGH); delay(keeptime); } void left(int Lduty, int Rduty, int keeptime){ analogWrite(L_PWM_Pin,Lduty); analogWrite(R_PWM_Pin,Rduty); digitalWrite(motorL1Pin,LOW); digitalWrite(motorL2Pin,HIGH); digitalWrite(motorR1Pin,HIGH); digitalWrite(motorR2Pin,LOW); delay(keeptime); } void motorStop(int keeptime){ digitalWrite(motorL1Pin,LOW); digitalWrite(motorL2Pin,LOW); digitalWrite(motorR1Pin,LOW); digitalWrite(motorR2Pin,LOW); delay(keeptime); } //超音波センサーによって測定された距離を計算するための関数 int calcDistance(){ digitalWrite(trigPin, LOW); delayMicroseconds(2); // trigPinを10マイクロ秒間HIGH状態に設定します digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); // echoPinを読み込み、音波の伝搬時間をマイクロ秒で返します distance= duration*0.034/2; if(distance < 0){ distance = 20; } return distance; } void IRcheck(){ int R_IR; int L_IR; R_IR = analogRead(A1); // 右IRセンサーから読込む L_IR = analogRead(A0); // 左IRセンサーから読込む if (R_IR < 100 & L_IR >100 ) { stop_back(500); left(130,130,200); //左回転 } else if (R_IR > 100 & L_IR < 100){ stop_back(500); right(130,130,200); //右回転 } else if (R_IR < 100 & L_IR < 100) { stop_back(500); left(130,130,300); //左回転 } else { } } void UltraFcheck(){ myServo.write(83); //forward delay(300); F_distance = calcDistance(); if (F_distance < 13) { stop_back(500); myServo.write(0); //right delay(500); R_distance = calcDistance(); myServo.write(173); //left delay(500); L_distance = calcDistance(); myServo.write(83); //forward delay(300); if(R_distance > L_distance) { right(130,130,300); } else { left(130,130,300); } } } void UltraRcheck(){ myServo.write(45); //right delay(300); R_distance = calcDistance(); if(R_distance < 19) { motorStop(10); left(130,130,50); } } void UltraLcheck(){ myServo.write(134); //left delay(300); L_distance = calcDistance(); if(L_distance < 19) { motorStop(10); right(130,130,50); } } void stop_back(int backtime){ motorStop(80); back(160,160,backtime); motorStop(80); }