- Blog entry posted in 'Electronics and Other Ramblings...', March 20, 2013.
This topic has probably been discussed extensively, but every now and then you still see questions about how to use ultrasound distance sensors. So why the post; it's been a while since my last post and I recently order a batch of HC-SR04, so I needed to get ready to play with those.
The HC-SR04 is a cheap copy of the PING sensor. I've used the PING in numerous occasions, and I've built my own as well. But no matter how much more I tried to lower the cost of the one I built, I could never approach the cost of this HC-SR04. So I decided to order a few and try them out.
First of: how do these work. These sensors work on the SONAR principle. A sound-wave is transmitted; if the wave hits something it will return back (think a tennis ball hitting a wall). The longer (time) it takes the sound-wave to come back, the longer distance it had to travel. That is the concept in a nutshell. There are lots more to consider (e.g. type of material the sound-wave reflects back from, how much distance can the sound-wave cover and still return enough energy to be detected, and many others); but for this post we'll keep it simple.
Both the PING and the HC-SR04 operate very similar to each other. You provide a 10usec (more or less) positive pulse to their input; a short time later they send 8-40kHz pulses; they then listens for those pulses to return; and finally they put out a positive pulse on their output which width (i.e. time between rising edge and falling edge) is proportional to the distance the sound-wave traveled before returning back. The PING happens to use the same pin for input and output; the HC-SR04 uses the individual pins (one for input, one for output). Other than this they are pretty close to each other (HC-SR04 claims a bit more range as well).
To test this system I created the code below using a PIC12F683 and a PING. I also created similar code for the HC-SR04 which I will test as soon as those arrive. The hookup is pretty simple. Connect one I/O from the PIC to the PING I/O; or two I/Os from the PIC to the HC-SR04. Then write the code to (1) provide a 10us pulse, (2) allow for some "dead/wait" time, (3) measure the pulse width of the return pulse, and (4) convert this pulse width into distance.
It would now be good to note that both PING and HC-SR04 only work at +5V (i.e. they do not work at +3.3V - I've confirmed this on the PING, still to confirm on the HC-SR04). That was the reason for building my own a while back.
How to convert from time to distance? Well, sound travels approximately at 340m/s (at standard altitude and temperature). The time reported by either sensor will be the time it took for the sound-wave to hit the target and return to the sensor, the sound-wave essentially traveled twice the distance (i.e. round-trip). Since we're interested in the distance to the target; this reported time must be divided in half. This means that we can represent distance as one of two ways:
1) D (inches) = 0.5 * Time (round-trip in usec) * 74_in/us
2) D (centimeters) = 0.5 * Time (round-trip usec) * 29_cm/us
Note the 0.5 term in from of the round-trip time, effectively measuring only the one-way trip (i.e. distance-to-target, not the distance-to-target-and-back).
Below is tested code used for the PING sensor. The PC was used to read the returns.
'Author: languer (©2013)
'Pin Allocation:
'PIN# Main_Fn Secondary_Fn
'GP0 -> OUT_RS232 ICSP-DAT
'GP1 -> N/A ICSP-CLK
'GP2 -> N/A
'GP3 -> N/A MCLR
'GP4 -> IO_SONAR
'GP5 -> N/A
'Usage Information:
'RS232 Baud Rate: 9600bps
'Comments: PING only works with +5V.
'To use lower voltage, recommend using step-up regulator (e.g NCP1402)
'The SONAR principle determines the distance to an object based on the
'speed of sound(1_inch = 73.746_usec).If a pulse is sent, its distance (in inches)
'to target will be; d_in = (t_usec / 73.746)
'SONAR measures the return pulse, time pulse travels to target and back to the SONAR
'Or d_in = (t_usec / 147.492)
'General Configuration
Define CONF_WORD = 0x33c4
'Oscillator/Clock Configuration for internal 8MHz osc
Define CLOCK_FREQUENCY = 8
OSCCON = 0x71
'Variable Declarations
'>>I/O
Symbol io_rs232_tx = GP0 'rs-232 output
Symbol io_sonar = GP4 'ping/hc-sr04 sensor
'>>Constants
Const _trisio = %11111110
'>>Variables
Dim flag_valid_dist As Bit
Dim _true As Bit
Dim _false As Bit
_true = True
_false = False
'Main Program
main:
Dim distance_in As Word 'distance in inches
Call init()
WaitMs 1000
Serout io_rs232_tx, 9600, CrLf, "Main..."
While _true
flag_valid_dist = False
distance_in = get_distance()
If flag_valid_dist = _true Then
Serout io_rs232_tx, 9600, CrLf, "Distance=", #distance_in, "_in"
Else
Serout io_rs232_tx, 9600, CrLf, "Invalid Measurement"
Endif
flag_valid_dist = False
WaitMs 1000
Wend
End
'init
Proc init()
AllDigital
TRISIO = _trisio
'set TMR1 prescaler to 1:2 -> with 8MHz clock
'this results in tmr1 resolution of 1uS, with maximum of 65.53ms
'or 0.007in resolution, with maximum of 442inches
T1CON.T1CKPS1 = 0
T1CON.T1CKPS0 = 1
'clear global variables
flag_valid_dist = False
Low io_rs232_tx
Low io_sonar
Serout io_rs232_tx, 9600, CrLf, "Power-up..."
End Proc
'get distance procedure
Function get_distance() As Word
Dim echo_time As Word
'transmit pulse
Config io_sonar = Output
High io_sonar
WaitUs 10
Low io_sonar
'receive echo time
'zero-out timer1
TMR1L = 0
TMR1H = 0
PIR1.T1IF = 0
'allow for some holdoff time
WaitUs 200 '8-cycles of 40kHz is 200us, PING recommends 750us
'wait for rising edge of echo pulse
Config io_sonar = Input
While io_sonar = 0
Wend
'turn-on timer1
T1CON.TMR1ON = True
'wait for falling edge of echo pulse or timeout
While io_sonar = 1 And PIR1.T1IF = 0
Wend
T1CON.TMR1ON = False
If PIR1.T1IF Then
echo_time = 0
Else
echo_time.HB = TMR1H
echo_time.LB = TMR1L
flag_valid_dist = True 'flag a valid distance was measured
Endif
'zero-out timer1
TMR1L = 0
TMR1H = 0
PIR1.T1IF = 0
'return value
get_distance = echo_time / 148
End Function
Davoid, February 26, 2018
Beaucoup! Merci!