stop the car now

johnlong

Senior Member
Hi One and all
its been a long time since I posted but sometimes life throws you a curve ball.
Looking at using the sr04 to operate a stop warning to avoid hitting the wall with the car when
parking. I have the unit working and reading in mm but only getting results to the nearest 100mm's (ie 100,200,300 and so forth)
is it possible to breakdown the values to read say 80mm 135mm and such.
Thank you all in advance for your wisdom
Code:
'Stop the car NOW love using an sr04 trig and echo connected via 2200k resistor
#Picaxe 18M2
#no_data

symbol trig = B.1            ' Define output pin for Trigger pulse
symbol echo  = B.1           ' Define input pin for Echo pulse
symbol range = w0

setfreq m4

main:
    do
    HIGH trig               'output for Trigger pulse
    PULSIN echo, 1 ,range   ' Measure the duration of the echo pulse
  pause 10                 ' Recharge period after ranging completes
  range = range / 58*100      ' Convert duration to distance in mm
  sertxd("distance ",#range," mm",cr,lf)    ' Output the distance
  sertxd(" bits of w0 ",#bit15,#bit14,#bit13,#bit12,bit11,#bit10,#bit9,#bit8,#bit7,#bit6,#bit5,#bit4,#bit3,bit2,#bit1,bit0,cr,lf)
  pause 5000                ' Wait before the next measurement
  loop                ' Repeat the process
 
I can see two things in your program that negatively affect its output. The first is the mathematics sequence in the equation
range = range / 58 * 100

Multiplying any number by 100 will always limit the increments to 100!

Due to the integer limitations of PICAXE's maths, you need to keep any values as large as possible but obviously less than the word maximum of 65535. Wherever possible, multiply first before dividing. Here, you will need to temporarily add a logging command immediately after the PulsIn command to display the actual 'crude' maximum distance reading. Eg. SerTxd("*", #range, "*, ")
If the 'crude' number is less than 655, it can be multiplied by 100 before dividing by 58: range = range * 100 / 58
If larger, but less than 1310, multiply by 50 and divide by 29: range = range * 50 / 29
If larger than that, e.g. but less than 2620, break the equation down further: range = range * 25 / 29 * 4
The equation can be taken further if the maximum reading from PulsIn is larger.

The second issue is the duration of the delay between readings. I have found that a more practical delay is between 250 and 500 milliseconds between readings, so reduce the Pause command before "Loop" to let's say, Pause 300. Also, you may as well remove the "Pause 50" altogether as it serves no purpose.
 
Another thing that does not look right:
The HC-CR04 doco gives the formula for calculating that range in cm as uS/58.

You are running your program at 4MHz and at this speed PULSIN measures the length of a pulse in units of 10us. i.e. a count of 1 = 10us, 2 = 20us, etc.
At 4MHz this would make the formula cm = <count from PULSIN> *10 / 58.

To get a finer resolution from PULSIN you will need to us a higher CPU Freq.
The 18M2 can run at 32MHz at which speed PULSIN measures the length of a pulse in units of 1.25us and the formula would be: cm = <count from PULSIN@32MHz> * 1.25 / 58
(or perhaps <count from PULSIN@32MHz> / 232 * 5)

There is a trade-off in choosing between the max distance you can measure and the finest resolution (the size of the steps.)
The max count returned by PULSIN is 65535 so:
At 4MHz 65535 / 58 * 10 = 11,299 cm in steps of 10 cm
At 32MHz 32MHz 65535 / 232 * 5 = 1412.39 cm in steps of 1.25 cm

But once you get this working you could make your program switch between different CPU speeds to get better resolution as you get closer. e.g.
Start at 4MHz to measure the distance in steps of 10cm then (using these distances as examples):
- when the distance gets below 9000 cm switch to 8MHz to measure the distance in steps of 5cm.
- when the distance gets below 4500 cm switch to 16MHz to measure the distance in steps of 2.5cm.
- when the distance gets below 1250 cm switch to 32MHz to measure the distance in steps of 1.25cm.

What is not mentioned in the doco for PULSIN is whether the measurement is rounded up or down. i.e. at 4MHz is a pulse that is 5ms long measured as 0 or 1? You can find this out by measurement.
 
Hi,

The simple answer to your question is to change the "Range" Line to range = range / 29 * 50 which will give a readout (decrementing) in 50 mm (2 inches) steps. ;) Note that the range is being truncated (not rounded), so for example a distance of 95 mm will be displayed as 50 mm.

Beyond that, there are numerous possibilities, as described above, depending whether you want a "clean" number readout (in simple steps), perhaps with minor inaccuracies, or a much higher resolution or distance. It may also depend what is the maximum functional (or desired) range and whether you want a more "urgent" notification, such as a buzzer or loudspeaker (tone/tune), etc..

To keep this post short, here is a range of possibilities for the "Range" line in your program (no other changes), with comments on what should be achieved (but not fully tested), assuming that the current display is accurate. All these formulae are now rounding to the nearest value, but this might not be a good idea for a reducing range alert, and can be removed by deleting the numerical value immediately after the "+" sign (and the sign itself) if desired :

Code:
range = range + 29 / 58 * 100    ; Original range in steps of 100 mm
range = range + 14 / 29 * 50     ; Range in steps of 50 mm
range = range + 1 / 3 * 5        ; Range in steps of 5 mm, but distance error of about 3%
range = range + 1 ** 22600 * 5   ; Range in steps of 5 mm
range = range + 3 ** 11300 * 10  ; Range in steps of 10 mm
range = range + 3 ** 11300       ; Range in centimetres
range = range + 7 ** 4449        ; Range in inches
range = range + 7 ** 4449 * 10   ; Range in tenths of an inch, in steps of 1 inch
range = range + 3 ** 8897 * 5    ; Range in tenths of an inch, in steps of 0.5 inch
range = range ** 44490           ; Range in tenths of an inch
range = range ** 56497 * 2       ; Range in mm in steps of 2 mm

If any of the latter (8) formulae prove to be inaccurate, they probably can be corrected by changing the number after the ** by the corresponding number of percent (which might be by hundreds or even thousands).

Cheers, Alan.
 
Many thanks Gents
Had a good play this morning, got good results with using 32Mhz and 4Mhz the only problem with 32Mhz is that the terminal needs a 38400 braud rate to run at that speed and only 4800 for 4Mhz. Spent most of the morning play around swapping frequency's in the code to view the terminal so settled with the 4Mhz route. Slipped a if statement into handle the reading ranges
Code:
'Stop the car NOW love using an sr04 trig and echo connected via 2200k resistor
#Picaxe 18M2
#no_data

symbol trig = B.1            ' Define output pin for Trigger pulse
symbol echo  = B.1           ' Define input pin for Echo pulse
symbol range = w0 
' m4, m8,m16,m32
setfreq m4
main:
    do
    HIGH trig               'outputfor Trigger pulse
    PULSIN echo, 1 ,range   ' Measure the duration of the echo pulse
    SerTxd("* m4 * ", #range, cr,lf)
    if range <1300 then 
      
   range = range * 50 / 29 'for results upto 2200mm
      sertxd(" distance in mm ",#range,cr,lf)
   
    else    
    
    range = range * 25 / 29 * 2 'for results over 2200mm
    SerTxd(" distance in mm ext  ", #range, cr,lf)
    endif 
    sertxd("----------------------------",cr,lf)
    pause 300
    loop

Like I mentioned in post 1 its been awhile so the grey sponge needed a good wringing out
have a good weekend one and all
regards John
 
Had a good play this morning, got good results with using 32Mhz and 4Mhz the only problem with 32Mhz is that the terminal needs a 38400 braud rate to run at that speed and only 4800 for 4Mhz.
John,

You can change the CPU speed as you need to, to suit the commands that you are running.

So for this issue you simply need to change the CPU speed to the speed you are using for the HC04 before sending and receiving the pulse and then change it back to 4MHz immediately immediately after so all the SERTXD commands are at 4MHz.

e.g. this is your code form post #5 modified to run most of the program, including all the SERTXD commands, at 4MHz and switch to 32MHz just to run the HIGH & PULSIN commands:
Code:
setfreq m4
main:
    do

    setfreq m32
    HIGH trig               'output for Trigger pulse
    PULSIN echo, 1 ,range   ' Measure the duration of the echo pulse
    setfreq m4

    SerTxd("* m4 * ", #range, cr,lf)
    if range <1300 then 
      range = range * 50 / 29 'for results upto 2200mm
      sertxd(" distance in mm ",#range,cr,lf)
    else    
      range = range * 25 / 29 * 2 'for results over 2200mm
      SerTxd(" distance in mm ext  ", #range, cr,lf)
    endif 
    sertxd("----------------------------",cr,lf)
    pause 300
    loop

Something I noticed is that you set the trig pin HIGH but never set it low so it looks like you only ever send one pulse. Should the "HIGH trig" command be a PULSEOUT command?
At 32MHz the command will need to be "PULSEOUT trig, 8" in order to send the 10us pulse to trigger the HC04. Check the PICAXE manual to calculate the value to use for other CPU frequencies.
 
Hi Flenser
I took the command from a old post answered by technical in post #11 (

18M2 WJEC Assembler HC-SR04)​

who used that formate for the trig pin but will drop a low command in and give it a go.
What you say doe's seem to make sense unless the open pin is to in able it to constantly read without a break, via the command been
reissued from via loop command hence a small pause in the loop.
As I think I understand it the sr04 once triggered via the high for 10us handles its own internal high and lows and frequency via the echo pin.
I intend to keep playing with it to see how fine you can go, get the results it would be cool if its possible to get it read down to a single mm so not discounting anything .
Found this site this morning using a that that should not be named and a Pi https://wiki.ros.org/Drivers/Tutori...tWithUltrasonicSensorHC-SR04ArduinoUARTPython
nice graphics.
Thanks and have a good weekend
regards john
 
Something I noticed is that you set the trig pin HIGH but never set it low so it looks like you only ever send one pulse. Should the "HIGH trig" command be a PULSEOUT command?
John,
What I said above was wrong. Technical is very experienced so his code using the HIGH command is correct and there is no value in adding a LOW command because it will have no effect.

I missed that you are using the SR04 is in "single pin" mode with trig and echo connected via 2200k resistor.
- After you trigger the SR04 to take a measurement with the "HIGH trig" command the SR04 must pull the echo pin low before the start of the measurment pulse it outputs.
- When the PULSEIN command runs it will make the b.1 pin an input so with trig and echo connected with a resistor the low signal on the SR04's echo pin will also pull the SR04's trig pin low and end the trigger pulse.
- The speed of the interpreted PICAXE basic no doubt means that the trig pin is high for more than the required 10us minimum before the PULSEIN command makes b.1 an input.

As I think I understand it the sr04 once triggered via the high for 10us handles its own internal high and lows and frequency via the echo pin.
That is correct.
Once the SR04 gets triggered via the high for 10us on the trig pin it sends out the ultrasonic pulses, measures how long it take for the reflected pulses to return, and then sends back the duration pulse on the echo pin.
 
Last edited:
Back
Top