超音波距離測定モジュールを使う

HC-SR04(その1)


超音波距離測定モジュール(HC-SR04)を入手したので紹介します。
デー タシートはこちらに掲載されています。
ピンは下の写真のように左からVcc、Trig、Echo、Gndの4ピンです。


裏には3つのチップが実装されています。
一番左のチップはLM324(オペアンプ)ですが、あとの2つのチップはマーキングを読み取れませんでした。
というよりもわざとマーキングを消している 感じです。
こ ちらに回路図が公開されています。
一番右の16ピンICはMAX232、真ん中の14ピンICはSTC11の様です。


以下のページにArduinoのサンプルソースがあります。
http://www.instructables.com/id/Simple-Arduino-and-HC-SR04-Example/step3/Upload-the-sketch/

音速は気温に影響を受け、331.5+0.61*気温[m/秒]で求められます。
気温を20度とすると331.5+0.61*20=343.7[m/秒]になります。
343.7[m/秒]→34370[cm/秒]→34.37[cm/ミリ秒]→0.03437[cm/マイクロ秒]となります。
逆算すると1cmに要する時間は29.0951マイクロ秒です。
つまり、音波を発射して戻ってくるまでの往復に要した時間[マイクロ秒]を半分にして、29.0951(≠29.1)で割ってやれば、
気温が20度の時の目的の距離[cm]を得ることが できます。
より正確を求めるならば、気温も同時に測定する必要が有ります。

これをRaspBerryに移植してみました。
/*

 hc-sr04.c

 Raspberry Pi driving the HC-SR04

 to compile : cc hc-sr04.c -o hc-sr04 -lwiringPi

*/
#include <stdio.h>
#include <stdlib.h>
#include <wiringPi.h>

#define    trigPin    8
#define    echoPin    7

int pulseIn(int pin, int level, int timeout)
{
   struct timeval tn, t0, t1;
   long micros;

   gettimeofday(&t0, NULL);
   micros = 0;
   while (digitalRead(pin) != level)
   {
      gettimeofday(&tn, NULL);
      if (tn.tv_sec > t0.tv_sec) micros = 1000000L; else micros = 0;
      micros += (tn.tv_usec - t0.tv_usec);
      if (micros > timeout) return 0;
   }

   gettimeofday(&t1, NULL);
   while (digitalRead(pin) == level)
   {
      gettimeofday(&tn, NULL);
      if (tn.tv_sec > t0.tv_sec) micros = 1000000L; else micros = 0;
      micros = micros + (tn.tv_usec - t0.tv_usec);
      if (micros > timeout) return 0;
   }

   if (tn.tv_sec > t1.tv_sec) micros = 1000000L; else micros = 0;
   micros = micros + (tn.tv_usec - t1.tv_usec);
   return micros;
}

int main (int argc, char **argv) {
  int i,j,k,l,m;
  long duration, distance;

  if(wiringPiSetupGpio() == -1) return 1;
  pinMode(trigPin,OUTPUT);
  pinMode(echoPin,INPUT);

  digitalWrite(trigPin, LOW);  // Added this line
  delayMicroseconds(2); // Added this line
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10); // Added this line
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH, 1000000);
  printf("duration=%d\n",duration);
  distance = (duration/2) / 29.1;
  printf("distance=%d cm\n",distance);
}


Vccは5V、TrigピンはGPIO8、Echoピンは5V→3.3VにレベルシフトしてGOIO7に接続しています。
適当な障害物を置いて実行してみました。



pi@raspberrypi ~/hc-sr04 $ sudo ./hc-sr04
duration=648
distance=11 cm
pi@raspberrypi ~/hc-sr04 $ sudo ./hc-sr04
duration=1257
distance=21 cm
pi@raspberrypi ~/hc-sr04 $ sudo ./hc-sr04
duration=1773
distance=30 cm
pi@raspberrypi ~/hc-sr04 $ sudo ./hc-sr04
duration=2355
distance=40 cm
pi@raspberrypi ~/hc-sr04 $ 

そこそこの精度で障害物までの距離を測ることができます。
部屋の中で一番遠い場所にPCケースを置いて測定してみました。
実際の距離は285cmぐらいです。
pi@raspberrypi ~/hc-sr04 $ sudo ./hc-sr04
duration=16337
distance=280 cm
pi@raspberrypi ~/hc-sr04 $ sudo ./hc-sr04
duration=16459
distance=282 cm
pi@raspberrypi ~/hc-sr04 $ sudo ./hc-sr04
duration=16547
distance=284 cm
pi@raspberrypi ~/hc-sr04 $ sudo ./hc-sr04
duration=16570
distance=284 cm
pi@raspberrypi ~/hc-sr04 $ sudo ./hc-sr04
duration=10259
distance=176 cm
pi@raspberrypi ~/hc-sr04 $ sudo ./hc-sr04
duration=16524
distance=283 cm
pi@raspberrypi ~/hc-sr04 $

時々176cmなどになりますが、そこそこの精度で距離を図ることができます。
データシートによると測定範囲は2cmから400cmとなっていますが、
我が家では400cmも離れたところに障害物を置くことができないので、残念ながら未確認です。

続く...