Ultrasonic range finder beginner

Thread Starter

emzdanow

Joined Jun 14, 2010
23
I am new to ultrasonic range finding and was looking to use the SRF04 http://www.robot-electronics.co.uk/htm/srf04tech.htm along with a PIC μc. As I understand from the documentation with the SRF04, the ouput is a pulse where the width corresponds to distance.

The area I need help in is how to time this with my μc. Can I start a timer when the output goes high and set the interrupt for when signal goes back low? What is the easiest way to do this? I am using C.
 

retched

Joined Dec 5, 2009
5,207
This will depend on the transmitter and receiver.

A look into the datasheet of the transmitter will show you the pulse length that the transmitter should be transmitting

Then when the receiver receives the bounced signal, again the datasheet will show what numbers mean what, and how to decode it to distance.
 

Thread Starter

emzdanow

Joined Jun 14, 2010
23
I understand how the range finder functions, I am just wondering about how to use the PIC to time the pulse length.
 

BMorse

Joined Sep 26, 2009
2,675
I understand how the range finder functions, I am just wondering about how to use the PIC to time the pulse length.

when I used that particular sonar module this is the specs I went by:

'Sound travels 1 inch every 73.746us
'Timer uses 625Khz clock Frequency (5Mhz/8)
'625Khz is 1.6us per clock tick
'Max range of sonar is Approx. 9m (354 inches/ 899cm)
'Distance of echo roundtrip is 354 *2 = 708 inches
'708 * 73.746us /1.6us = 32633 'ticks at max range
'32632 / (354) = 92 --> = inches
'32632 / (899) = 36 --> = cm
Basically when you pulse the sonar input you will also start a timer, once the ECHO line goes high, you stop the timer and see how much time has elapsed since the "ping" was sent, then do the calculations to convert timer value to inches or centimeters....

here is a code snippet I used with the OOPIC II Module:

Rich (BB code):
'Devantech SRF04 Sonar Ranger program
Dim W1 As New oWord    'Sonar Reading
Dim X1 As New oWord
Dim Y1 As New oWord
Dim SonarSrv As New OServo

Dim EchoTimer As New oTimer
Dim TmrControl As New oGate(1)
Dim INIT As New oDio1
Dim ECHO As New oDio1

Sub Init_Sonar()
    'Sound travels 1 inch every 73.746us
    'Timer uses 625Khz clock Frequency (5Mhz/8)
    '625Khz is 1.6us per clock tick
    'Max range of sonar is Approx. 9m (354 inches/ 899cm)
    'Distance of echo roundtrip is 354 *2 = 708 inches
    '708 * 73.746us /1.6us = 32633 'ticks at max range
    '32632 / (354) = 92 --> = inches
    '32632 / (899) = 36 --> = cm

    EchoTimer.ExtClock=cvOff
    EchoTimer.PreScale=3

    INIT.IOLine = 6
    INIT.Direction = cvOutPut
    INIT.Value = 0

    ECHO.IOLine = 7
    ECHO.Direction = cvInput

    TmrControl.Input1.Link(ECHO.Value)
    TmrControl.OutPut.Link(EchoTimer.Operate)
    TmrControl.Operate = cvTrue

End Sub


Sub Read_Sonar()
    EchoTimer.Value = 0    'Clear old result
    INIT.Value = 1
    INIT.Value = 0        'Pulse sonar input
    OOPic.Delay = 1        'Give ECHO Chance to go high
    'Wait until echo goes low again to return reading
    'ECHO might be low already, but could take up to 36ms
    'timer automatically runs while echo is high

    While (ECHO.Value=1)
    Wend

    W1 = (EchoTimer.Value/92)    'Convert to inches

    OOPic.Delay = 1 

End Sub
B. Morse
 

Thread Starter

emzdanow

Joined Jun 14, 2010
23
So I purchased a Parallax Ping sensor and am trying to detect with a PIC16F690. Since there is only one signal pin I am sending pulse with RC6 and measuring echo with RB4. My problem is that I am not detecting the echo pulse (not receiving high input on RB4). My code is below and please consider I am a beginner. Does anyone have any suggestions? Thanks!

#include <htc.h>
void pause (unsigned short msvalue);

__CONFIG (INTIO & WDTDIS & MCLRDIS & UNPROTECT );

unsigned char ticks = 0; //timer tick storage variable can be 0 to 255

main()
{
ANSEL = 0;
CM1CON0 = 0;
CM2CON0 = 0;

PORTC = 0x00;
TRISC = 0x00;
PORTB = 0x00;
TRISB = 0xFF;

while(1)
{
RC6 = 1; // Instruction clock operates at 1MHz
RC6 = 1; // so every instruction 1us. 5 RC6 high
RC6 = 1; // lines = 5 us high pulse
RC6 = 1;
RC6 = 1;
RC6 = 0;
while(RB4 == 0); // wait for beginning of echo pulse

OPTION = 0b00000101; //Set TMR0 prescaler to 1:64
TMR0 = 0b00000000; // Start TMR0 at 0
while(RB4 == 1); // Hold while echo pulse high
ticks = TMR0; // When pulse goes low, capture TMR0 value
T0IF = 0; // Clear TMR0 interupt flag

// Next section lights four LEDS based on how many clock ticks
// No distance calculation yet, just trying to get it to work
if(ticks < 60)
{
RC0 = 1;
RC1 = 0;
RC2 = 0;
RC3 = 0;
}
if(ticks > 60 && ticks < 120 )
{
RC0 = 1;
RC1 = 1;
RC2 = 0;
RC3 = 0;
}
if(ticks > 120 && ticks < 180)
{
RC0 = 1;
RC1 = 1;
RC2 = 1;
RC3 = 0;
}
if(ticks > 180)
{
RC0 = 1;
RC1 = 1;
RC2 = 1;
RC3 = 1;
}
pause(500); // pause 500 milliseconds
}
}
 

