ESP32

ESP32で超音波距離センサを使って、距離を測定してみます

超音波距離センサを使って、距離の測定を行ってみます。

どれ位の精度があるかわかりませんが、簡単に距離が測定できるのは、ちょっと楽しそうです。

ESP32と超音波距離センサの接続

ESP32と超音波距離センサを接続していきます。

準備するもの

今回準備するものは、以下になります。

  • ESP32
  • ブレッドボード
  • ジャンパーワイヤー
  • 超音波距離センサ

超音波距離センサ

超音波距離センサは、秋月電子通商様から「超音波距離センサー HC-SR04」を購入しました。

主な仕様は以下になります。

  • 測距範囲:2~400cm
  • 電源電圧:DC 5.0V
  • 動作電流:15mA
  • 動作周波数:40kHz
  • トリガ信号:10μS(TTLレベルのパルス波)
  • エコー出力信号:反射(往復)時間
  • サイズ:45×20×15mm

測定範囲が2~400cmです。もっと測定範囲が狭いと思っていたのですが、びっくりです。

超音波センサーは、出力した超音波が障害物に反射して戻ってくるまでに、どの程度時間がかかったかで距離を測定するセンサーです。

接続

超音波距離センサとESP32を以下のように接続します。

プログラム作成

超音波距離センサで距離を測定するためのプログラムを作成していきます。

プログラム

const int TRIG = 15;                  // ECHOピン
const int ECHO = 16;                  // TRIGピン
const int MAX_WAIT = 20000;
double sonic = 331.5 + (27.0 * 0.6);  // 音速

void setup() {
  pinMode(TRIG, OUTPUT);
  pinMode(ECHO, INPUT);
  Serial.begin(115200);
}

void loop() {
  double dist = read_distance();
  Serial.print("dist:");
  Serial.println(dist);
  delay(500);
}

double read_distance() {
  digitalWrite(TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG, LOW);

  double time = pulseIn(ECHO, HIGH, MAX_WAIT);

  Serial.println(time);
  double dist = (time * sonic * 100) / 1000000 / 2;

  return dist;
}

プログラムについて簡単に説明していきます。

4行目で、音速の定数を計算しています。定数は、約340m/sでもよいのですが、温度によって速度が変わるようなので、雰囲気で計算式を追加してみました。実際の温度を測定するセンサーなどはつけていないので、室温(27℃)ベタ打ちです。ちなみに音速の公式は以下になります。340m/sは摂氏温度15℃の場合の音速になります。

 音速(m/s) = 331.5 + (0.6 * 摂氏温度)

7行目でTRIGピン(発信用のピン)を「OUTPUT」に設定しています。

8行目でECHOピン(受信用のピン)を「INPUT」に設定しています。

今回の計測結果は、シリアルモニタで確認するので、9行目でシリアル通信の初期化を行っています。

基本的な動作としては、12~17行目のloop()関数の中で、500msごとに距離を測定して、シリアルモニタに結果を出力する処理になっています。

距離の測定は、19~30行目のread_distance()関数で行っています。

超音波を出力して、障害物に当たって反射してくるまでの時間を計測します。

まずは、20~22行目で10μsだけ超音波を出力します。TRIGの出力をHIGHにすると超音波が出力して、delayMicroseconds(10)で10秒間出力状態を維持して、TRIGの出力をLOWにすることで超音波の出力を停止します。

次に出力した超音波が障害物に反射して、ECHOピンに入力されるまでの時間を計測します。

24行目で、pulseIn()を使用して、ECHOピンの入力がHIGHになるまでの時間を測定しています。

 pulseIn(pin, value, timeout)

  pin:パルスを読み取りたいピンの番号 (int)

  value: 読み取りたいパルスの種類: HIGH または LOW. (int)

  timeout (任意): パルスを何マイクロ秒待つか; 初期値は1秒 (unsigned long)

  戻り値:パルス幅(μs).もし,タイムアウトまでパルスが入力されなかった場合は0 (unsigned long)

  ※Arduinoリファレンス参照

27行目で、取得した時間から距離を計算しています。

 距離(cm) = (時間(μs) * 音速(m/s) * 100) / 1000000 / 2

超音波が往復する距離になるので計算結果を2で割ると、片道の距離が求められます。

距離の単位を「cm」に合わせるために、100(1m=100cm)をかけてます。

またpulseIn()で求めた時間の単位は「μs(マイクロ秒)」なので、単位を秒に合わせるために、1000000(1秒=1000000μs)で割っています。

pulseIn()の結果が「1000μs」だった場合は、

 1000 * (331.5 + (27.0 * 0.6)) * 100 / 100000 / 2 = 17.385cm となります。

動作確認

実際に動作を確認してみます。

障害物をセンサの前に置いて、定規で距離を測りながらセンサの測定値を確認していきます。

厳密ではありませんが、ざっと計測した結果を以下に記載いたします。

実測(cm)センサー測定結果(cm)
54.43
65.51
76.36
87.75
98.78
1010.27
1111.18
1212.31
1313.21
1414.22
1514.88
2019.75
2524.74
3029.35
10099.18

大体の目見当で測定していますので、厳密な結果ではありませんが、そこそこ近しい値になっている気がします。距離が近いほど、なぜか誤差が大きかったです。

シリアルモニタに表示された結果を見ていると、値が結構上下に振れていました。ミリ単位では、そこそこ動く感じです。

室内でエアコンをつけた状態なので、多少は影響があるのかもしれません。

まとめ

ESP32で超音波距離センサを使用して、対象物との距離を測定してみました。

超音波を反射させる障害物を正確に垂直にしたり、正確に距離を測る手段が難しく、測定した結果は大体あっているのかな、程度でしか確認できませんでした。

正直なところ、誤差がどの程度なのかもわかりませんでした。値がパタパタと動きます。

厳密に測定するためには、それなりに治具を作成する必要がありそうです。

測定サイクルですが、データシートでは60ms以上が推奨されていました。今回は500msごとに計測していたので、特に問題はなかったと思います。

時速40kmで1秒間に約11m前進、60msだと67cm前進だと考えると、あまり早く動くものは無理ですが、ある程度の速度のものであれば、十分に衝突防止用センサとして使えそうだと思いました。

参考にした本では、ラジコンの衝突防止用にこのセンサを使っていたので、ぜひともチャレンジしてみたいと思いました。

【参考図書】