### プロジェクト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シリアル通信と競合し、アップロードが失敗する可能性があります。)
```C
/*
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側に切り替えて電源を入れると、スマートカーは前進しながら自動的に障害物を回避します。
