Parallax PING))) ?


19 posts
by jdj » Wed Jun 06, 2012 10:18 pm
Hi there Forum,

I have a small robotics project in mind. In this I need some distance measurements and I thought that the ever used Sharp IR range sensors would do the trick (together with an ADC of course). However I stumbled on the Parallax PING))) ultrasonic range finder which has an impressive 3cm to 3-4meter range for less € than one Sharp IR... tempting of course. The Sharp:s are either like 10-80 cm, 100-200cm etc. etc. The PING))) would do both far and near object ranging at once.

However, there is a catch of course! The PING))) use one pin only for communication (while the Sharp is an anlog piece, so it needs ADC:s etc). The basic logic is as follows (if I have understood it correctly): You drive the pin high for a set period of time (2 - 5us) - this triggers the PING))) to 'schedule' an ultrasonic 'ping' 750us later. The PING))) then drives the signal high when it emits the pulse and drives it low again when it senses an echo. Time lapsed between the high and low events is the time the acoustic signal has travelled (i.e. from the sensor and back again).

My initial thought was "ah well, nice, cheap, but won't work in the regular linux environment" (due to timing inaccuracies in a multitasking environment). Also, my cats would probably appreciate the IR sensors.

But then... according to the Wiki, the RPi GPIO pins are able to work as both inputs and outputs, and are able to trigger interrupts on high/change (amongst others)... my mind started churning on dark thoughts (according to my cats); perhaps it is possible after all!

The logic would then be to do something like this (most likely in a kernel space driver):
- user space program calls for a range probe.
- driver change an GPIO pin to output, drives it high for the required amount of time (2 - 5us).
- driver switch the GPIO pin to input, and sets an interrupt handler on input change.
- when the PING))) drives the input high, the driver notes an appropriate time from the function clock_gettime() using CLOCK_REALTIME or similar (i.e. get a very good start time).
- then the driver sleeps again until the next change (i.e. PING))) drives it low again), it gets the interrupt, notes the time, does the math and returns the range.

What do you guys & gals (I hope) think? This ought to be possible?

More info on the PING))):
Supply voltage +5V
Communication: Positive TTL pulse <- Really I don't know what this means.
Further: "Bidirectional TTL pulse interface on a single I/O pin can communicate with 5 V TTL or 3.3 V CMOS microcontrollers". I think I like the 3.3V parts since the GIPO pins are rated as such. :)

Cheers!
/ Daniel
Posts: 7
Joined: Mon Dec 26, 2011 3:15 pm
by klappy » Sat Jun 09, 2012 5:55 pm
I'm attempting to get any usable output from the Parallax Ping)) on the rPi as well.

Currently I'm using Ruby and a GPIO gem I've been working on:
http://rubygems.org/gems/gpio http://klappy.github.com/gpio/

So far I can get my readings to return in 142 microseconds which appears to be enough for a result even if it is inaccurate.

Has anybody else had any luck?
Posts: 2
Joined: Sat Jun 09, 2012 5:44 pm
by Phil Spiegel » Sat Jun 09, 2012 6:16 pm
You could look up 'Picaxe' or Revolution Software and then 'their' Ultrasonic measuring module and how its used on the Picaxe /PIC micro.
It seems ot be similar.
Posts: 209
Joined: Tue Jan 17, 2012 8:17 am
by jdj » Mon Jun 11, 2012 8:27 am
Thanks for the replies!

Klappy: Do you mean that you have an 142us inaccuracy? I.e. difference between repeated measurements of the same distance? That would mean ~2.5cm distance inaccuracy which I could live with.

I will order a pair and try them out; the seeedstudio ones are just ~€15, so if they don't work. Well... tough luck. I think the most tricky part will be to develop the driver anyway.

Cheers
/ Daniel
Posts: 7
Joined: Mon Dec 26, 2011 3:15 pm
by klappy » Mon Jun 11, 2012 7:04 pm
Imprecise would be more fitting than inaccurate in this case.

