こんにちは、「メカのりまき」です。
この記事では、Arduinoで超音波距離センサ(HC-SR04)を使用する方法について、説明したいと思います。
この記事では、タクトスイッチの動作を確認するために、PCとシリアル通信を行ったり、ブザーを鳴らしたりしますので、それらについての知識も必要となります。
以下のリンク先の記事で、シリアル通信やブザーの使い方について説明していますので、シリアル通信やブザーの使い方が分からないという方は、先に以下のリンク先の記事をご覧になることをお勧めします。
また、この記事は「Arduino IDE」の基本的な使い方を、理解していることを前提とした記事となっています。
「Arduino IDE」の使い方は以下のリンク先の記事で説明していますので、「Arduino IDE」の使い方が分からない方は、以下のリンク先の記事を是非ご覧になってください。
目次
本記事で使用するもの
本記事で私が使用した物は以下の通りです。
- 「Arduino IDE2.0.3」をインストールしたPC(Windows11)
- USBケーブル
- Arduino Uno R3(ELEGOO UNO R3でも可)
- ブレッドボード
- 超音波距離センサ(HC-SR04)
- パッシブブザー
- ジャンパーワイヤー
「Arduino Uno R3」の互換ボードであれば、「ELEGOO UNO R3」以外のボードでも、本記事と同様な手順で動作可能だと思われますが、動作検証はしていないので、その点はご了承ください。
以下のリンクのスターターキットを購入した場合、上記で述べた使用するものは、PC以外すべて入手することができます。
Arduinoをまだ購入していないという方やArduinoで動かすことができるたくさんのパーツが欲しいという方は、購入を検討してみてください。
超音波とは
まずは、今回センサが扱う「超音波」について、説明したいと思います。
前回の記事ではブザーで音を鳴らす制御を行い、振動数が大きい程、高い音が鳴るという説明をしました。
しかし、振動数をとても大きくすると、人間の耳では聞くことができない高い音が発生します。
それが「超音波」と呼ばれているものであり、その振動数は20[kHz]以上となります。
超音波距離センサの説明
超音波距離センサ(HC-SR04)は上記で説明した、超音波を利用して、距離を測定するセンサで、以下の写真のような見た目をしています。
超音波距離センサ(HC-SR04)のピンは4つあり、電力を供給するための、「VCCピン」と「GNDピン」、マイコンと信号のやり取りを行うための、「Trigピン」と「Echoピン」があります。
センサの見た目と役割から、人間の目を連想させますが、距離を測定する仕組みは、人間の目と全く異なります。
例えば、人間の目が2つあるように、超音波距離センサの円筒部分は2つありますが、超音波を発生させる円筒と反射してきた超音波を受け取る円筒というように、それぞれが別々の役割を持っています。
そして、超音波を発生させてから、物体に超音波が当たり、反射してきた超音波を受け取るまでの時間を測定することで、距離の測定を可能にしています。
より具体的な流れを説明すると、超音波距離センサ(HC-SR04)は、Trigピンで10[μs]以上のパルス波を受け取ると超音波を発生させて、反射してきた、超音波を受け取るまでの時間に応じた信号をEchoピンで出力するということを行っています。
図でまとめると以下のようになります。
また、センサの測定範囲は2[cm]~400[cm]であり、測定精度は3[mm]となっています。
こういったセンサの情報は購入先のメーカーのデータシートに記載されている場合が多いので、センサがどのような信号のやり取りを行っているか知りたい場合は、購入先のメーカーのデータシートを確認すると良いです。
また、センサの名前が分かっている場合は、「センサの名前 データシート」で検索するとデータシートを確認することが出来る場合があります。
超音波距離センサ(HC-SR04)の信号のやり取りについては、上記で紹介したスターターキットのマニュアルにも載っていますし、以下のリンク先からも確認できます。
Arduinoと超音波距離センサ
上記で説明したように、超音波距離センサ(HC-SR04)は、電源を入れれば勝手に、距離を測定してくれるようなものではありません。
超音波距離センサ(HC-SR04)を扱うには、Trigピンへパルス波を入力するための出力ピンとEchoピンからの信号を受け取るための入力ピンが必要となります。
また、超音波距離センサ(HC-SR04)から得られる情報は、測定した物との距離ではなく、超音波を発生させてから戻ってくるまでの時間となります。
そのため、Arduinoでは超音波を発生させてから戻ってくるまでの時間から距離を計算するスケッチを記述する必要があります。
Trigピンへの入力
Trigピンに対しては、10[μs]以上のパルス波を入力すれば良いので、出力ピンと接続した後に「digitalWrite()」と「delayMicroseconds()」を使って、出力ピンの「HIGH」と「LOW」を切り替えれば良いということになります。
ただし、データシートによると、連続してパルス波を出力する際は、60[ms]以上の時間を空けなければならないそうなので、その点は注意が必要になります。
Echoピンからの出力
Echoピンからの出力は、超音波が発生してから戻ってくるまでの時間「HIGH」となり、それ以外の時は「LOW」となるという特徴を持っています。
つまり、出力が「HIGH」となっている時間を測定すれば、超音波が発生してから戻ってくるまでの時間を知ることが出来るということになります。
そして、Arduinoでは「pulseIn関数」というものを、使用して、簡単に「HIGH」になっている時間や「LOW」になっている時間を測定することができます。
pulseIn関数
「pulseIn関数」は以下のような文を記述するだけで、指定したピンの「HIGH」になっている時間や「LOW」になっている時間を測定することができます。
1 |
pulseIn(8,HIGH); |
上記の文は、まず、指定したピン(上記の場合8番ピン)が「LOW」から「HIGH」になるのを待ち、「HIGH」に変わると同時に時間の計測を始め、「LOW」に戻ったら、そこまでの時間をマイクロ秒[μs]単位の数値で表します。
例えば、指定したピンに、以下の図のような0.2秒のパルス波が入力された場合、「pulseIn(8,HIGH)」の値は、「200000」となります。
ただし、「pulseIn(8,HIGH)」が実行されてから、1秒の間にパルス波が確認できなかった場合、「pulseIn(8,HIGH)」の値は「0」となってしまうので注意が必要となります。
パルス波の確認を待つ時間は、以下のような文を記述することにより、マイクロ秒単位で指定することができます。
1 |
pulseIn(8,HIGH,2500000); |
上記の文では、パルス波の確認を待つ時間を2.5秒としています。
上記では、「HIGH」になっている時間を測定する文について説明しましたが、以下のような文を記述すれば、同じように「LOW」となっている時間を測定することができます。
1 |
pulseIn(8,LOW); |
pulseIn関数の注意点
「pulseIn関数」を使用している間は、別の処理を行うことはできません。
よって、「pulseIn関数」の下に別の処理を記述していた場合、その処理が実行されるのは、パルス波が入力されるか、設定した時間(デフォルトだと1秒)が過ぎた後になります。
例外として、割り込み処理というものを利用すれば、別の処理を行うことができるのですが、「pulseIn関数」の処理を邪魔していまい、「HIGH」または「LOW」になっている時間の測定に誤差が生じることがあるので、お勧めはしません。
また、「tone関数」は実行中に割り込み処理を利用しているので、「pulseIn関数」と同時に実行していた場合、「pulseIn関数」の測定に誤差が生じてしまう可能性があるので注意が必要となります。
距離を測定する方法
距離と時間と速度は以下のような、関係を持っていて、この3つの内の2つの値が分かっていれば、分からないもう1つの値を計算で求めることが出来ます。
つまり、今回求めたい物体との距離を測定するためには、超音波が物体に到達するまでの時間と超音波の速さが分かっていれば良いということになります。
超音波が物体に到達するまでの時間については、センサから得られる超音波を発生させてから戻ってくるまでの時間を半分にすれば求めることができます。
次は、超音波の速度についてですが、実は空気中を伝わる音の速さというのは、振幅や振動数によって変わるものではなく、気温によって変化をし、以下のように表すことが出来ます。
よって、物体との距離を測定するためには、以下のような計算を行えば良いということになります。
距離を測定するための理論についての説明は以上となります。
距離を測定するための理論について、ご理解いただけましたら、次は実際に距離センサを使用して、距離の測定を行っていただこうと思います。
距離を測定する
まずは、距離センサで距離を測定して、測定した距離をシリアルモニタに表示させる方法について説明したいと思います。
空のスケッチを書き込む
回路を作成する前に、空のスケッチ(「ファイル」タブの「New Sketch」をクリックしたときに出てくる何の処理も書かれていないスケッチ)を書き込みます。
そうすることにより、前に書き込んだスケッチが、新しく作成しようとしている回路に影響を及ぼすことを防げます。
新しい回路を作成するときは、いつもこの作業をやっておくと、安全に回路を作成することができます。
回路を作成する
以下のような回路をブレッドボードで作成してください。
スケッチを書き込む
回路が作成できましたら、以下のようなスケッチを書き込んでください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
//TrigとEchoに接続するピンを指定する変数 int Trig=9; int Echo=8; //超音波が往復した時間を入れるための変数を用意 float duration=0; //物体との距離を入れるための変数を用意 float distance=0; //気温を入れるための変数(今回は20℃とする) float temperature=20; void setup() { //シリアル通信の初期処理 Serial.begin(9600); //Trigに接続したピンを出力ピンに設定 pinMode(Trig,OUTPUT); //Echoに接続したピンを入力ピンに設定(デフォルト設定なので省略しても良い) pinMode(Echo,INPUT); } void loop() { //Trigピンにパルス波を入力 digitalWrite(Trig,HIGH); delayMicroseconds(10); digitalWrite(Trig,LOW); //Echoピンからの出力について「HIGH」の時間を測定[μs] duration=pulseIn(Echo,HIGH); //「HIGH」の時間を[μs]から[s]に変換 duration=duration/1000000; //距離の計算を行う[m] distance=(331.5+0.6*temperature)*(duration/2); //計算した距離がセンサの測定範囲内のときシリアルモニタに距離を[mm]で表示 if(distance>=0.02&&distance<=4){ Serial.print("Distance:"); Serial.print(distance*1000); Serial.println(" mm"); } //測定の間隔を500[ms]空ける delay(500); } |
スケッチの解説
スケッチの全体としては、以下の図のような流れで、処理を行っています。
基本的には、これまで説明してきたものを、そのままスケッチにまとめただけとなりますが、誤った距離を表示させないようにするために、43行目に「if文」を使っています。
43 44 45 46 47 |
if(distance>=0.02&&distance<=4){ Serial.print("Distance:"); Serial.print(distance*1000); Serial.println(" mm"); } |
この「if文」は計算した距離が、データシートで確認できるセンサの測定範囲(0.02[m]~4[m])に収まっているかを確認しています。
それにより、パルス波がうまく測定できず、計算した距離が「0」となってしまった場合や、極端に長い距離になってしまった場合に、それらを誤った距離として認識し、シリアルモニタに表示させないようにしています。
ここまでの説明で「変数宣言」や「if文」について、よく分からないと感じた方やもっと詳しく知りたいと思った方は、以下のリンク先の記事で、より詳しい説明をしていますので、是非ご覧になってください。
また、「if文」以外に注意しなくてはならないのは、単位を変換するために、37行目で割り算を行ったり、45行目で掛け算を行ったりしているところです。
37 |
duration=duration/1000000; |
上記の文では、[μs]を[s]に直すために、1000000で割り算を行っています。
スケッチ内で割り算を行うためには、「÷」ではなく「 / 」を使用します。
45 |
Serial.print(distance*1000); |
上記の文では、[m]を[mm]に直すために、1000で掛け算を行っています。
スケッチ内で掛け算を行うためには、「×」ではなく「 * 」を使用します。
動作の確認
スケッチの内容について、ご理解いただけましたら、次は動作の確認を行っていただこうと思います。
ArduinoをPCに接続した状態でシリアルモニタを開いてください。
すると、以下のように、「Distance: ~ mm」という表示が現れます。
これが、センサで距離を測定した結果であり、センサの前にある物を動かすと、その表示が変化することが確認できます。
ここで、距離を測定する物体が木材、プラスチック、金属などの場合は、割と正確に(大体、誤差が10[mm]以内で)距離を測定することができるのですが、布やスポンジなど、音を吸収しやすい物体の場合は、距離の測定が正確に行えなくなるので注意してください。
距離に応じてブザーを鳴らす
距離が測定できることが確認できましたら、次は「if文」とブザーを利用し、測定した距離に応じて音を鳴らすような制御を行っていただこうと思います。
回路を作成する
先ほどの回路にパッシブブザーを追加して、以下のような回路を作成してください。
スケッチを書き込む
回路が作成できましたら、以下のスケッチを書き込んでください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
//TrigとEchoに接続するピンを指定する変数 int Trig=9; int Echo=8; //ブザーに接続するピンを指定する変数 int buzzer=2; //超音波が往復した時間を入れるための変数を用意 float duration=0; //物体との距離を入れるための変数を用意 float distance=0; //気温を入れるための変数(今回は20℃とする) float temperature=20; void setup() { //Trigに接続したピンを出力ピンに設定 pinMode(Trig,OUTPUT); //Echoに接続したピンを入力ピンに設定(デフォルト設定なので省略しても良い) pinMode(Echo,INPUT); //ブザーに接続したピンを出力ピンに設定 pinMode(buzzer,OUTPUT); } void loop() { //Trigピンにパルス波を入力 digitalWrite(Trig,HIGH); delayMicroseconds(10); digitalWrite(Trig,LOW); //Echoピンからの出力について「HIGH」の時間を測定[μs] duration=pulseIn(Echo,HIGH); //「HIGH」の時間を[μs]から[s]に変換 duration=duration/1000000; //距離の計算を行う[m] distance=(331.5+0.6*temperature)*(duration/2); //計算した距離に応じて、音を鳴らす if(distance>=0.02&&distance<0.04){ tone(buzzer,262,250); }else if(distance<0.06){ tone(buzzer,294,250); }else if(distance<0.08){ tone(buzzer,330,250); }else if(distance<0.1){ tone(buzzer,349,250); }else if(distance<0.12){ tone(buzzer,392,250); }else if(distance<0.14){ tone(buzzer,440,250); }else if(distance<0.16){ tone(buzzer,492,250); }else if(distance<0.18){ tone(buzzer,523,250); } //測定の間隔を500[ms]空ける delay(500); } |
動作の確認
スケッチと回路が正しければ、以下の動画のように、物体との距離に応じて、決まった高さの音が鳴るのが確認できます。
スケッチの解説
スケッチの内容は、先ほどのスケッチのシリアルモニタへ出力させる部分を、「else if」で細かく条件を分けて、「tone関数」により、決まった高さの音をブザーで鳴らすように変えたものとなっています。
ピアノの音階と振動数(tone関数の値)の関係はおおよそ(小数点以下を四捨五入した場合)、以下のようになっています。
音階名 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
ド | 33 | 65 | 131 | 262 | 523 | 1047 | 2093 |
ド# | 35 | 69 | 139 | 277 | 554 | 1109 | 2217 |
レ | 37 | 73 | 147 | 294 | 587 | 1175 | 2349 |
レ# | 39 | 78 | 156 | 311 | 622 | 1245 | 2489 |
ミ | 41 | 82 | 165 | 330 | 659 | 1319 | 2637 |
ファ | 44 | 87 | 175 | 349 | 698 | 1397 | 2794 |
ファ# | 46 | 93 | 185 | 370 | 740 | 1480 | 2960 |
ソ | 49 | 98 | 196 | 392 | 784 | 1568 | 3136 |
ソ# | 52 | 104 | 208 | 415 | 831 | 1661 | 3322 |
ラ | 55 | 110 | 220 | 440 | 880 | 1760 | 3520 |
ラ# | 58 | 117 | 233 | 466 | 932 | 1865 | 3729 |
シ | 62 | 123 | 247 | 494 | 988 | 1976 | 3951 |
「tone関数」について、よく分からないという方は、以下のリンク先の記事で詳しく説明していますので、是非ご覧になってください。
Arduinoで超音波距離センサ(HC-SR04)を使用する方法についての説明は以上となります。
今回説明したスケッチを、少し変更すれば、距離に応じて音を変えるだけでなく、物体を検知したら、LEDを点灯させるようにしたり、物体との距離に応じて、モータを動かしたりするといったことも可能になります。
超音波距離センサ(HC-SR04)と他の物を組み合わせたいときは、是非、今回の記事で説明したことを参考にしていただければと思います。
次回の記事では、Arduinoのアナログ入力とポテンショメータについて説明したいと思います。
本記事はここまでです。ご清覧ありがとうございました。
広告
今回使用した超音波距離センサを追加でいくつか購入したい方は、以下の商品がおすすめです。
また、超音波距離センサを使った車型のロボットを作りたいという方は、以下のような商品もおすすめです。
楽天モーションウィジェットとGoogleアドセンス広告です。
気になる商品がございましたら、チェックをしてみてください。