Solved - PING alternative HC-SR04 coding problem!
Hi all, it's been quite a while since I used the propeller and I've run into a coding problem while trying to get the HC-SR04 working. Here is my code so far, some of it borrowed from other locations.
I have it running but either my timing is wrong or my distance calculations are wrong.
HC-SR04 Product Page
HC-SR04 datasheet
I am getting unexpected measurement results and modified the code somewhat while trying to figure it out.
Thanks in advance.
I have it running but either my timing is wrong or my distance calculations are wrong.
HC-SR04 Product Page
HC-SR04 datasheet
I am getting unexpected measurement results and modified the code somewhat while trying to figure it out.
Thanks in advance.
{{
Sparkfun's HC-SR04 Ultrasonic Sensor on the Propeller :)
I've only seen this in C code for the Propeller so here it is
in SPIN.
}}
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
TRIG = 1 ' Connected to P1
ECHO = 0 ' Connected to P0
HIGH = 1
LOW = 0
INPUT = 0
OUTPUT = 1
MAX_DIST = 23_200
DEBUG = 1 ' 1 = true, 0 = false
' from Timing.spin
_10us = 1_000_000 / 10 ' Divisor for 10 us
_1ms = 1_000_000 / 1_000 ' Divisor for 1 ms
_1s = 1_000_000 / 1_000_000 ' Divisor for 1 s
' from dualPing.spin
TO_IN_std = 74_641 ' std atmosphere speed of sound, us per inch traveled @ 59F air temperature
TO_CM_std = 29_386 ' std atmosphere speed of sound, us per cm traveled @ 59F air temperature
OBJ
pst : "Parallax Serial Terminal"
VAR
LONG pulse_Start
LONG pulse_Stop
' from Timing.spin
LONG delay
LONG syncpoint
LONG clkcycles
PUB Main | Microseconds, Distance, cnt1, cnt2
waitcnt(clkfreq * 5 + cnt)
pst.start(115200)
' set pin directions
OUTA[TRIG] := HIGH ' Direction not set but set the state low
DIRA[TRIG] := OUTPUT ' Set to Output
OUTA[TRIG] := LOW ' Ensure it is still Low
DIRA[ECHO] := INPUT ' Set the echo input
IF DEBUG == 1
pst.Str(STRING("Directions Set, ready for testing!"))
NL
REPEAT
' main loop
OUTA[TRIG] := HIGH
pause10us(1)
OUTA[TRIG] := LOW
WAITPNE(0, |< ECHO, 0)
cnt1 := CNT
WAITPEQ(0, |< ECHO, 0)
cnt2 := CNT
Microseconds := (||(cnt1 - cnt2) / (CLKFREQ / 1_000_000)) >> 1
if DEBUG == 1
pst.Home
pst.ClearEnd
pst.Dec(Microseconds)
pst.Str(STRING(" us. "))
Distance := Microseconds / 58
IF DEBUG == 1
pst.Dec(Distance)
pst.Str(STRING(" cm."))
pause1ms(100)
PUB Inches(ms) : Distance
''Measure object distance in inches
Distance := ms * 1_000 / TO_IN ' Distance In Inches
PUB Centimeters(ms) : Distance
''Measure object distance in centimeters
Distance := Millimeters(ms) / 10 ' Distance In Centimeters
PUB Millimeters(ms) : Distance
''Measure object distance in millimeters
Distance := ms * 10_000 / TO_CM ' Distance In Millimeters
'from dualPing.spin
PUB calibrate(Tamb)
''Adjust Ping))) calibration constants to reflect ambient
''temperature impact on speed of sound (temperature assumed to be °F)
Tamb += 460
TO_IN := TO_IN_std * (^^(Tamb * 1_000_000)) / (^^518_690_000)
TO_CM := TO_IN * TO_CM_std / TO_IN_std
'From Timing.spin
PUB pause10us(period)
'' Pause execution for period (in units of 10 us)
clkcycles := ((CLKFREQ / _10us * period) - 4296) #> 381 ' Calculate 10 us time unit
WAITCNT(clkcycles + CNT) ' Wait for designated time
'From Timing.spin
PUB pause1ms(period)
'' Pause execution for period (in units of 1 ms).
clkcycles := ((CLKFREQ / _1ms * period) - 4296) #> 381 ' Calculate 1 ms time unit
WAITCNT(clkcycles + CNT) ' Wait for designated time
'From Timing.spin
PUB pause1s(period)
'' Pause execution for period (in units of 1 sec).
clkcycles := ((CLKFREQ / _1s * period) - 4296) #> 381 ' Calculate 1 s time unit
WAITCNT(clkcycles + CNT) ' Wait for designated time
'From Timing.spin
PUB marksync10us(period)
delay := (CLKFREQ / _10us * period) #> 381 ' Calculate 10 us time unit
syncpoint := CNT
'From Timing.spin
PUB waitsync
WAITCNT(syncpoint += delay)
PRI NL
pst.NewLine
PRI CLS
pst.Clear
DAT
'-----------[ Predefined variables and constants ]-----------------------------
TO_IN LONG 74_641 '
TO_CM LONG 29_386
Comments
Ping idles low and asserts high.
Yes, according to its datasheet it is.
And just to clarify, I am getting results but I can only detect readings between 2 and 6 centimeters. it should be more between 2 and 400 according to the specifications so I think some timing calculations, I have are off, which should be more apparent to someone with more experienced with spin than I am.
{{ Sparkfun's HC-SR04 Ultrasonic Sensor on the Propeller :) I've only seen this in C code for the Propeller so here it is in SPIN. }} CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 TRIG = 1 ' Connected to P1 ECHO = 0 ' Connected to P0 HIGH = 1 LOW = 0 INPUT = 0 OUTPUT = 1 MAX_DIST = 23_200 DEBUG = 1 ' 1 = true, 0 = false ' from Timing.spin _10us = 1_000_000 / 10 ' Divisor for 10 us _1ms = 1_000_000 / 1_000 ' Divisor for 1 ms _1s = 1_000_000 / 1_000_000 ' Divisor for 1 s ' from dualPing.spin TO_IN_std = 74_641 ' std atmosphere speed of sound, us per inch traveled @ 59F air temperature TO_CM_std = 29_386 ' std atmosphere speed of sound, us per cm traveled @ 59F air temperature OBJ pst : "Parallax Serial Terminal" VAR LONG pulse_Start LONG pulse_Stop ' from Timing.spin LONG delay LONG syncpoint LONG clkcycles PUB Main | Microseconds, Distance, cnt1, cnt2 waitcnt(clkfreq * 5 + cnt) pst.start(115200) ' set pin directions OUTA[TRIG] := HIGH ' Direction not set but set the state low DIRA[TRIG] := OUTPUT ' Set to Output OUTA[TRIG] := LOW ' Ensure it is still Low DIRA[ECHO] := INPUT ' Set the echo input IF DEBUG == 1 pst.Str(STRING("Directions Set, ready for testing!")) NL REPEAT ' main loop OUTA[TRIG] := HIGH pause10us(1) OUTA[TRIG] := LOW WAITPNE(0, |< ECHO, 0) cnt1 := CNT WAITPEQ(0, |< ECHO, 0) cnt2 := CNT Microseconds := (||(cnt1 - cnt2) / (CLKFREQ / 1_000_000)) >> 1 if DEBUG == 1 pst.Home pst.ClearEnd pst.Dec(Microseconds) pst.Str(STRING(" us. ")) Distance := Millimeters(Microseconds) IF DEBUG == 1 pst.Dec(Distance) pst.Str(STRING(" mm.")) pause1ms(100) PUB Inches(ms) : Distance ''Measure object distance in inches Distance := ms * 1_000 / TO_IN ' Distance In Inches PUB Centimeters(ms) : Distance ''Measure object distance in centimeters Distance := Millimeters(ms) / 10 ' Distance In Centimeters PUB Millimeters(ms) : Distance ''Measure object distance in millimeters Distance := ms * 10_000 / TO_CM ' Distance In Millimeters 'from dualPing.spin PUB calibrate(Tamb) ''Adjust Ping))) calibration constants to reflect ambient ''temperature impact on speed of sound (temperature assumed to be °F) Tamb += 460 TO_IN := TO_IN_std * (^^(Tamb * 1_000_000)) / (^^518_690_000) TO_CM := TO_IN * TO_CM_std / TO_IN_std 'From Timing.spin PUB pause10us(period) '' Pause execution for period (in units of 10 us) clkcycles := ((CLKFREQ / _10us * period) - 4296) #> 381 ' Calculate 10 us time unit WAITCNT(clkcycles + CNT) ' Wait for designated time 'From Timing.spin PUB pause1ms(period) '' Pause execution for period (in units of 1 ms). clkcycles := ((CLKFREQ / _1ms * period) - 4296) #> 381 ' Calculate 1 ms time unit WAITCNT(clkcycles + CNT) ' Wait for designated time 'From Timing.spin PUB pause1s(period) '' Pause execution for period (in units of 1 sec). clkcycles := ((CLKFREQ / _1s * period) - 4296) #> 381 ' Calculate 1 s time unit WAITCNT(clkcycles + CNT) ' Wait for designated time 'From Timing.spin PUB marksync10us(period) delay := (CLKFREQ / _10us * period) #> 381 ' Calculate 10 us time unit syncpoint := CNT 'From Timing.spin PUB waitsync WAITCNT(syncpoint += delay) PRI NL pst.NewLine PRI CLS pst.Clear DAT '-----------[ Predefined variables and constants ]----------------------------- TO_IN LONG 74_641 ' TO_CM LONG 29_386