自動障害物回避車の製作


自動的に障害物を避けて動く車を作成しました



 Arduinoで自動障害物回避車を製作しました。



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