超音波センサーと赤外線センサーを使用して、自動的に障害物を回避して動く車を製作してみました。
低い位置にある障害物を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);
}