Raspberry Developer's Guide: Ultra-sound Sensor




超音波測距模組


Ultrasonic ranging module HC - SR04 provides:
  • 2cm - 400cm non-contact measurement function
  • 測距範圍從  2 公分至 400公分(4 公尺)
  • the ranging accuracy can reach to 3mm
  • 精密度0.3公分

The modules includes ultrasonic transmitters, receiver and control circuit.




  • Vcc 接5V
  • Trig 觸發 (輸入脈波至少10us)
  • Echo 檢測接收回音信號(接收後輸出高準位電壓)
  • Gnd 接地

We power the module using Vcc, ground it using GND, and use our Raspberry Pi to send an input signal to TRIG, which triggers the sensor to send an ultrasonic pulse. The pulse waves bounce off any nearby objects and some are reflected back to the sensor. The sensor detects these return waves and measures the time between the trigger and returned pulse, and then sends a 5V signal on the ECHO pin.

ECHO will be “low” (0V) until the sensor is triggered when it receives the echo pulse. Once a return pulse has been located ECHO is set “high” (5V) for the duration of that pulse. Pulse duration is the full time between the sensor outputting an ultrasonic pulse, and the return pulse being detected by the sensor receiver. Our Python script must therefore measure the pulse duration and then calculate distance from this.

IMPORTANT. The sensor output signal (ECHO) on the HC-SR04 is rated at 5V. However, the input pin on the Raspberry Pi GPIO is rated at 3.3V. Sending a 5V signal into that unprotected 3.3V input port could damage your GPIO pins, which is something we want to avoid! We’ll need to use a small voltage divider circuit, consisting of two resistors, to lower the sensor output voltage to something our Raspberry Pi can handle.

A voltage divider consists of two resistors (R1 and R2) in series connected to an input voltage (Vin), which needs to be reduced to our output voltage (Vout). In our circuit, Vin will be ECHO, which needs to be decreased from 5V to our Vout of 3.3V.


Vout = Vin * R2 / (R1 + R2)

Vout must be below 3.3.

  • Using IO trigger for at least 10us high level signal. 
  • 啟動樹莓派發出至少10us 的觸發脈波到 HC-SR04 模組的trig腳
  • The Module automatically sends eight 40 kHz and detect whether there is a pulse signal back.
  • 使得 HC-SR04 模組產生8個40KHz(25us)超音波的脈波,HC-SR04 模組的Echo腳 變為高準位,等待接收回音信號
  • IF the signal back, through high level , time of high output IO duration is the time from sending ultrasonic to returning.
  • 如果有收到TTL的高電位訊號,那Echo會送出超音波來回的時間,使用者再自己計算音速換算距離。
  • Test distance = (high level time×velocity of sound (340M/S) / 2. 
  • 「距離(cm) = 時間(us) / 2(來回) /29.1 (m/s轉換cm/us)」。 每58.3us的時間為1公分,回音越久接收,Echo腳高準位時間越久,距離越遠。
  • When tested objects, the range of area is not less than 0.5 square meters and the plane requests as smooth as possible, otherwise ,it will affect the results of measuring.
  • 量測物體最好大於0.5公尺平方
  • Suggest to use over 60ms measurement cycle, in order to prevent trigger signal to the echo signal.
  • trigger時間最好大於60ms,以免trig與echo干擾。



A TTL signal must meet an output voltage and current specification, an input voltage and current specification, and a rise/fall time specification. For any given hardware, the signal must also have a minimum pulse width.
Note: All specifications use the following notation:
  • Output Low = OL
  • Output High = OH
  • Input Low = IL
  • Input High = IH
  1. The output voltage and current specifications are as follows:
    • VOL = 0.4 V
    • VOH = 2.4 V
    • IOL = 16 mA
    • IOH = 400 µA 
  2. The input voltage and current specification are as follows:
    • VIL = 0.8 V
    • VIH = 2.0 V
    • IIL = 1.6 mA
    • IIH = 40 µA 
  3. The maximum rise/fall time is 50 ns between VIL and VIH. The minimum pulse width for:
    • NI-STC devices is 10 ns.
    • NI-TIO devices is 5 ns. 

( DC 3 - 5.5V ) 低功耗、超音波感測模組升級版 (HC-SR04+)


超音波感測模組,可以用來偵測距離,也可以偵測物體的移動。但一般市面上常見的超音波感測模組 HC-SR04 使用 DC +5V 作為電源輸入,消耗的電流在 6.5 ~ 7 mA 之間;而賣場這款 HC-SR04+(升級版) 只需要提供介於 DC 3 - 5.5V 之間的電源就能工作,而且消耗的電流只需要 2.5 ~ 3.0mA,能直接使用在更低電壓的環境並提供更小的功率消耗,是一款值得選用的超音波感測模組。

使用的方法與一般的超音波感測模組相同,賣場提供了幾個範例程式,可用來作為撰寫程式的參考。

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)

TRIG = 23 
ECHO = 24

print "Distance Measurement In Progress"

GPIO.setup(TRIG,GPIO.OUT)
GPIO.setup(ECHO,GPIO.IN)

GPIO.output(TRIG, False)
print "Waiting For Sensor To Settle"
time.sleep(2)

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

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

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

pulse_duration = pulse_end - pulse_start

