Arduinoで超音波センサHC-SR04の使い方【距離測定】

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つのポイントを理解するだけです。

  1. Triggerピンを10μ秒だけHighにすると、超音波が発信される
  2. ❶の発振が終わったタイミングでEchoピンがHighになる
  3. 跳ね返ってきたパルスを受信するとEchoピンがLowになる

この手順を図で表現すると次のようになります。

HC-SR04のTriggerとEchoのフロー図
HC-SR04のTriggerとEchoのフロー図

距離を測るには、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に変換する回路図
分圧抵抗で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初心者向きの内容となっています。ほかのArduino書籍と比べて図や説明がとてもていねいで、読みやすかったです。Arduinoで一通りのセンサーが扱えるようになります。

▼ 外国人が書いた本を翻訳したものです。この手の書籍は、目からうろこな発見をすることが多いです。

▼ Arduinoの入門書を既に読んでいる方で、次のステップを目指したい人向きの本です。C言語のプログラミングの内容が中心です。ESP32だけでなく、ふつうのArduinoにも役立つ内容でした。

関連記事