ここでは、クムクムの目の部分に使用されている超音波距離センサー[HC-SR04]を使った距離測定について解説します。
超音波距離センサー HC-SR04
Arduinoを使ったネットの記事でもかなり一般的になっているこのセンサーをクムクムでは使用しています。
このセンサーは、電源をつなぎ、TRIGという足に「測定してね」というパルス(10μ秒)を与えると、片方から40kHzの周波数の超音波を発生させて、その超音波を受けると8回のパルスを返してきます。
このパルスを受信した時間の長さから障害物までの距離を計算で求めることになります。
ここで得た値は超音波という音なので音と空気の振動の公式を使い距離を計算します。
公式 距離=331.5 + 0.6 t (m/sec) tは摂氏温度
制御の方法
※制御のポイントは、TRIG信号は、LOWからHIGHにして10μ秒出した後LOWに戻す。
※そのあとすぐに8回のパルスを受け、そのパルスの長さを取得する。
ということになります。
実際のArduino(クムクム)の接続
HC-SR04は動作に15MAの電流しか必要としないので、Arduinoの5Vから電源をとっても問題ありませんので、このようにシンプルに接続することができます。
ただし、もしお使いのArduinoが3.3V版でしたら、HS-SR04の駆動電圧は5Vなので、正常に動作しない可能性がありますので気を付けてください。
ソースコード
実際にプログラムで書くと下記のようになります。
プログラムの処理についてはソースコード内にコメントで記述してあります。
このソースコードでのポイントは、Setup関数内でのLeonardo独特のwhileでのシリアルが準備できるまで待っている点です。
特にSetupの中でSerialを操作しないのであれば必要はありませんが、もし、Setupの中でprintなどでシリアルにデータを送りたいときは、必ずこのwhileの部分が必要となります。
それからLeonardoがArduinoのシリアルモニターにデータを出力する場合はSerial1を使用します。
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 |
#define Trig 13 #define Echo A3 int Duration; float Distance; void setup() { Serial.begin(9600); while (!Serial) { ; } //Leonardoの場合にはこの部分が必要 pinMode(Trig,OUTPUT); pinMode(Echo,INPUT); } void loop() { digitalWrite(Trig,LOW); //まずLowにする delayMicroseconds(1); //1μ秒まつ digitalWrite(Trig,HIGH); //トリガー信号をあげる delayMicroseconds(11); //10μ秒だが念のため11μ秒HIGHを出す digitalWrite(Trig,LOW); //信号を落とす Duration = pulseIn(Echo,HIGH);//パルスがHIGHの間の時間を測る if (Duration>0) { //パルスの秒から距離を計算する Distance = Duration/2; Distance = Distance*340*100/1000000; Serial.println(Distance);//シリアルに書き出してみる } delay(1000); } |
pulseIn(pin, value, timeout)
引数[pin]からパルスがvalue(HIGHもしくはLOW)の間のパルスを読み取る。
例えばvalueをHIGHとして家いた場合、pulseIn()は、ピンがLOWからHIGHになるのを待ち、時間計測を開始します。そして、[pin]がLOWになるとそれまでの時間時間を関数の戻り値として返します。timeout時間内にパルスが開始されないとタイムアウトし、0を戻します。
引数 | [pin]uint8_t [value]uint8_t state [timeout]unsigned long |
パルスを受け取るピン番号 HIGH または LOW タイムアウト時間(マイクロ秒)デフォルト1μ秒 |
戻り値 | unsigned long | パルスが発生していた時間(マイクロ秒) タイムアウトが発生した時は0 |
シリアルモニター
Arduinoには、プログラミング中にデータがどのようになっているかを知るための方法として、SerialMonitorという方法があります。
上のプログラムでも計測した距離をSerialで表示しているコードがあります。
Serial.println(Distance)
この命令は計算した Distance値をモニター画面に表示してくれます。
printlnはデータを表示した後に自動改行をする関数で、開業したくない場合は printを使用します。
この処理の困ったこと
このプログラムでは、一定時間(10μ秒)パルスを出力するために使用している delayMicrosecondというArduinoの命令を使っていますが、この命令はすべてのプログラムを10μ秒止めてしまうことになります。
また、pluseinというコマンドも同じようにパルスを受け終わるまで一定時間処理が止まってしまいます。そのため、何か別の処理をさせながら距離を測るというような並行処理ができなくなってしまいます。
特に制御系ですと、障害物をよけながら走る車などを思いつくのですが、ある程度まで作っていてハタと気が付くのがこれです。どうもなぜだか動きが機敏ではなく、どっかつまるような動きになる…
そんな困ったことが起こります。
それを回避するためにはプログラム的にしっかりした処理を作りこむ(Arduinoでは限界がありますが)必要があります。
または、新しくハードを取り付けて解決する方法もあります。
下記は現在私が開発をしているボードで、Arduinoとセンサーの間に挟むだけで、リアルタイムに距離データを返してくれるボードです。
まもなく商品化を考えています。
HC-SR04を1つの信号ピンで処理をする方法
信号ピンが足りない時に1本で処理することもできるようです。
私には経験がありませんが、クムクムをご使用いただいているユーザー様(アクシオン様)のブログでは実験をされた結果をご紹介されています。