Shop OBEX P1 Docs P2 Docs Learn Events
Trying to detect if Ping sensor is connected — Parallax Forums

Trying to detect if Ping sensor is connected

I'm looking at the Ping object and see that it returns a value when called. How do I abort the call when there isn't a Ping connected? Or maybe a better question is what is returned if there is no Ping connected? Does it just hang because it never sees the pin go high or low? If so how do I get past it? Maybe a watchdog timer?

Thanks for any help.

BTW- first post in the new forum format...

Don

Comments

  • LoopyBytelooseLoopyByteloose Posts: 12,537
    edited 2015-08-27 15:04
    No Ping? I would have to say nothing is returned.

    The easiest thing to do is to comment out the Ping code rather than add more code for a watch dog timer or some sort of test of presence.

    In fact, I have strong doubts that you can write code to see that the Ping is not attached. You might start having to track what is physically plugged in by building a special interlock.

    As best as I can recall, the Ping only returns a pulse when it hears one and that can be a long, long time if it isn't moving and nothing moves in front of it.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-08-27 15:31
    If a Ping is connected it will return a pulse even if there isn't an echo. It has its own timeout period. I don't recall what this time period is. I think it's around 20ms.

    I think the Ping object in the Propeller library will hang if no Ping connected. A watchdog timer is probably the easiest way to check if a Ping is connected. At least it's the easiest way I can think of.

    Edit: If you have a spare I/O pin, I think there's a way to modify the Ping object so one I/O pin will change after a timeout period (using a counter). Instead of having the waitpxx wait for a change on a single pin, it could look for a change on two pins so the timeout pin will free the cog from continuing to wait.
  • An oscilloscope would easily tell you what the Ping actually does during periods of inactivity.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-08-27 17:35
    I'm sure the Ping has a timeout and will pull the data line low if it doesn't detect an echo.

    There wasn't a timeout here but this shows what the line is doing while a measurement is taking place.

    attachment.php?attachmentid=88032&d=1325195663

    The Ping code toggles the signal line (the short pulse seen in the trace) and sets it as an input. The code both waits for the pin to go high and then waits for the pin to go low. If no Ping is connected, this will cause the cog to freeze.
    outa[Pin]~                                                                    ' Clear I/O Pin
      dira[Pin]~~                                                                   ' Make Pin Output
      outa[Pin]~~                                                                   ' Set I/O Pin
      outa[Pin]~                                                                    ' Clear I/O Pin (> 2 µs pulse)
      dira[Pin]~                                                                    ' Make I/O Pin Input
      waitpne(0, |< Pin, 0)                                                         ' Wait For Pin To Go HIGH
      cnt1 := cnt                                                                   ' Store Current Counter Value
      waitpeq(0, |< Pin, 0)                                                         ' Wait For Pin To Go LOW 
      cnt2 := cnt                                                                   ' Store New Counter Value
      Microseconds := (||(cnt1 - cnt2) / (clkfreq / 1_000_000)) >> 1                ' Return Time in µs
    

    Since the code leaves the signal line pin low and an input, it could be forced to terminate by another cog without the need of a second I/O pin. The other cog could set the pin as an output and toggle the line to stop the cog from waiting for the pin state changes.
  • Briefly looking at the OBEX code in "Ping))) Demo", you will indeed hang if the PING is not communicating. Looking at the OBEX code in "Ping PASM", it looks like you could detect a missing PING by checking if Echo_Length is zero.
  • Don MDon M Posts: 1,647
    So I am revisiting this project and was looking at the code suggested by Seairth. There were 2 different objects in the OBEX and one of them mentioned Echo_Length so I'm guessing that is the object he was thinking of.

    Here is the code from this object and what I don't understand is where the variable "Echo_Length" gets it's value from. In the beginning of the repeat loop it is assigned to the variable "Distance" in this statement- Distance := Echo_Length >> 1
    CON
            _clkmode = xtal1 + pll16x                       'Standard clock mode * crystal frequency = 80 MHz
            _xinfreq = 5_000_000
    
            Ping_Pin = 11                                   '  Pin that Ping))) Sensor is wired to
            DPu = 13512
    {{      DPu assumes Speed of Sound to be 1126 Feet per Second in Dry Air @ 68 °F.
            1126 * 12 = 1352 inches per second
    
    }}        
    VAR
    
            long          Sensor_Pin    
            long          Echo_Length
            long          Distance
            long          uSec
            long          Raw_Distance
            long          Remainder
    
    OBJ
    
            pst : "Parallax Serial Terminal"
          
    PUB   start  :  okay       
    
          pst.start(115_200)                    ' Start the Display
           
          Sensor_Pin := Ping_Pin                ' Prepare Variable
          
          cognew (@entry,@Sensor_Pin)           ' Start Assembly Routine in a new COG
          
          waitcnt(clkfreq + cnt)                ' Wait a second
    
          ' Prepare Display screen with Labels for data to be shown
          
          pst.str(string("          PING))) Demo",13,13))
          pst.str(string("  Raw Count in CLOCK Cycles........",13,13))
          pst.str(string("  One Way Time in CLOCK Cycles.....",13,13))  
          pst.str(string("  µSeconds to Target...............",13,13)) 
          pst.str(string("  Distance in Inches...............",13,13)) 
      
        repeat
            pst.Position(34,2)
            pst.ClearEnd      
            pst.dec(Echo_Length)      'Raw Count in CLOCK Cycles
    
            Distance := Echo_Length >> 1
            pst.Position(34,4)
            pst.ClearEnd
            pst.dec(Distance)         'One Way Time in CLOCK Cycles
    
            uSec := Distance / 80
            pst.Position(34,6)
            pst.ClearEnd
            pst.dec(uSec)             'µSeconds to Target
             
            pst.Position(34,8)
            pst.ClearEnd
            Raw_Distance := uSec * DPu  / 1_000_000
            Remainder := uSec * DPu // 1_000_000
            pst.dec(Raw_Distance)     'Distance in Inches
            pst.char(46)              'Print decimal point
            pst.dec(Remainder)        'Distance fractional portion
    
            waitcnt(clkfreq/4 + cnt)  'Wait to do it again
    
    
    Dat
    
    entry         org       0
                  rdlong    P_Pin, par                      'Read Main Ram to find out Pin Ping)) is wired to.
                  mov       Pin, #1                         'Set a 1 into "Pin"
                  shl       Pin, P_Pin                      'Shift the 1 to Pin bit
                  add       Trigger_Counter, P_Pin          'Add Pin into APIN of Counter
                  add       Echo_Counter, P_Pin             'Add Pin into APIB of Counter
                  mov       Echo_to_Main_Ram, par           'Echo_to_Main_Ram is distance to be returned.
                  add       Echo_to_Main_Ram, #4            'Make it the second Variable in the list
                  mov       frqa, #1                        'Set frqa to count 1 per clock
                  mov       time, cnt                       'Get original time stamp
    
    :loop         add          time, Echo_Holdoff           'Add Echo_Holdoff to time   
                  mov          ctra, Trigger_Counter        'Set counter to NCO single-ended mode
                  or           dira, pin                    'Set APIN to be an output
                  neg          phsa, Trigger_Pulse          'Send Trigger Pulse 2 µsec pulse  
                  waitcnt      time, Echo_Pulse             'Wait for Echo_Holdoff 750 µsec  
                  muxc         dira, pin                    'Make Ping))) Pin into an Input    
                  mov          ctra, Echo_Counter           'Time Echo Return Pulse     
                  mov          phsa, #0                     'Clear the accumulator 
                  waitcnt      time, Delay_B4_Next          'Wait for pulse to complete  ≈ 21.7 msec max 
                  mov          Echo, phsa                   'Read Echo Return Pulse length
                  wrlong       Echo, Echo_to_Main_Ram       'Write the result to Main Ram
                  waitcnt      time, #0                     'Wait B4 taking another measurment
                  jmp          #:loop                       'Loop forever
    
    Trigger_Counter         long    %00100_000_00000000_000000_000_<< 6  'NCO single-ended Mode
    Echo_Counter            long    %11010_000_00000000_000000_000_<< 6  'LOGIC A Mode
    
    Trigger_Pulse           long    160                     '2 µsec Trigger Pulse Width
    Echo_Holdoff            long    60_000                  '750 µsec wait B4 Measuring Echo Pulse
    Echo_Pulse              long    1_924_000               '1_924_000 for 40 reads per second
    Delay_B4_Next           long    16_000                  '200 µsec Delay B4 Next Cycle
    
    Pin                     res     1
    P_Pin                   res     1
    time                    res     1
    Echo                    res     1
    Echo_to_Main_Ram        res     1
    
    
                 fit
    
  • Don MDon M Posts: 1,647
    edited 2016-01-08 19:44
    I changed this line:
    pst.dec(Echo_Length)      'Raw Count in CLOCK Cycles   
    

    to this and it works when the Ping is disconnected but what I'm wondering is where the Echo_Length variable gets its value from in the first place.
    if Echo_Length == 0
              pst.str(string("Not connected"))     
            else
              pst.dec(Echo_Length)      'Raw Count in CLOCK Cycles
    
  • I think it gets its value in lines 7 and 8 of the PASM
    mov       Echo_to_Main_Ram, par           'Echo_to_Main_Ram is distance to be returned.
    add       Echo_to_Main_Ram, #4            'Make it the second Variable in the list
    

    It would be important to not change the order of the variables in VAR without changing line 8 in the pasm.
    Tom
Sign In or Register to comment.