Raspberry Pi 3(ラズベリーパイ3)で超音波距離センサー(HC-SR04)を使う

 9,852 total views,  3 views today

超音波距離センサー(HC-SR04)を買ったので、使ってみた。

測定

超音波距離センサーでは、音速(20.055 (セルシウス温度 + 273.15 )^1/2 )を利用して距離を測定しているので、測定する数値は温度に影響を受けるという。


なので、温・湿度センサー(DHT11)で測定した温度を用いて音速を算出することにした。


また、スイッチを押すごとに距離を測定し、測定した距離と温度をLCDに表示するようにした。


使用した物


5cmと10cmの測定結果

まず、5cmと10cmの距離をそれぞれ5回ずつ測定した結果、下表の通りとなった。

回数 5cm 10cm
1回目 4.63cm 10.88cm
2回目 4.75cm 10.88cm
3回目 4.75cm 10.83cm
4回目 4.77cm 10.85cm
5回目 4.75cm 10.83cm
平均 4.73cm 10.854cm

距離が5cmの場合には平均で3mm程度の誤差が見られ、10cmの場合には平均で8mmほどの誤差が見られた。




15cmと20cmの測定結果

次に、15cmと20cmの距離をそれぞれ5回ずつ測定した結果、下表の通りとなった。

回数 15cm 20cm
1回目 15.09cm 20.05cm
2回目 15.07cm 20.07cm
3回目 15.07cm 20.04cm
4回目 15.07cm 20.06cm
5回目 15.03cm 20.09cm
平均 15.066cm 20.062cm

15cm、20cmともに、平均で0.6mm程度の誤差があった。




25cmと30cmの測定結果

最後に、25cmと30mの距離を5回ずつ測定した結果、下表の通りとなった。

回数 25cm 30cm
1回目 25.01cm 30.02cm
2回目 24.98cm 29.97cm
3回目 25.01cm 30.00cm
4回目 25.01cm 30.00cm
5回目 24.98cm 30.01cm
平均 24.998cm 30.00cm

25cm、30cmともに、1mm未満の誤差しか見られなかった。





とりあえず、今回測定した距離での誤差は全て1cm未満に収まっていた。

スポンサーリンク

もう何個か買って、段差や障害物を自動で避けて動くものを作るのに使おうと思う。

配線とプログラム

配線


プログラム

#!/usr/bin/ebv python
#-*- coding: utf-8 -*-
import time
import RPi.GPIO as GPIO
import smbus
import math
import dht11

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)

#超音波距離センサーの入力(ECHO)と出力(TRIG)
TRIG = 5
ECHO = 6
GPIO.setup(TRIG, GPIO.OUT)
GPIO.setup(ECHO, GPIO.IN)
GPIO.output(TRIG, GPIO.LOW)

#スイッチの入力
GPIO.setup(21, GPIO.IN)

#温・湿度センサーのインスタンス生成(ピン番号4)
instance = dht11.DHT11(pin=4)

# Define some device parameters
I2C_ADDR  = 0x27 # I2C device address
LCD_WIDTH = 16   # Maximum characters per line

LCD_CHR = 1 # Mode - Sending data
LCD_CMD = 0 # Mode - Sending command

LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line

LCD_BACKLIGHT  = 0x08  # On
#LCD_BACKLIGHT = 0x00  # Off

ENABLE = 0b00000100 # Enable bit

# Timing constants
E_PULSE = 0.0005
E_DELAY = 0.0005

#Open I2C interface
#bus = smbus.SMBus(0)  # Rev 1 Pi uses 0
bus = smbus.SMBus(1) # Rev 2 Pi uses 1

def lcd_init():
  # Initialise display
  lcd_byte(0x33,LCD_CMD) # 110011 Initialise
  lcd_byte(0x32,LCD_CMD) # 110010 Initialise
  lcd_byte(0x06,LCD_CMD) # 000110 Cursor move direction
  lcd_byte(0x0C,LCD_CMD) # 001100 Display On,Cursor Off, Blink Off 
  lcd_byte(0x28,LCD_CMD) # 101000 Data length, number of lines, font size
  lcd_byte(0x01,LCD_CMD) # 000001 Clear display
  time.sleep(E_DELAY)

def lcd_byte(bits, mode):
  # Send byte to data pins
  # bits = the data
  # mode = 1 for data
  #        0 for command

  bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT
  bits_low = mode | ((bits<<4) & 0xF0) | LCD_BACKLIGHT

  # High bits
  bus.write_byte(I2C_ADDR, bits_high)
  lcd_toggle_enable(bits_high)

  # Low bits
  bus.write_byte(I2C_ADDR, bits_low)
  lcd_toggle_enable(bits_low)

def lcd_toggle_enable(bits):
  # Toggle enable
  time.sleep(E_DELAY)
  bus.write_byte(I2C_ADDR, (bits | ENABLE))
  time.sleep(E_PULSE)
  bus.write_byte(I2C_ADDR,(bits & ~ENABLE))
  time.sleep(E_DELAY)

def lcd_string(message,line):
  # Send string to display

  message = message.ljust(LCD_WIDTH," ")

  lcd_byte(line, LCD_CMD)

  for i in range(LCD_WIDTH):
    lcd_byte(ord(message[i]),LCD_CHR)

def reading(sensor):
    result = instance.read() #温度取得
    c = result.temperature
    if result.is_valid():
        lcd_init()
        if sensor == 0:
            time.sleep(0.3)

            GPIO.output(TRIG, True)
            time.sleep(0.00001)
            GPIO.output(TRIG, False)

            while GPIO.input(ECHO) == 0:
                signaloff = time.time()

            while GPIO.input(ECHO) == 1:
                signalon = time.time()

            t = signalon - signaloff
            v = 20.055 * math.sqrt(c + 273.15)  #絶対温度を用いない場合:v = 331.5 + 0.61 * result.temperature
            print(str(v))
            d = v * t  * 50
            temp = "Temp: " + str(c + 273) + "K("+ str(c) + "C)" 
            distance = str(math.floor(d *100) /100)+ "cm"
            print(temp)
            print(distance)
            lcd_string(distance, LCD_LINE_1)
            lcd_string(temp, LCD_LINE_2)
        else:
            print "Incorrect usonic() function varible"

try:
    while True:
      if GPIO.input(21) == GPIO.HIGH:
          reading(0) #超音波距離センサーの値取得
          time.sleep(1.5)
          print("ready")
except KeyboardInterrupt:
    pass
finally:
  LCD_BACKLIGHT = 0x00
  lcd_byte(0x01, LCD_CMD)
  GPIO.cleanup()

まとめ

  • 超音波距離センサー(HC-SR04)を使ってみた
  • 誤差はそれほど大きくなかった(1cm未満)
  • 障害物を避けて動くものを作るのに使う