Submitted by airman00 on August 30, 2008 - 10:54pm.
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
BASIC Code:
'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.
timer0ClearOverflowCount();
}
//***************************************
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;