PING Ultrasonic Rangefinder

The PING))) Ultrasonic rangefinder is a great sensor to add to a robot when the robot needs to know how far it is from an object or obstacle. The rangefinder takes up only one I/O pin on your microcontroller. Because it uses only a single I/O pin it needs a unique control algorithm. It sends out an ultrasonic signal from one of its ultrasonic transducers and measures how long it takes for that signal to bounce back to the 2nd ultrasonic transducer. The time can be converted to inches or cm.  More info can be found on the Parallax website.


Purpose of Sensor: Rangefinding

Details of Purpose: Range of 2cm to 3m( ~.75" to 10' )

Power Requirements: 4.5 - 6V @ 35mA draw

Pins needed : One I/O pin


Pseudo Code:

 Make the I/O pin an Output

Bring LOW the  pin that the PING rangefinder is connected

Bring the  pin HIGH for 5 microseconds

Bring the  pin LOW

Make the I/O pin an Input

Wait until the pin goes HIGH

Use a timer to see how much longer it takes for the pin to become LOW

The time it took to become low is now our raw distance ( in microseconds)

Divide Raw Distance by two since it includes the time for a return trip of the sonar

Raw distance * 2257 is our distance in cm

Raw distance * 889 is our distance in inches





'Where Ping is the alias for the  I/O port where the PING Rangefinder is connected to( e.g. PORTB.1)
Get_sonar:                                   ' we will call this subroutine Get_Sonar
  LOW Ping                                  'make trigger 0-1-0
  PULSOUT  Ping, 1                        'activate sensor
  PULSIN  Ping, 1 rawDist               'measure echo pulse  and store it in variable rawDist
  rawDist = rawDist * 10                    'convert to uS
  rawDist = rawDist / 2                          'remover return trip
                                'get sensor value                                                               
  inches = rawDist ** 889                 'multiply by 889 to convert to inches
  cm = rawDist **2257                     'multiply by 2257 to convert to centimeters
  Return                                           ' End subroutine


C Code:

Credit to Pomprocker

Uses the reset timer macro and "timer.h" - be sure to include that

//**************RESET TIMER**************
void reset_timer_0(void) {
//restart timer count
TCNT0=0x00;//clear timer
//clear timer0's overflow counter.


Note:  Pin used is PORTC.1 . For any other port , just change the pin # and also change the C in DDRC to the port you are using . For example for PORTE.0 use DDRE and change PingPin to 0.

int PingPin = 1;          // assign pin #1 o to the Ping Sensor
int PingVal = 0; // initialize and assign Ping Sensor Reading Value
PORT_ON(DDRC, PingPin); // Switch PingPin to OUPUT
// ------Trigger Pulse--------------
PORT_OFF(PORTC, PingPin); // Bring PingPin low before starting trigger pulse
delay_us(2); // Wait for 2 microseconds
PORT_ON(PORTC, PingPin); // Bring PingPin High for 5us according to spec sheet.
delay_us(5); // Wait for 5 microseconds
PORT_OFF(PORTC, PingPin);; // Bring PingPin Low and standby
//--------End Trigger Pulse---------------------
FLIP_PORT(DDRC, PingPin); // Switch PingPin to INPUT
loop_until_bit_is_set(PINC, PingPin); // Loop until the the PingPin goes high (macro found in sfr_def.h)
//clears timer, reset overflow counter
reset_timer_0(); //reset timer 0
loop_until_bit_is_clear(PINC, PingPin); // Loop until the the PingPin goes low (macro found in sfr_def.h)
//read timer0's overflow counter
//255 is count before overflow, dependent on clock
int elapsed_time=timer0GetOverflowCount()*255+TCNT0;
// The PING))) returns a pulse width of 29.033 uS per centimeter
PingVal = elapsed_time;