Parallax PING))) Arduino example issues

At least one of the PING Arduino interface sketches has a number of subtle problems when the communication between the Arduino and the sensor is analyzed in detail. The problems include multiple trigger pulses of the wrong pulse width.

The example does work, but I suspect using code that doesn't actually do what it claims to do could cause problems in other circumstances.

Details here.


  • This Parallax code should work.
  • The Ard**n* code referenced by Genetix does not include the offending pullup resistor in the original code noted by Oiberex1.

    Here is yet another way written in simpleIDE. I normally would use "ping.h" but thought this more illustrative.
      PING))) Sensor in Simple IDE
      Typically would use "ping.h" but I didn't 
    #include "simpletools.h"                      // Include simple tools
    #define pingpin 15
    int main()                                    // Main function
         input(pingpin);                         //the direction register
         set_output(pingpin, 0);                 //just the output register
      while(1)                                  //forever 
        pulse_out(pingpin, 10);
        long usec = pulse_in(pingpin, 1) / 2;        //one way time
        putStr("One-way time in uSec:  ");
        long mm = (usec * 305) / 1000;               //speed of sound taken to be 1000 ft/sec
                                                     // 1 millifoot = 305 micrometers
        putStr("   Distance in mm:  ");
      }   //end of while  
    }     //end of main() 

    I took speed of sound to be 1000 ft/sec. Here are a few actual vs measured points, all in mm.
    Actual   Measured
     30         33
     50         51
     70         68
    100        99
    150       154
    200       205
    250       246
    2560 x 1920 - 1M
  • The Parallax code and both the original Arduino and the modified Arduino code work and produce correct distance measurements.

    I was just surprised to see that the Arduino code was not actually producing a single 5 usec pulse to trigger the sensor as the code was attempting to do, and that it appears the Arduino digitalWrite function is actually incapable of producing a pulse of less than about 11 usec (at least on an Arduino Uno).

    The original Arduino code works, but it probably wouldn't be a very good example to use in other circumstances (say, with a less tolerant sensor ) since it is not actually producing the single 5 usec pulse as is intended.

    I tested Parallax's simpletools pulse_out function and it is capable of reliably producing down to a 1 usec pulse (on my PPDB anyway.) Arduino doesn't appear to offer the equivalent of a pulse_out function.

    Again, not a big deal really. All versions of the code actually produce valid distance measurements.

    I guess my conclusion would be: Don't use the Arduino digitalWrite function for pulses of less that maybe 20 us. Use direct port access instead.
  • Actually, I just found a source (scope trace here) that suggests that Arduino digitalWrite's smallest pulse (two digitalWrites in sequence with no delay) is just under 5 usec.
  • Both the Arduino example and KickStart code are actually within spec for a PING (can't say about another sensor), which is why they both work. I'm not sure why the Arduino example has that pullup resistor line in it, but that could be a vestige from pre-Uno days.

    In the PING docs, the length of the trigger pulse is stated as 2us minimum, 5us typical, and no maximum. 5us, 10us, even 50us, it doesn't matter. There is a minimum holdoff of 750 us, and the assumption there is that any additional trigger pulses during this phase will be ignored in the PING. So any double trigger would likely to be ignored anyway, at least when using a genuine Parallax part.

    It's fairly well known the digitalWrite function for the Arduino takes many cycles, as it has a lot more built-in tasks it performs, including checking if PWM is active, validating the pin number, and so on. Naturally direct port writes will be faster because all these clock cycles are saved. It's up to you to make sure you don't clobber a pin.

    If you look closely at the BS2 code in the PING doc examples and KickStart, you'll see the delay value for the pulse is '5', which for a BS2 is actually 10us. The Arduino KickStart keeps the 5us value because it "looks right" based on the specs, even though the Arduino cannot produce pulses this short using digitalWrite.

    There could be some cheap imported knockoffs that might double-trigger or can't handle a pulse longer than X, but that wouldn't be Parallax's concern. In any case, I doubt there would be many of these out there, as its maker would test it with an Arduino, using the most common examples available, which include the one from Arduino.
Sign In or Register to comment.