Sonar range changes on stationary object
I am running a code I picked up from Parallax and modified to fit two run two sonar. There are two problems I can't seem to get around.
First - Why do I get different readings on a stationary object?
The code is set to average 5 readings so with a stationary sonar and a stationary object there should be no changes.
Second - Why do I get false distance readings?
The sonar are off a lot - upto a couple feet. One is pointing at the ceiling and shows the ceiling·moving up and down. If I put my hand in front of either sonar its reading changes so much that somethings it says my hand is 1.5 inches away when I know its a lot more.
Here's the code:
By the way, how does·$03EF translate to a decimal? I can't use a decimal no matter what I try.
First - Why do I get different readings on a stationary object?
The code is set to average 5 readings so with a stationary sonar and a stationary object there should be no changes.
Second - Why do I get false distance readings?
The sonar are off a lot - upto a couple feet. One is pointing at the ceiling and shows the ceiling·moving up and down. If I put my hand in front of either sonar its reading changes so much that somethings it says my hand is 1.5 inches away when I know its a lot more.
Here's the code:
'Parallax, INC. • Devantech SRF04 Ultrasonic Range Finder (#28015) • 10/2003 Page 4 ' ========================================================================= ' ' File....... SRF04_Demo.BS2 ' Purpose.... Devantech SRF04 Ultrasonic Range Finder ' Author..... Parallax, Inc. (Copyright 2003 - All Rights Reserved) ' E-mail..... [url=mailto:support@parallax.com]support@parallax.com[/url] ' Started.... 06 MAR 2002 ' Updated.... 01 OCT 2003 ' ' {$STAMP BS2} ' {$PBASIC 2.5} ' ' ========================================================================= ' -----[noparse][[/noparse] Program Description ]--------------------------------------------- ' ' This program uses the Devantech SRF04 to measure the distance between the ' unit and a target. Display is raw value, centimeters, and inches. ' -----[noparse][[/noparse] Revision History ]------------------------------------------------ ' ' 01 OCT 2003 : Updated for PBASIC 2.5 and for any BASIC Stamp module ' -----[noparse][[/noparse] I/O Definitions ]------------------------------------------------- ' Trigger PIN 0 Echo PIN 1 Trigger2 PIN 2 Echo2 PIN 3 ' -----[noparse][[/noparse] Constants ]------------------------------------------------------- Trig10 CON 5 ' trigger pulse = 10 uS ToCm CON 30 ' conversion factor to cm ' -----[noparse][[/noparse] Variables ]------------------------------------------------------- samples VAR Nib ' loop counter pWidth VAR Word ' pulse width from sensor rawDist VAR Word ' filtered measurment rawDist2 VAR Word ' filtered measurment cm VAR Word ' centimeters inches VAR Word ' -----[noparse][[/noparse] Initialization ]-------------------------------------------------- Setup: LOW Trigger DEBUG CLS, "Devantech SRF04 Demo", CR, "--------------------", CR, "Raw........... ", CR, "Centimeters... ", CR, "Inches........ ", CR, "Raw2........... ", CR, "Centimeters... ", CR, "Inches........ ", CR, HOME ' -----[noparse][[/noparse] Program Code ]---------------------------------------------------- Main: DO GOSUB Get_Sonar ' take sonar reading cm = rawDist / ToCm ' convert to centimeters inches = cm */ $03EF ' x 3.937 (to 0.1 inches) DEBUG CRSRXY, 15, 4, DEC inches / 10, ".", DEC1 inches, CR cm = rawDist2 / ToCm ' convert to centimeters inches = cm */ $03EF ' x 3.937 (to 0.1 inches) DEBUG CRSRXY, 15, 7, DEC inches / 10, ".", DEC1 inches, CR, HOME PAUSE 250 ' delay between readings LOOP END ' -----[noparse][[/noparse] Subroutines ]----------------------------------------------------- Get_Sonar: rawDist = 0 ' clear measurements rawDist2 = 0 FOR samples = 1 TO 5 ' take five samples PULSOUT Trigger, Trig10 ' 10 uS trigger pulse RCTIME Echo, 1, pWidth ' measure pulse rawDist = rawDist + (pWidth / 5) ' simple digital filter PAUSE 10 ' minimum period between PULSOUT Trigger2, Trig10 ' 10 uS trigger pulse RCTIME Echo2, 1, pWidth ' measure pulse rawDist2 = rawDist2 + (pWidth / 5) ' simple digital filter PAUSE 10 ' minimum period between NEXT RETURN
By the way, how does·$03EF translate to a decimal? I can't use a decimal no matter what I try.
Comments
If you have a windows based PC, you can easily convert with the "Calculator" program. Just go to the "View" menu, and put it in "Scientific" mode. Then you can enter a number in HEX and then change to DEC and visa-versa.
Also, for a more thorough understanding: Digits 0-9 are the same as in Decimal, A-F = 10 - 15. Starting from the right most digit, the first digit is "ones", the second is "Sixteens", then "256s", followed by "4096s". Thusly:
0 = 0 x 4096 = 0
3 = 3 x 256 = 768
E = 14 x 16 = 224
F = 15 x 1 = 15
And 0 + 768 + 224 + 15 = 1007
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
John R.
8 + 8 = 10
PAR
I too suffer the same as you... at first I thought it was my wiring, so I buildt a totally new board... then I thought it was my sensor, so I bought a totally new one, but I am still where you are.... I even increased the cycle to calculate an average of 50 readings, but same result... the numbers just keep jumping all over... I saw your other posting where someone suggested adding a filter cap... I added a 100uF polarized electrolytic, but no real change... I solicited this group for other suggested values, but have not gotten a response (http://forums.parallax.com/showthread.php?p=623041)
Even if we can't ever figure out why, at least it is comforting knowing that I am not alone with my problem....
I am tempted to buy a PING))) and compare the two...
Q. What is the accuracy of the ranging?
A.· We quote 3-4cm. Its normally better than this, however so many factors affect accuracy that we won't specify anything better than this. The speed of sound in air is approx. 346m/S at 24 degrees C. At 40KHz the wavelength is 8.65mm. The sonar's detect the echo by listening for the returning wavefronts. This echo has an attack/decay envelope, which means it builds up to a peak then fades away. Depending on which wavefront is the 1st to be strong enough to be detected, which could be the 1st, 2nd or even 3rd, the result can jitter by this much. Another effect which limits accuracy is a phasing effect where the echo is not coming from a point source. Take a wall for example, the ping will bounce off the wall and return to the sonar. The wall is large, however, and there will be reflections from a large area, with reflections from the outside being slightly behind the central reflection. It is the sum of all reflections which the sensor sees which can be either strengthened or weakened by phasing effects. If the echo is weakened then it may be the following wavefront which is detected - resulting in 8.65mm of jitter. It is possible to see changes of distance as small as mm but then get cm of jitter.
Wow, jitter.
Rick
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Chris Savage
Parallax Tech Support
This set up takes 5 readings
So yes, it does send multi pulses.
However with a 10 ms pause and a perpendicular arrangment I do not understand why this is getting false readings. Perhaps the sonar need to trigger farther apart.
If the SRF04 is the problem then I will have to go with QTI, IR or Ping))) provided one of them is more reliable. The intent is to mount IR directly below the Sonar so there is a second distance measurment and so that more surfaces can be detected.
PAR
The particular part of the code was when the Boe was driving forward the ping would sample to make sure nothing is in front. But the values I was getting back made no sense. And the if statement directly after the ping that used the distance value seemed to be messing up.
If i place a short pause after the ping subroutine (which does include the conversion to cm) and the if statement that uses the final distance value everything works perfect.
This is really odd because I call the same ping subroutine other places in the code and everything works fine. By all accounts the error should not happen but i tested it more than a few times with with the pause commented out and then with the pause, making sure to change nothing else and in a very open room so there was no chance of any odd reflections and this definitly was the solution to the problem.
I am at work right now (GDRS) so I don't have the code in front of me but I will post it when I get home.
See if this solves your problem
For example if you want to multiply x by 1.4 just do
y = (x * 14) / 10
This eliminates the need to do things with HEX. Which honestly I don't care to take the time to work with because its much easier to mess up the math in HEX.
In the code I am running I do no averaging at all, and all the ping measurements make sense, maybe an average would be a little more precise but I don't see the point, if something is far away, just drive closer and ping it again and get a much more accurate distance by being closer to the object. Then drive around using that distance.
Smart Sensors and Applications product page: http://www.parallax.com/detail.asp?product_id=28029
Smart Sensors and Applications PDF (5.5 MB): http://www.parallax.com/dl/docs/prod/sic/SmartSensors-v1.0.pdf
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Andy Lindsay
Education Department
Parallax, Inc.
Post Edited (Andy Lindsay (Parallax)) : 1/2/2007 9:48:49 PM GMT
Sonar 1····································· Sonar 2
376··········································· 771.7
386.2·········································706
435.8·········································53.10
319··········································· 797.3
383.1········································ 573.9
388.2·········································623.8
383.9········································ 599.8
The longer the code runs the bigger the problem gets.
As you can see these are not minor changes. Sonar 1 is the more stable but still changes from a high of 435 to a low of 319 - thats over a hunderd. Sonar 2 makes changes in excess of 700.
I ran this a second time with a pause of 20 between the individual sonar pulses and got to following. (Not looping, pulses.·The loop has a pause of 10 before geting an echo from sonar 1 AFTER sonar 2 has triggered.)
Sonar 1······························· Sonar 2
421.2·································· 855.5
416.1·································· 828.8
421.2·································· 823.3
410.6···································831.1
420.1···································100.3
60······································· 420.8
451.8··································· 809.9
Again Sonar 1 and 2 both show large differences. Sonar one changes by almost 400 and sonar 2 changes by over 700.
These measurments are current as of this posting. I literally ran the program while on line to get accurate data to post.
"PULSOUT Trigger, Trig10" and the "RCTIME Echo, 1, pWidth" gets much more reliable and stable readings!
Try inserting "Output Trigger" between the two commands so it looks like this...
PULSOUT Trigger, Trig10 ' 10 uS trigger pulse
OUTPUT Trigger ' creates a very slight delay by having the Stamp process a "dummy" command
RCTIME Echo, 1, pWidth ' measure pulse
I also am allowing at least 100ms between each reading so the sound waves are not bouncing off each other... I suspect that I can reduce this a bit, but I seem to be on to something here!
Can you give it a try and confirm that you are getting better results as well?
Sonar 1···························· Sonar 2
461··································· 701
459····································99
489··································· 766
469····································651
493··································· 99
503··································· 3
498····································813
With the code showing a dummy command of OUTPUT Trigger and 100 ms pause I get these results
Sonar 1······················· Sonar 2
452.7···························814.6
521.9·························· 147.1
449.6···························764.6
472.4·························· 836.6
448·····························120.3
457.4··························718.2
Again large differences and as early this was done while on the post so the measurments and code changes will be accurate to the thread.
I have also tried this code:
' {$STAMP BS2}
' {$PBASIC 2.5}
'
' Devantech SRF04 Example
'
wDist· VAR· Word
wDist2· VAR· Word
INIT· CON· 0
ECHO· CON· 1
INIT2 CON 2
ECHO2 CON 3
' CONVERSION FACTORS:
'
' The PULSIN command returns the round-trip echo time in 2us units
' which is equivalent to the one-way trip time in 1us units.
'
' distance = (echo time) / (conversion factor)
'
' use 74 for inches······ (73.746us per 1 in)
' use 29 for centimeters· (29.033us per 1 cm)
'
convfac· CON· 74· ' use inches
'
main:
· GOSUB sr_sonar_2
· DEBUG DEC wDist, CR
· PAUSE 200
· GOTO main
sr_sonar:
· PULSOUT INIT,5··· ' 10us init pulse
· PULSIN ECHO,1,wDist· ' measure echo time
· wDist=wDist/convfac· ' convert to inches
· PAUSE 10
· RETURN
sr_sonar_2:
· PULSOUT INIT,5··· ' 10us init pulse
· OUTPUT INIT··· ' dummy command (delay)
· RCTIME ECHO,1,wDist· ' measure echo time
· wDist=wDist/convfac· ' convert to inches
· PAUSE 10
· PULSOUT INIT2,5··· ' 10us init pulse
· OUTPUT INIT2··· ' dummy command (delay)
· RCTIME ECHO2,1,wDist2· ' measure echo time
· wDist2=wDist2/convfac· ' convert to inches
· PAUSE 10
· RETURN
Which gave much better results of 47, 48, 45, 48, 44
And this code
' {$STAMP BS2}
' Sonar check
'''''variables'''''
Dist VAR Word··· ' variable that will be used to store reading from sensor
'''''notes'''''
' Pin 0 of BS2 wired to init (next to unused pin)
' Pin 1 of BS2 wired to echo (inbetween init and VDD)
'''''Main routine'''''
main:
GOSUB checksensors
DEBUG ? Dist
GOTO main
'''''sub routines'''''
checksensors:
PULSOUT 0,5······· 'send initial pulse
OUTPUT 0··········· 'dummy delay
RCTIME 1,1,Dist·· 'store value of received pulse in Dist
RETURN
Which returned raw distance as 3247, 3222, 3234, 3561, 2957, 3273
This leads me to believe that the top code for this response is the most stable of the codes listed in this thread.
The code needs to be debugged for both sensors, so I will post again in a moment.
Post Edited (AIman) : 1/3/2007 3:21:29 AM GMT
Sonar 1····························· Sonar 2
3256································· 3549
3239··································3595
3262································· 3568
3252································· 3567
3290································· 3557
Ironic that code that was sent to me is more accurate then the web site that sells the product...
Heres the code that gave the above results, so if anyone else needs code there are 4 different functional examples posted with this one being the most reliable so far.
Also for reference I just tested my ping with this code and my returns couldn't have been more stable. Up to about 100 cm 20 returns are almost always equal, and over 100 cm they may vary 1 or 2 cm, but thats really acceptable. Not sure how this compares to the actuall distance but it is dependable.
' {$STAMP BS2}
' {$PBASIC 2.5}
RawDist VAR Word
Ping PIN 15
'Constants for Ping
Scale CON $200
Trigger CON 5
RawToIn CON 889
RawToCm CON 2257
IsHigh CON 1
IsLow CON 0
counter VAR Byte
DEBUG CLS
FOR counter = 1 TO 20
Ping = IsLow
PULSOUT Ping, Trigger
PULSIN Ping, IsHigh, RawDist
RawDist = RawDist */Scale
RawDist = (RawDist/2) ** RawToCm
DEBUG DEC RawDist,CR
NEXT
END
I have a few other sonar I can swap out and will give that a shot.
The other solution would be to do a couple of variables to hold a number and if the distance is greater then a set amount ignore the figure unless all the returns start getting that same distance. Probably something like +/- 5%.
What stamp are you using? are you using the SRF04 or Ping)))?
Main:
'Get Distance Data
Low SRRS ' Makes Trigger 0-1-0, SRRS is signal pin of PING)))
PulsOut SRRS, 5 ' Activate sensor
PulsIn SRRS, 1, RawDis ' Measure echo pulse
RawDis = RawDis * 2 ' Convert to uS
RawDis = RawDis / 2 ' Remove return trip
RawDis = RawDis / 29.034 ' Convert to cm
Print $Fe, 1 'Clear LCD display
Print $Fe, 2 'Set to Home position
Print "Distance in cm" 'Print text to LCD
Print $fe, $c0 'Set Cursor to second line
Print Dec RawDis 'Print Value on second line
DelayMS 1000 ' Pause for 1 sec
goto Main
Post Edited (cotang) : 1/8/2007 6:10:33 AM GMT
RawDis = RawDis * 2 ' Convert to uS
RawDis = RawDis / 2 ' Remove return trip
They seem to cancel one another out. Or am I missing something.
Regards,
Eric
·