🤖

超音波距離センサの使い方

2023/01/07に公開

仕様

https://akizukidenshi.com/catalog/g/gM-11009/

項目
測距範囲 2cm 〜 4m
分解能 3mm
電源電圧 5V
動作電流 15mA
トリガー信号 10μs
エコー出力信号 反射(往復)時間

配線

モジュール側 Arduino 側
Vcc 5v
Trig D8
Echo D9
Gnd GND

コード

#define TRIG 8
#define ECHO 9

#define TEMPERATURE 15
#define SOUND_SPEED (331.5 + 0.61 * TEMPERATURE)

void setup() {
  Serial.begin(9600);

  pinMode(TRIG, OUTPUT);
  pinMode(ECHO, INPUT);
}

void loop() {
  // TRIG をいったん LOW にしたのち、
  digitalWrite(TRIG, LOW);
  delayMicroseconds(2);  // ← どこからきた値?

  // しばらく HIGH にすると「やっほー」と叫ぶ
  digitalWrite(TRIG, HIGH);
  delayMicroseconds(10); // ← 仕様にある「トリガー信号」の値から来ている
  digitalWrite(TRIG, LOW);

  // すると、やまびこが発生する
  // ECHO が HIGH から LOW に変わるまでがやまびこ総往復時間になる
  // タイムアウトした場合は 0 を返す(初期値1秒)
  double total_duration = pulseIn(ECHO, HIGH);

  // タイムアウトしていない場合にのみ時間から距離を計算する
  if (total_duration > 0) {
    double half_duration = total_duration / 2;
    double distance = SOUND_SPEED * 100 * half_duration / ((uint32_t)1000 * 1000);
    Serial.println(distance);
  }

  delay(60); // 次の計測までに 60ms 以上開けるべしとされている
}

対象物との距離をシリアルモニタに表示する。

仕組み

  1. TRIG をいったん LOW にしたのち、しばらく HIGH にすると「やっほー」と叫ぶ
  2. すると、やまびこが発生する
  3. ECHO が HIGH から LOW に変わるまでがやまびこ総往復時間になる
  4. 距離 = 速さ * 時間 に当てはめて距離を求める

距離を求める

1秒 : 秒速340メートル = 時間μ秒 : 距離

距離をセンチメートル、時間を秒に統一する。

1 : (340 * 100) = (時間 / (1000 * 1000)) : 距離

並べ替えて無駄なかっこを取る。

距離 = (340 * 100) * (時間 / (1000 * 1000))
距離 = 340 * 100 * 時間 / (1000 * 1000)

それがこれ。

double distance = SOUND_SPEED * 100 * half_duration / ((uint32_t)1000 * 1000);

音速の定義

https://ja.wikipedia.org/wiki/音速

331.5 + 0.61 t (※) (m/s) (※ t は摂氏温度)
常温として15℃を採用することが一般的であり、その場合 340.5(m/s)となる

通常
#define TEMPERATURE 15
#define SOUND_SPEED (331.5 + 0.61 * TEMPERATURE)
簡易版
#define SOUND_SPEED 340.5

最初の待ち時間の2はどこから来た?

digitalWrite(TRIG, LOW);
delayMicroseconds(2);

こちらによると、

https://burariweb.info/electronic-work/arduino-learning/arduino-ultrasonic-sensor-hc-sr04.html

パルス入力(Trig)は最小2μsとなっています。

とのこと。どこを見てわかったんだろう? データシートを見るが中国語でよくわからない

https://akizukidenshi.com/download/ds/rainbow_e-technology/hc-sr04_v20.pdf

計測間隔

エコー信号へのトリガ信号を防止するために、60ms 以上の測定サイクルを使用することを 推奨します。
── ELEGOO のマニュアルより

とあるため最後に delay(60) としている。

はまったこと

1000 * 100016960 になる。

Ruby
(1000 * 1000) & 0xffff  # => 16960

16ビットで切られている。警告が出ない。これは unsigned long 型を明示して 1000ul と書くのが正しい。一方が unsigned long になっていればよい。また (unsigned long)1000 と書いてもよい。(unsigned long)(1000 * 1000) とするのはダメ。1000000 と直接書くのも問題なかった。おそらく long 型になっている。この挙動からコンパイル前に 1000 * 1000 を 1000000 に置換していないのがわかった。また long 型が32ビットでないケースを心配するなら (uint32_t)1000 とする。

Discussion