142us is the best timing I've obtained so far between my readings. Right now it is theoretical as I actually haven't returned more than just 0's from the signal pin.
Posts: 2
Joined: Sat Jun 09, 2012 5:44 pm
by SiXiam » Sat Jun 30, 2012 2:34 pm
Any updates on this?
My sensor arrived this week, so I'm just starting to get into the python programming.
Posts: 5
Joined: Sat Jun 30, 2012 2:32 pm
by SiXiam » Mon Jul 02, 2012 3:03 am
klappy wrote:Imprecise would be more fitting than inaccurate in this case.

142us is the best timing I've obtained so far between my readings. Right now it is theoretical as I actually haven't returned more than just 0's from the signal pin.
I think I can help you out there! ;)

After two solid days of effort I managed to get Python to return a number.
I can say four things about this number:
1) It changes based on the distance to an object
2) It is a small fraction, like 0.0073457982
3) Its created from timing, something the gpio module says its not meant to do
4) It probably isn't very accurate

My next step is to turn this number into a distance.
Here is the code, I hope it helps:
(Please excuse the son of Dracula!)

Code: Select all
# import time module
import time

# import gpio module
import RPi.GPIO as GPIO

alpha = 0
beta = 0
gamma = 0
delta = 0

# set up gpio pin 11 as output
GPIO.setup(11, GPIO.OUT)

# Be sure there is no signal to parallax ping: pin 11, 0 = False
GPIO.output(11, 0)

# send parallax ping a signal: pin 11, 1 = True
GPIO.output(11, 1)

time.sleep(0.00075)

# set up gpio pin 11 as input
GPIO.setup(11, GPIO.IN)

# send parallax ping a signal: pin 11, 1 = True
GPIO.input(11)

# Start time
alpha = time.time()

while GPIO.input(11) == 1 and delta < 20:
    delta = delta + 1
else:
    # Stop time
    beta = time.time()
    gamma = beta - alpha
    # print parallax ping value
    print gamma

# Alucard
print "What!"


Keep in mind I'm very new to Python.
I'm only up to Bucky's 36 Python tutorial!
http://www.youtube.com/watch?v=x57d_PaskKo
Posts: 5
Joined: Sat Jun 30, 2012 2:32 pm
by MagnusAycox » Sat Jul 21, 2012 10:56 am
Wouldn't it be better to build this in hardware (setting the PING))) off, counting and triggering)? Then just sending the result to the rPi by using the serial interface or USB? Then we have no need for fancy programming freeing the processor for more important tasks. Just a suggestion...
And yes, I also need a ultrasonic distance sonar. I'm not *just* a stuck up knowitall... ;)
Posts: 2
Joined: Sat Jul 21, 2012 10:44 am
by SiXiam » Sat Jul 21, 2012 3:08 pm
MagnusAycox wrote:Wouldn't it be better to build this in hardware (setting the PING))) off, counting and triggering)? Then just sending the result to the rPi by using the serial interface or USB? Then we have no need for fancy programming freeing the processor for more important tasks. Just a suggestion...
And yes, I also need a ultrasonic distance sonar. I'm not *just* a stuck up knowitall... ;)

Unfortunately the project I'm working on doesn't allow me to do that, but yes that is another method. A basic stamp is Parallax's preferred method.
Posts: 5
Joined: Sat Jun 30, 2012 2:32 pm
by MagnusAycox » Tue Aug 07, 2012 11:45 pm
I found this which I have choosen. It interfaces using the I2C bus and no special timing or anyting else is needed. Just trigger it and fetch the range. Super neato... :)
http://www.acroname.com/robotics/parts/R241-SRF10.html
Posts: 2
Joined: Sat Jul 21, 2012 10:44 am
by notnewcivilman » Sun Sep 23, 2012 1:06 am
Has anyone made any progress with this?
I have tried my self and i'm not really getting any results.

There is a chance that I wired this thing up wrong but i'm not sure...
I'm using an external power supply (5VDC) to power the Ping))) device.
Wiring is:
GND -> -side of power supply
5V -> +side of power supply
SNG -> Pin Number 11

I used the code above (with some modifications) and i'm getting numbers but the numbers are not changing to reflect that there is an object in the sensors path.

This is what is getting returned:
Code: Select all
Time:  0.000296115875244
Inch:  4.0011177063
CM:  10.162838974

Time:  0.000293016433716
Inch:  3.95923805237
CM:  10.056464653

