プロジェクト12:超音波障害物回避タンク

(1)概要:

前のプロジェクトでは、超音波を使った追跡スマートカーを作りました。実際には、同じコンポーネントと同じ配線方法を使い、テストコードを変更するだけで、超音波障害物回避スマートカーに変えることができます。このスマートカーは人の手の動きに合わせて動くことができます。

超音波センサーを使って、スマートカーと前方の障害物との距離を検出し、そのデータに基づいて2つのモーターの回転を制御することで、スマートカーの動きを制御します。

検出

超音波センサーで測定したカーと前方の障害物との距離
(サーボの角度を90°に設定)

a(cm)

超音波センサーで測定したカーと右側の障害物との距離
(サーボの角度を20°に設定)

a2(cm)

超音波センサーで測定したカーと左側の障害物との距離
(サーボの角度を160°に設定)

a1(cm)

設定: サーボの開始角度を90°に設定する

条件1

条件2

条件3

動作

a<20

500ms停止;
サーボの角度を180°に設定し、a1を読み取り、100msの遅延;
サーボの角度を0°に設定し、a2を読み取り、0.1sの遅延。

a1<50
または
a2<50

a1とa2を比較する

a1>a2

サーボの角度を90°に設定し、700ms左回転(PWMを255に設定)
前進(PWMを200に設定)。

a1<a2

サーボの角度を90°に設定し、700ms右回転(PWMを255に設定)
前進(PWMを200に設定)。

条件1

条件2

動作

a<20

a1≥50
かつ
a2≥50

ランダム

サーボの角度を90°に設定し、500ms左回転(PWMを255に設定)
前進(PWMを200に設定)

サーボの角度を90°に設定し、500ms右回転(PWMを255に設定)
前進(PWMを200に設定)

条件

動作

a≥20

前進(PWMを100に設定)

(2)フローチャート:

(3)接続図:

(注意: サーボの茶色、赤色、オレンジ色のワイヤーはそれぞれ拡張ボードのG(GND)、V(5V)、D10に接続します;超音波センサーについては、VCCピンを5v(V)に、Trigピンをデジタル12(S)に、Echoピンをデジタル13(S)に、GndピンをGnd(G)に接続します;前のプロジェクトと同様です。)

(4)テストコード:

(注意: コードをアップロードする前にBluetoothモジュールを接続しないでください。コードのアップロードもシリアル通信を使用するため、Bluetoothシリアル通信と競合し、アップロードが失敗する可能性があります。)

/*
  Keyestudio Mini Tank Robot V3 (Popular Edition)
  lesson 12
  Ultrasonic avoid tank
  http://www.keyestudio.com
*/
#define servoPin 10  //サーボのピン
int a, a1, a2;
#define ML_Ctrl 4  //左モーターの方向制御ピンを定義する
#define ML_PWM 6   //左モーターのPWM制御ピンを定義する
#define MR_Ctrl 2  //右モーターの方向制御ピンを定義する
#define MR_PWM 5   //右モーターのPWM制御ピンを定義する
#define Trig 12
#define Echo 13
float distance;

void setup() 
{
  Serial.begin(9600);
  pinMode(servoPin, OUTPUT);
  pinMode(Trig, OUTPUT);
  pinMode(Echo, INPUT);
  pinMode(ML_Ctrl, OUTPUT);
  pinMode(ML_PWM, OUTPUT);
  pinMode(MR_Ctrl, OUTPUT);
  pinMode(MR_PWM, OUTPUT);
  procedure(90); //サーボの角度を90°に設定する
  delay(500); //500ms遅延する
}

void loop() 
{
  a = checkdistance();  //超音波センサーで検出した前方への距離を変数aに代入する

  if (a < 20) //前方への距離が20cm未満の場合
  {
    Car_Stop();  //ロボットが停止する
    delay(500); //500ms遅延する
    procedure(180);  //超音波パンチルトが左を向く
    delay(500); //500ms遅延する
    a1 = checkdistance();  //超音波センサーで検出した左側への距離を変数a1に代入する
    delay(100); //値を読み取る
    procedure(0); //超音波パンチルトが右を向く
    delay(500); //500ms遅延する
    a2 = checkdistance(); //超音波センサーで検出した右側への距離を変数a2に代入する
    delay(100); //値を読み取る
    
    procedure(90);  //90°に戻る
    delay(500);
    if (a1 > a2) 
    { //左側への距離が右側より大きい場合
      Car_left();  //ロボットが左折する
      delay(700);  //700ms左折する
    } 
    else 
    {
      Car_right(); //700ms右折する
      delay(700);
    }
  } 
  else//前方への距離が20cm以上の場合、ロボットは前進する
  {    
    Car_front(); //前進する
  }

}

void Car_front()
{
  digitalWrite(MR_Ctrl, HIGH);
  analogWrite(MR_PWM, 55);
  digitalWrite(ML_Ctrl, HIGH);
  analogWrite(ML_PWM, 55);
}

void Car_back()
{
  digitalWrite(MR_Ctrl, LOW);
  analogWrite(MR_PWM, 200);
  digitalWrite(ML_Ctrl, LOW);
  analogWrite(ML_PWM, 200);
}

void Car_left()
{
  digitalWrite(MR_Ctrl, HIGH);
  analogWrite(MR_PWM, 55);
  digitalWrite(ML_Ctrl, LOW);
  analogWrite(ML_PWM, 200);
}

void Car_right()
{
  digitalWrite(MR_Ctrl, LOW);
  analogWrite(MR_PWM, 200);
  digitalWrite(ML_Ctrl, HIGH);
  analogWrite(ML_PWM, 55);
}

void Car_Stop()
{
  digitalWrite(MR_Ctrl, LOW);
  analogWrite(MR_PWM, 0);
  digitalWrite(ML_Ctrl, LOW);
  analogWrite(ML_PWM, 0);
}

//サーボを制御する関数
void procedure(byte myangle) 
{
  int pulsewidth;
  for (int i = 0; i < 5; i++) 
  {
    pulsewidth = myangle * 11 + 500;  //パルス幅の値を計算する
    digitalWrite(servoPin, HIGH);
    delayMicroseconds(pulsewidth);   //ハイレベルの時間がパルス幅を表す
    digitalWrite(servoPin, LOW);
    delay((20 - pulsewidth / 1000));  //サイクルは20msなので、残りの時間はローレベルになる
  }
}

//超音波を制御する関数
float checkdistance() 
{
  float distance;
  digitalWrite(Trig, LOW);
  delayMicroseconds(2);
  digitalWrite(Trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(Trig, LOW);
  distance = pulseIn(Echo, HIGH) / 58.20;  //ここでの58.20は2*29.1=58.2から来ている
  delay(10);
  return distance;
}

(5)テスト結果:

テストコードを正常にアップロードし、配線を行い、DIPスイッチをON側に切り替えて電源を入れると、スマートカーは前進しながら自動的に障害物を回避します。