hsuetsugu’s diary

ITの技術的なことに関して主に書きます。Rとpythonとd3.jsとAWSとRaspberryPiあたりを不自由なく使いこなせるようになりたいです。

(35連休)14日目:Raspberry Pi(超音波距離センサーをつけてみた)

前回、LEDの制御をやってみたことで、Raspberry PiのGPIOについて少し理解できてきました。

今回は、超音波距離センサーをつけてみます。使ったのは"HC-SR04"というセンサーです。

HC-SR04 超音波距離センサーモジュール For Arduino

HC-SR04 超音波距離センサーモジュール For Arduino

配線

for Arduinoと書いてますが、特に難しいところはありませんでした。
Byte Creationに従って、こんな感じで配線してます。

  • VCCを5Vへ
  • TrigとEchoはGPIOへ
  • GNDGND

f:id:hsuetsugu:20140828090839j:plain

pythonでセンサーデータを取得

Raspberry PiのOSでRaspbianを使っている場合は、"RPi.GPIO"というpythonのモジュールが最初からインストールされているようなので、特にインストールするべきものはありません。
超音波を発して、前の物体にあたって戻ってくるまでの時間を計測することで、物体までの距離を計る、という仕組みのようです。GPIO.INをGPIO27(13),GPIO.OUTをGPIO17(Pin11)としています。

距離を取得するコードは下記の通りです(上記サイトのものそのままです)。
usonic.py

#!/usr/bin/python

# remember to change the GPIO values below to match your sensors
# GPIO output = the pin that's connected to "Trig" on the sensor
# GPIO input = the pin that's connected to "Echo" on the sensor

def reading(sensor):
    import time
    import RPi.GPIO as GPIO

    # Disable any warning message such as GPIO pins in use
    GPIO.setwarnings(False)

    # use the values of the GPIO pins, and not the actual pin number
    # so if you connect to GPIO 25 which is on pin number 22, the
    # reference in this code is 25, which is the number of the GPIO
    # port and not the number of the physical pin
    GPIO.setmode(GPIO.BCM)

    if sensor == 0:

        # point the software to the GPIO pins the sensor is using
        # change these values to the pins you are using
        # GPIO output = the pin that's connected to "Trig" on the sensor
        # GPIO input = the pin that's connected to "Echo" on the sensor
        GPIO.setup(17,GPIO.OUT)
        GPIO.setup(27,GPIO.IN)
        GPIO.output(17, GPIO.LOW)

        # found that the sensor can crash if there isn't a delay here
        # no idea why. If you have odd crashing issues, increase delay
        time.sleep(0.3)

        # sensor manual says a pulse ength of 10Us will trigger the
        # sensor to transmit 8 cycles of ultrasonic burst at 40kHz and
        # wait for the reflected ultrasonic burst to be received

        # to get a pulse length of 10Us we need to start the pulse, then
        # wait for 10 microseconds, then stop the pulse. This will
        # result in the pulse length being 10Us.

        # start the pulse on the GPIO pin
        # change this value to the pin you are using
        # GPIO output = the pin that's connected to "Trig" on the sensor
        GPIO.output(17, True)

        # wait 10 micro seconds (this is 0.00001 seconds) so the pulse
        # length is 10Us as the sensor expects
        time.sleep(0.00001)

        # stop the pulse after the time above has passed
        # change this value to the pin you are using
        # GPIO output = the pin that's connected to "Trig" on the sensor
        GPIO.output(17, False)

        # listen to the input pin. 0 means nothing is happening. Once a
        # signal is received the value will be 1 so the while loop
        # stops and has the last recorded time the signal was 0
        # change this value to the pin you are using
        # GPIO input = the pin that's connected to "Echo" on the sensor
        while GPIO.input(27) == 0:
          signaloff = time.time()

        # listen to the input pin. Once a signal is received, record the
        # time the signal came through
        # change this value to the pin you are using
        # GPIO input = the pin that's connected to "Echo" on the sensor
        while GPIO.input(27) == 1:
          signalon = time.time()

        # work out the difference in the two recorded times above to
        # calculate the distance of an object in front of the sensor
        timepassed = signalon - signaloff

        # we now have our distance but it's not in a useful unit of
        # measurement. So now we convert this distance into centimetres
        distance = timepassed * 17000

        # return the distance of an object in front of the sensor in cm
        return distance

        # we're no longer using the GPIO, so tell software we're done
        GPIO.cleanup()

    else:
        print "Incorrect usonic() function varible."


print reading(0)

距離を計算しているところは下記の部分で、

timepassed = signalon - signaloff
distance = timepassed * 17000

公式説明文書にある下記の説明をみると、上記コードではcm(センチメートル)単位で距離が計算されることがわかります。

Distance = ( (Duration of high level)(Sonic :340m/s))/2

実行結果(手をかざしながら遠のいていった結果です。)

この通り、10cm弱から2mくらいのところまで、感覚と同程度の値が無事計測されました。

pi@raspberrypi ~ $ sudo python usonic.py
7.29155540466
pi@raspberrypi ~ $ sudo python usonic.py
93.7039852142
pi@raspberrypi ~ $ sudo python usonic.py
114.885568619
pi@raspberrypi ~ $ sudo python usonic.py
160.499334335
pi@raspberrypi ~ $ 
pi@raspberrypi ~ $ sudo python usonic.py
190.840959549
pi@raspberrypi ~ $ sudo python usonic.py
192.543268204

今後やりたいこと

これまでRaspberry Piを使って、下記のようなことをやってきました。

  • OpenCVでリアルタイム顔認識*1
  • 計測した温度・湿度データをfluentdでTreasureDataに格納*2
  • WEBIOPiを用いてスマホからLED制御*3
  • 超音波距離センサーを使ってみる(今回)

この辺を使って、例えば、下記のようなものが作れるといいなーと考えています。

  • お掃除しないお掃除ロボット(前に物体がきたら方向転換)

  超音波距離センサー×サーボ系の制御
  できればカルマンフィルタとかも組み合わせて制御させたい。
  動きの軌跡でもfluentdでTreasureDataに送るか・・・。

  • 前方XXcm以内に人がいたらLEDを光らせる(その意味はわからないけど・・・)

  OpenCV×超音波距離センサー

・・など。

SiriProxyとかも使えるようになりたいし、サーボ系はやったことないので、部品揃えるところからしないと。
という感じです。

そういえば、「インド人の発明家がRaspberry PiでGoogleGlassクローンを制作した」という記事が最近出てました。すごいなあ。
インドの発明家がセクシーとは言えないけどクールなGoogle GlassクローンをRaspberry Piで制作 - TechCrunch