Time:  0.000289916992188
Inch:  3.91735839844
CM:  9.95009033203



This is the code I used with some modifications.
Code: Select all
#!/usr/bin/python
# speed of sound 1126 feet per second
#13512 inches per second
# import time module
import time

# import gpio module
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)

count = 0
#loop used to check values multiple times
while (count < 100):

   alpha = 0
   beta = 0
   gamma = 0
   delta = 0
   inch = 0
   cm = 0
   
   # set up gpio pin 11 as output
   GPIO.setup(11, GPIO.OUT)

   # Be sure there is no signal to parallax ping: pin 11, 0 = False
   GPIO.output(11, 0)

   # send parallax ping a signal: pin 11, 1 = True
   GPIO.output(11, 1)
         
   time.sleep(0.00075)
   # set up gpio pin 11 as input
   GPIO.setup(11, GPIO.IN)

   # send parallax ping a signal: pin 11, 1 = True
   GPIO.input(11)

   # Start time
   alpha = time.time()

   while GPIO.input(11) == 1 and delta < 20:
      delta = delta + 1
   else:
      # Stop time
      beta = time.time()
      gamma = beta - alpha
      # print parallax ping value
      # calc for speed of sound at inches per second should be "correct"
      inch = 13512 * gamma
      #calc for speed at centimeters per second should be "correct"
      cm = 34320.48 * gamma
      #displays time, inches, cm should be the distance the object is from the device
      print "Time: ", gamma
      print "Inch: ", inch
      print "CM: ", cm
      #increase count by 1
   count = count + 1
   #sleep thread for 2 seconds
   time.sleep(2)


One thing i did notice was that even if i unplugged the sensor I would get the same results.

I've got an Arduino UNO on order. I'm fairly certain i can get some results with it and communicate them back to the pi.

I almost feel like i'm at a loss getting the pi to get the correct info being that there "could" be some timing issues, but if anyone can tell me what i might be doing wrong that would be great!
Posts: 6
Joined: Sun Jul 08, 2012 3:17 am
by SiXiam » Sun Sep 23, 2012 1:10 am
Unfortunately the timing method will not work.
The Raspberry Pi can't do timing from the software side, it is too inaccurate.
It must be done from the hardware side.
Posts: 5
Joined: Sat Jun 30, 2012 2:32 pm
by notnewcivilman » Sun Sep 23, 2012 1:30 am
SiXiam wrote:Unfortunately the timing method will not work.
The Raspberry Pi can't do timing from the software side, it is too inaccurate.
It must be done from the hardware side.


Any ideas or insight how we could approach this?
Or is it not possible to do timing from the hardware side?
As stated above i've got an arduino uno on order... so its not that big of deal...

I'll be more than happy to post my results once i get something going with the pi and uno talking together.
Posts: 6
Joined: Sun Jul 08, 2012 3:17 am
by SiXiam » Sun Sep 23, 2012 1:38 am
I think the I2C. There is a pin that is supposed to be used for ping, but I'm not sure if anyone got it to work right.

Frankly I gave up after total frustration with how slow and unresponsive the Raspberry Pi is as a programming tool. I suggest remoting into the device.
Posts: 5
Joined: Sat Jun 30, 2012 2:32 pm
by notnewcivilman » Sun Sep 23, 2012 2:01 am
SiXiam wrote:I think the I2C. There is a pin that is supposed to be used for ping, but I'm not sure if anyone got it to work right.

Frankly I gave up after total frustration with how slow and unresponsive the Raspberry Pi is as a programming tool. I suggest remoting into the device.


LOL :lol:

:? I'm not sure what this I2C stuff is... Guess i have some homework to do.
Pin 3 and/or 5 support I2C but im not sure what the difference between the two are.
Pin 12 supports PWM which appears to be what the arduino uses as I/O. I'm not sure if using this pin will make any difference.

I'm most definitely going to take your advice and remote into the device.
:idea: I'm thinking about having the arduino handle all of the distance code and just have it report its findings to the pi via pulse counts. This may not work but thats the starting plan. I'm all kinds of new to this robotics/electronics stuff.
Posts: 6
Joined: Sun Jul 08, 2012 3:17 am
by notnewcivilman » Sun Oct 14, 2012 1:44 am
OK so i got something working with this. I'm using an arduino to report the finds to the pi using a relay.
This may not be what anyone is wanting to do but might help someone get something else accomplished. I could have used the UART pins but decided not to.