BMorse

Joined Sep 26, 2009
2,675
You had asked about the SRF04, but yet purchased a completely different module....

with the module you have, you can not use it the way you are using it, only 1 I/O pin is required, you would make the io pin and output to send the trigger pulse, then switch it to an input to capture the echo trigger.... Since you are using 2 different IO pins, and when you set one low, the other input pin (RB4) will never go high since you have set RC6 to low.........

You need to study the datasheet and learn how to use this module....

B. Morse
 

Thread Starter

emzdanow

Joined Jun 14, 2010
23
ok so I purchased the correct range finder and am using the following code without positive results. With this code I find that nothing happens, but when I comment out the while(RB5 == 0); line, the program will loop. I can hear a buzz from the range finder. This tells me my uC (a PIC16F690) is not sensing a high signal from the range finder. If anyone can help that would be great, again this code was written by beginner. Thanks!

#include <htc.h>
void pause (unsigned short msvalue);
__CONFIG (INTIO & WDTDIS & MCLRDIS & UNPROTECT );
unsigned char ticks = 0; //timer tick storage variable can be 0 to 255
main()
{
ANSEL = 0;
CM1CON0 = 0;
CM2CON0 = 0;
PORTC = 0x00;
TRISC = 0x00;
PORTB = 0x00;
TRISB = 0b00100000;
while(1)
{
/******************Pulse Transmission**********************************************************/
RB4 = 1; // 10 commands of RB4 = 1 is 10us
RB4 = 1; // pulse high (1 inst cycle per us
RB4 = 1;
RB4 = 1;
RB4 = 1;
RB4 = 1;
RB4 = 1;
RB4 = 1;
RB4 = 1;
RB4 = 1;
RB4 = 0;

/****************Echo Detection****************************************************************/
OPTION = 0b00000101; // Make TMRO prescale 1:64, oscillator = 1 tick per 1us, 64(1us)= 64us. Range = 256(64us) = 16.3ms
T0IF = 0; // Clear timer0 interupt flag
while(RB5 == 0); // Wait for echo pulse to start (go high)
TMR0 = 0; // Start Timer0 with 0 ticks
while(RB5 == 1); // Wait for echo pulse to stop (go low)
ticks = TMR0; // Capture timer0 value and store it in 'ticks'
/****************Display Results****************************************************************/
if(TMR0 < 60)
{
RC0 = 1;
RC1 = 0;
RC2 = 0;
RC3 = 0;
}
if(TMR0 > 60 && TMR0 < 120 )
{
RC0 = 1;
RC1 = 1;
RC2 = 0;
RC3 = 0;
}
if(TMR0 > 120 && TMR0 < 180)
{
RC0 = 1;
RC1 = 1;
RC2 = 1;
RC3 = 0;
}
if(TMR0 > 180)
{
RC0 = 1;
RC1 = 1;
RC2 = 1;
RC3 = 1;
}
pause(10); // Pause 10 milliseconds between next measurement
}
}
 
@emzdanow
Why do you do generation like this?
RB4 = 1; // 10 commands of RB4 = 1 is 10us
RB4 = 1; // pulse high (1 inst cycle per us
RB4 = 1;
RB4 = 1;
RB4 = 1;
RB4 = 1;
RB4 = 1;
RB4 = 1;
RB4 = 1;
RB4 = 1;
RB4 = 0;
Are you sure that every instruction takes 1 us exactly??
Why don't you make it as a delay??
e.g. __delay_us(10);

But if you decided to make it as a square pulse, make sure that the low interval is in range of ms not us as the high interval is.

And make greatly sure that you can run the timer in your pic and see if it's 16 bit or just 8 as it's highly important.

Good Luck :)
 

Thread Starter

emzdanow

Joined Jun 14, 2010
23
I have changed my code to use delays to generate pulse, but still my uC is not detecting a high signal from the echo line, I am running out of ideas....
 

BMorse

Joined Sep 26, 2009
2,675
For one, the PING sensor uses 1 IO to receive the start pulse, and to also signal for an echo, I do not see in your code where you are changing the output pin to an input to capture the echo....

B. Morse
 

Thread Starter

emzdanow

Joined Jun 14, 2010
23
Got it working finally! I changed my input and output pins to the PORTA register. Dont know why this worked but definitely learned some things on the way, thanks for all the help!
 

retched

Joined Dec 5, 2009
5,207
Why it worked:

from BMorse's post # 13:
the PING sensor uses 1 IO to receive the start pulse, and to also signal for an echo, I do not see in your code where you are changing the output pin to an input to capture the echo....
You have to set pin to OUTPUT.
Send pulse
Switch pin to INPUT
receive echo on SAME pin you send pulse on.
Check timer to see the time between send and receive.
 
Top