Ultrasonic range finder beginner

Discussion in 'Embedded Systems and Microcontrollers' started by emzdanow, Jun 29, 2010.

  1. emzdanow

    Thread Starter New Member

    Jun 14, 2010
    23
    0
    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.
     
  2. emzdanow

    Thread Starter New Member

    Jun 14, 2010
    23
    0
    I guess my real question is how do I time the length of an input pulse with my μController?
     
  3. retched

    AAC Fanatic!

    Dec 5, 2009
    5,201
    312
    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.
     
  4. emzdanow

    Thread Starter New Member

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

    Member

    Apr 14, 2010
    377
    19
    i would suggest moving this post to the embedded forum - there are people over there that can definitely help you with this.
     
  6. BMorse

    Senior Member

    Sep 26, 2009
    2,675
    234

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

    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:

    Code ( (Unknown Language)):
    1. 'Devantech SRF04 Sonar Ranger program
    2. Dim W1 As New oWord    'Sonar Reading
    3. Dim X1 As New oWord
    4. Dim Y1 As New oWord
    5. Dim SonarSrv As New OServo
    6.  
    7. Dim EchoTimer As New oTimer
    8. Dim TmrControl As New oGate(1)
    9. Dim INIT As New oDio1
    10. Dim ECHO As New oDio1
    11.  
    12. Sub Init_Sonar()
    13.     'Sound travels 1 inch every 73.746us
    14.     'Timer uses 625Khz clock Frequency (5Mhz/8)
    15.     '625Khz is 1.6us per clock tick
    16.     'Max range of sonar is Approx. 9m (354 inches/ 899cm)
    17.     'Distance of echo roundtrip is 354 *2 = 708 inches
    18.     '708 * 73.746us /1.6us = 32633 'ticks at max range
    19.     '32632 / (354) = 92 --> = inches
    20.     '32632 / (899) = 36 --> = cm
    21.  
    22.     EchoTimer.ExtClock=cvOff
    23.     EchoTimer.PreScale=3
    24.  
    25.     INIT.IOLine = 6
    26.     INIT.Direction = cvOutPut
    27.     INIT.Value = 0
    28.  
    29.     ECHO.IOLine = 7
    30.     ECHO.Direction = cvInput
    31.  
    32.     TmrControl.Input1.Link(ECHO.Value)
    33.     TmrControl.OutPut.Link(EchoTimer.Operate)
    34.     TmrControl.Operate = cvTrue
    35.  
    36. End Sub
    37.  
    38.  
    39. Sub Read_Sonar()
    40.     EchoTimer.Value = 0    'Clear old result
    41.     INIT.Value = 1
    42.     INIT.Value = 0        'Pulse sonar input
    43.     OOPic.Delay = 1        'Give ECHO Chance to go high
    44.     'Wait until echo goes low again to return reading
    45.     'ECHO might be low already, but could take up to 36ms
    46.     'timer automatically runs while echo is high
    47.  
    48.     While (ECHO.Value=1)
    49.     Wend
    50.  
    51.     W1 = (EchoTimer.Value/92)    'Convert to inches
    52.  
    53.     OOPic.Delay = 1
    54.  
    55. End Sub
    56.  
    B. Morse
     
  7. kingdano

    Member

    Apr 14, 2010
    377
    19
    i knew someone in this forum would come through for OP
     
  8. emzdanow

    Thread Starter New Member

    Jun 14, 2010
    23
    0
    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
    }
    }
     
  9. BMorse

    Senior Member

    Sep 26, 2009
    2,675
    234
    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
     
  10. emzdanow

    Thread Starter New Member

    Jun 14, 2010
    23
    0
    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
    }
    }
     
  11. Sherif Amer

    New Member

    Jul 6, 2010
    8
    0
    @emzdanow
    Why do you do generation like this?
    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 :)
     
  12. emzdanow

    Thread Starter New Member

    Jun 14, 2010
    23
    0
    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....
     
  13. BMorse

    Senior Member

    Sep 26, 2009
    2,675
    234
    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
     
  14. emzdanow

    Thread Starter New Member

    Jun 14, 2010
    23
    0
    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!
     
  15. retched

    AAC Fanatic!

    Dec 5, 2009
    5,201
    312
    Why it worked:

    from BMorse's post # 13:
    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.
     
Loading...