Arduinoで超音波センサHC-SR04の使い方【距離測定】
こんなお悩み、解決します。
- 超音波でなんで距離がはかれるの?
- 超音波センサHC-SR04はどうやってつかうの?
- ArduinoとHC-SR04でプログラミングしたい
この記事では、Arduinoと超音波センサ(HC-SR04)を使った距離測定のやり方を解説します。
HC-SR04は、超音波の送信機と受信機が一体になったセンサモジュールです。信号の送受信は、HC-SR04が自動でやってくれます。ですから、超音波センサの扱いはとても簡単なのです。Arduino初心者の方でも恐れずに超音波センサで遊んでみてくださいね!
つかうもの
まずは、この記事で「つかうもの」をご紹介します。
超音波センサ(HC-SR04)
HC-SR04という超音波センサモジュールを使います。2つの超音波ユニットが付いていて、目のような形をしているのが特徴です。
片方で超音波を発振し、もう片方で跳ね返った超音波を受信します。
Arduino
この記事では「Seeeduino XIAO」を使いましたが、みなさんはお好きなArduinoを使ってみてください。
▼「Seeeduino XIAO」の使い方はこちらを御覧ください。
▼ どのArduinoを選んだら良いかわからない方は、こちらの記事もご参考になさってみてください。
なんで超音波で距離が測定できるの?
超音波で距離が測定できる仕組みを説明しますね。
そもそも超音波とは、人間の耳には「聞こえない」または「聞こえにくい」音域の音のことです。とはいえ聞こえないだけであって音にはかわりありません。
超音波も音も、空気を振動させて遠くへ広がっていきます。そして、その音の速さは決まっているのです。(ココ大事)
音の速さは、気温や気圧によっても変化しますが、たとえば1気圧で20度のときでは「秒速343.7m/s」であることが知られています。
よって、音の速さが分かっているのであれば「音を出してからその音が戻ってくるまでの時間」を測れば距離が測定できます。
つまり距離の計算式は次のようになります。
$$ 距離 = 音速 \times \frac{往復時間}{2} $$
音速の定義
また、音の速さを正確に知りたい場合は、次式で計算できます。ただし、この式は「1気圧で空気が乾燥している」という条件が付きます。また、tは摂氏温度、音速の単位はm/sです。
$$ 音速 = 331.5 + 0.61t$$
距離の計算方法
これらの式を元に、たとえば気温を20度と仮定して、超音波を発信してから受信するまでの往復時間をT秒としてみましょう。距離の計算は次のとおりになります。ただし、距離の単位はメートルです。
$$ 距離 = 331.5 + 0.61 \times 20 \times \frac{T}{2} $$
HC-SR04の使い方
ここまで理解できましたでしょうか?つぎに、超音波センサHC-SR04の使い方を解説します。
▼ HC-SR04の使い方は、次の3つのポイントを理解するだけです。
- Triggerピンを10μ秒だけHighにすると、超音波が発信される
- ❶の発振が終わったタイミングでEchoピンがHighになる
- 跳ね返ってきたパルスを受信するとEchoピンがLowになる
この手順を図で表現すると次のようになります。
距離を測るには、EchoピンがHighからLowに変わるまでの時間だけを知れればよいのです。具体的には、❷から❸の往復時間をArduinoなどで監視することになります。
ちなみに、超音波パルスの周波数は40kHzになります。HC-SR04の詳細はこちらをご覧ください。
HC-SR04とArduinoの配線
お待たせいたしました。ここからは実際に、HC-SR04とArduinoを使っていきます。まずは配線です。
配線
HC-SR04とArduinoの端子をそれぞれ表のように接続してください。
HC-SR04 | Arduino |
---|---|
Vcc | 5V |
Trig | D1 |
Echo | D2 |
GND | GND |
ただし、お使いのArduinoによっては、次のように端子の電圧に気をつけなければなりません。
Seeeduino XIAOで使う場合の注意点
Seeeduino XIAOのGPIOピンと、HC-SR04のEchoピンは直接接続してはダメです。なぜなら、HC-SR04のEchoピンからは5Vの信号が出力されるからです。
Seeeduino XIAOの場合、入力は3.3Vまでとなっています。ですので5V信号を3.3V電圧に変換する必要があります。
簡単な方法として、抵抗を使った分圧法があります。次の図のように、抵抗を2本つかって5V電圧を3.3Vに変換できます。
または、ロジックレベル変換モジュールを使うと、5Vを3.3V信号へ安全に変換できます。ご参考になさってみてください。
HC-SR04のTriggerピンは、入力になります。3.3V〜5Vの電圧を入力できますので、レベルシフトの必要はありません。Seeeduino XIAOのGPIOをそのまま接続できます。
ここら辺は、デジタルピンに使われている「MOSFETの仕組み」を理解すると良いと思います。余裕のある方は、つぎの記事の「MOSFETの使い方」をご参考になさってみてください。
HC-SR04で距離を測定するArduinoプログラミング
配線ができましたら、Arduinoをプログラミングしてみましょう。
Arduino IDEでSketchファイルを新規作成し、つぎのプログラムを書き込んでみましょう。Arduino IDEのシリアルモニターを開いてみてください。距離(cm)が表示されているはずです。超音波センサを動かして、障害物などに向けると距離の値が変化します。
/*
Created by Toshihiko Arai.
https://101010.fun/iot/arduino-hc-sr04.html
*/
#define TrigPin 1 // D1
#define EchoPin 2 // D2
double speedSound = 331.5 + 0.61 * 20; // 20は現在の気温
double distance = 0;
void setup() {
Serial.begin(9600);
pinMode(TrigPin, OUTPUT);
pinMode(EchoPin, INPUT);
}
void loop() {
trigger();
double t = pulseIn(EchoPin, HIGH); // μS
if (t > 0) {
t = t / 2; //往復距離なので半分の時間
distance = t * speedSound * 100 / 1000000; // 距離(cm)を計算
Serial.println(distance);
}
delay(500);
}
void trigger() {
digitalWrite(TrigPin, LOW);
delayMicroseconds(2);
digitalWrite(TrigPin, HIGH );
delayMicroseconds( 10 );
digitalWrite(TrigPin, LOW );
}
ところで、プログラム中のpulseInは「デジタルピンがHigh状態になっている時間をマイクロ秒で返す」とても便利な関数です。Arduino言語では標準で使える関数になります。
▼ 超音波センサとサーボモータを組み合わせると、レーダーのように物体のうごきに合わせて追従させることもできます。
▼ 動画の動きのしくみはこちらをご覧ください。
距離をOLEDディスプレイに表示させてみよう
さいごに、少し発展としてシリアルモニターではなく「OLEDディスプレイ」へ距離を表示してみましょう。
OLEDの詳しい使い方はこちらの記事をご覧ください。
もちろん液晶ディスプレイ(LCD)を使ってもかまいません。
OLEDを使ったプログラム
さきほどのプログラムを元に、OLEDで文字表示できるように改良してみました。
/*
Created by Toshihiko Arai.
https://101010.fun/iot/arduino-hc-sr04.html
*/
#include <U8g2lib.h>
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
#define TrigPin 1 // D1
#define EchoPin 2 // D2
double speedSound = 331.5 + 0.61 * 20; // 20は現在の気温
void setup() {
Serial.begin(9600);
pinMode(TrigPin, OUTPUT);
pinMode(EchoPin, INPUT);
u8g2.begin();
}
void loop() {
trigger();
double distance = 0;
double t = pulseIn(EchoPin, HIGH); // μS
if (t > 0) {
t = t / 2; //往復距離なので半分の時間
distance = t * speedSound * 100 / 1000000; // 距離(cm)を計算
displayOLCD(distance);
}
delay(500);
}
void trigger() {
digitalWrite(TrigPin, LOW);
delayMicroseconds(2);
digitalWrite(TrigPin, HIGH );
delayMicroseconds( 10 );
digitalWrite(TrigPin, LOW );
}
void displayOLCD(double distance) {
char buf[10];
snprintf(buf, 10, "%.1fcm", distance);
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_crox3hb_tf);
u8g2.drawStr(0, 16, "Distance");
u8g2.drawStr(0, 32, buf);
u8g2.sendBuffer();
}
プログラム中のu8g2.drawStrは、char型で文字を渡さなければなりません。そのため、snprintf関数でdouble値をchar型へ変換させています。
対象物との距離を5cm・10cm・20cm・30cmと変えて測定してみました。写真のように、かなり正確な距離を測定できて驚きです。
▼ Arduino初心者向きの内容となっています。ほかのArduino書籍と比べて図や説明がとてもていねいで、読みやすかったです。Arduinoで一通りのセンサーが扱えるようになります。
▼ 外国人が書いた本を翻訳したものです。この手の書籍は、目からうろこな発見をすることが多いです。
▼ Arduinoの入門書を既に読んでいる方で、次のステップを目指したい人向きの本です。C言語のプログラミングの内容が中心です。ESP32だけでなく、ふつうのArduinoにも役立つ内容でした。