distance = pulse_duration * 17150

distance = round(distance, 2)

print "Distance:",distance,"cm"

GPIO.cleanup()

Another Example,

#Libraries
import RPi.GPIO as GPIO
import time
 
#GPIO Mode (BOARD / BCM)
GPIO.setmode(GPIO.BCM)
 
#set GPIO Pins
GPIO_TRIGGER = 18
GPIO_ECHO = 24
 
#set GPIO direction (IN / OUT)
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)
 
def distance():
    # set Trigger to HIGH
    GPIO.output(GPIO_TRIGGER, True)
 
    # set Trigger after 0.01ms to LOW
    time.sleep(0.00001)
    GPIO.output(GPIO_TRIGGER, False)
 
    StartTime = time.time()
    StopTime = time.time()
 
    # save StartTime
    while GPIO.input(GPIO_ECHO) == 0:
        StartTime = time.time()
 
    # save time of arrival
    while GPIO.input(GPIO_ECHO) == 1:
        StopTime = time.time()
 
    # time difference between start and arrival
    TimeElapsed = StopTime - StartTime
    # multiply with the sonic speed (34300 cm/s)
    # and divide by 2, because there and back
    distance = (TimeElapsed * 34300) / 2
 
    return distance
 
if __name__ == '__main__':
    try:
        while True:
            dist = distance()
            print ("Measured Distance = %.1f cm" % dist)
            time.sleep(1)
 
        # Reset by pressing CTRL + C
    except KeyboardInterrupt:
        print("Measurement stopped by User")
        GPIO.cleanup()

First, import the Python GPIO library, import our time library (so we make our Pi wait between steps) and set our GPIO pin numbering.
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
Next, we need to name our input and output pins, so that we can refer to it later in our Python code. We’ll name our output pin (which triggers the sensor) GPIO 23 [Pin 16] as TRIG, and our input pin (which reads the return signal from the sensor) GPIO 24 [Pin 18] as ECHO.
TRIG = 23
ECHO = 24
We’ll then print a message to let the user know that distance measurement is in progress. . . .
print "Distance Measurement In Progress"
Next, set your two GPIO ports as either inputs or outputs as defined previously.
GPIO.setup(TRIG,GPIO.OUT)
GPIO.setup(ECHO,GPIO.IN)
Then, ensure that the Trigger pin is set low, and give the sensor a second to settle.
GPIO.output(TRIG, False)
print "Waiting For Sensor To Settle"
time.sleep(2)
The HC-SR04 sensor requires a short 10uS pulse to trigger the module, which will cause the sensor to start the ranging program (8 ultrasound bursts at 40 kHz) in order to obtain an echo response. So, to create our trigger pulse, we set out trigger pin high for 10uS then set it low again.
GPIO.output(TRIG, True)
time.sleep(0.00001)
GPIO.output(TRIG, False)
Now that we’ve sent our pulse signal we need to listen to our input pin, which is connected to ECHO. The sensor sets ECHO to high for the amount of time it takes for the pulse to go and come back, so our code therefore needs to measure the amount of time that the ECHO pin stays high. We use the “while” string to ensure that each signal timestamp is recorded in the correct order.
The time.time() function will record the latest timestamp for a given condition. For example, if a pin goes from low to high, and we’re recording the low condition using the time.time() function, the recorded timestamp will be the latest time at which that pin was low.
Our first step must therefore be to record the last low timestamp for ECHO (pulse_start) e.g. just before the return signal is received and the pin goes high.
while GPIO.input(ECHO)==0:
  pulse_start = time.time()
Once a signal is received, the value changes from low (0) to high (1), and the signal will remain high for the duration of the echo pulse. We therefore also need the last high timestamp for ECHO (pulse_end).
while GPIO.input(ECHO)==1:
  pulse_end = time.time()      
We can now calculate the difference between the two recorded timestamps, and hence the duration of pulse (pulse_duration).
pulse_duration = pulse_end - pulse_start
With the time it takes for the signal to travel to an object and back again, we can calculate the distance using the following formula. 
Speed = Distance / Time
The speed of sound is variable, depending on what medium it’s travelling through, in addition to the temperature of that medium. However, some clever physicists have calculated the speed of sound at sea level so we’ll take our baseline as the 343m/s. 
34300 = Distance / ( Time/2 )
We can plug this calculation into our Python script:
distance = pulse_duration x 17150
Now we need to round our distance to 2 decimal places (for neatness!)
distance = round(distance, 2)
Then, we print the distance. The below command will print the word “Distance:” followed by the distance variable, followed by the unit “cm”
print "Distance:",distance,"cm"
Finally, we clean our GPIO pins to ensure that all inputs/outputs are reset
GPIO.cleanup()

  • 寬電壓工作範圍:DC 3V ~ 5.5V
  • 工作溫度:-20 °C ~ +80 °C
  • 低功耗:2.5 mA @ DC +3.3V;3mA @ DC +5.0V
  • 偵測距離:
    • DC 3.3V:2 cm ~ 400 cm
    • DC 5.0V:2 cm ~ 450 cm
  • 偵測角度:15 度 
  • 採用工業級微控制器 (MCU)
  • 軟體、硬體兼容 HC-SR04


留言

熱門文章