🤖
超音波距離センサの使い方
仕様
項目 | 値 |
---|---|
測距範囲 | 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 以上開けるべしとされている
}
対象物との距離をシリアルモニタに表示する。
仕組み
- TRIG をいったん LOW にしたのち、しばらく HIGH にすると「やっほー」と叫ぶ
- すると、やまびこが発生する
- ECHO が HIGH から LOW に変わるまでがやまびこ総往復時間になる
-
距離 = 速さ * 時間
に当てはめて距離を求める
距離を求める
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);
音速の定義
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);
こちらによると、
パルス入力(Trig)は最小2μsとなっています。
とのこと。どこを見てわかったんだろう? データシートを見るが中国語でよくわからない
計測間隔
エコー信号へのトリガ信号を防止するために、60ms 以上の測定サイクルを使用することを 推奨します。
── ELEGOO のマニュアルより
とあるため最後に delay(60)
としている。
はまったこと
1000 * 1000
は 16960 になる。
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