The results returned are not 100% accurate but are really close.
Every once and a while I will get a stray number. Example ill be reading a consistent 14 then ill receive a 2 when nothing has changed. I would assume that this is being caused by the two devices being out of "sync" but none the less I'm getting results.
The Python code could be altered to check for these changes and dis guard the "false" results

All the code listed below is not all mine it has been stripped from here and there.

R-Pi Python code:
Code: Select all
#!/usr/bin/python
import RPi.GPIO as GPIO
import time
from datetime import datetime

GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.IN)

count = 0
tstart = 0
tstop = 0
dif = 0
tdif = 0

#creates infinite loop
while True:
   input_value = GPIO.input(11)
   #sets "start" time
   tstart = datetime.now()
   #resets dif to 0
   dif = 0
   
   #runs loop while time difference is less than 100ms *i think*
   while dif < 1000:
      #checks for input True=NO INPUT False=INPUT
      if input_value == False:
         #increase count by 1 to designate that input was received
         count += 1
         #sets "stop" time
         tstop = datetime.now()
         #sets time difference between "start" and "stop"
         tdif = tstop - tstart
         #set time difference to compare
         dif = tdif.microseconds / 100
         ####needed to keep "while dif < 1000" loop under control without this counts received will be wrong
         while input_value == False:
            input_value = GPIO.input(11)
         ###else statement may not be needed
      else:
         input_value = GPIO.input(11)
         #sets "stop" time
         tstop = datetime.now()
         #sets time difference between "start" and "stop"
         tdif = tstop - tstart
         #set time difference to compare
         dif = tdif.microseconds / 100
               
   #shows count and sets count to 0 if greater than 0
   if count > 0:
      print count
      count = 0      


Arduino Code:
Code: Select all
const int pingPin = 11;
unsigned int duration, inches, count;

void setup() {
  Serial.begin(9600);
}

void loop() {
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
  pinMode(pingPin,INPUT);
  duration = pulseIn(pingPin, HIGH);
  inches = duration / 74 / 2;
  count = 0;
  while(count < inches) {
    digitalWrite(7, HIGH);
    delay(1);
    digitalWrite(7, LOW);
    delay(1);
    count++;
  }
  Serial.println(inches);
  delay(100);
}
Posts: 6
Joined: Sun Jul 08, 2012 3:17 am
by feiry » Sun Oct 13, 2013 8:34 am
Hi All,

I finally able to get the correct distance value from my PING Parallax sensor.
It doesn't need an i2c code, there is no sda/scl pins like the srf08 sensor.

I just have to measure the duration the pin go high and return low after I send a trigger signal.
After carefully apply the same logic of the arduino code in (http://arduino.cc/en/Tutorial/Ping), but use different calculation of the duration to cm, because the duration is in seconds instead of microseconds by multiplying with 34000 cm/sec.

I use pin 11 as the SIG pin, 5v to pin 2, GND to pin 6.

Here's the final code:
Code: Select all
import time
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.OUT)

#cleanup output
GPIO.output(11, 0)

time.sleep(0.000002)

#send signal
GPIO.output(11, 1)

time.sleep(0.000005)

GPIO.output(11, 0)

GPIO.setup(11, GPIO.IN)

while GPIO.input(11)==0:
   starttime=time.time()

while GPIO.input(11)==1:
   endtime=time.time()
   
duration=endtime-starttime
distance=duration*34000/2
print distance


Hope it will be useful for someone in the future...
Posts: 11
Joined: Fri Jan 04, 2013 2:08 pm
Location: Bandung, Indonesia
by psychephylax » Tue Oct 29, 2013 6:09 am
Thanks! I tried your code and get the measurements in centimeters (+/- 2 or 3 cm)
Posts: 1
Joined: Tue Oct 29, 2013 6:07 am
by kohcl » Wed Jan 08, 2014 1:40 am
hi feiry, thanks so much for your code.
Posts: 1
Joined: Wed Jan 08, 2014 1:37 am