Ultrasonic Sensors are widely used for non-contact proximity, presence and distance measuring applications. These devices work on a similar principle of sonar or radar which evaluates the target by interpreting the echo from sound or radio waves. It emits a short high frequency sound waves and evaluates echo which is reflected back from the target. Sensors uses the time interval between sending the sound waves and receiving the echo to determine the distance of target. Most of the ultrasonic sensors are equipped with temperature compensation circuit to avoid changes in readings due to temperature changes.
Ultrasonic Sensors can work in 3 different modes :
Thru-Beam
Diffuse Reflective
Retro Reflective
Thru-Beam Mode Ultrasonic Sensor
In this mode ultrasonic transmitter and receiver are two separate units as shown in the above diagram. Transmitter emits high frequency sound waves and receiver detects it. A target can easily detected when it block the signals send by the transmitter.
Diffuse Reflective Mode Ultrasonic Sensor
In this mode Ultrasonic transmitter and receiver are put together in a single package as shown in the above diagram. The ultrasonic transmitter continuously emits high frequency sound waves. When a target comes within the operating range of the sensor, the receiver will get the echo reflected from the target.
Retro-Reflective Mode Ultrasonic Sensor
In this mode we are using one more component called Retro-Reflector. As in the previous case transmitter and receiver are in the same package. Usually this mode is used to detect target which is far from the sensors. The retro-reflector is placed a little far away from the Ultrasonic Sensors. The high frequency sound waves emitted by the transmitter is reflected by the retro-reflector and it is detected by the receiver. Thus when a target comes across the sensor and retro-reflector the ultrasonic waves will not reflected back to receiver. Here is one problem, the wave may get reflected from the target itself, to avoid this a polarizing filter is used in the sensor such that it detects only the wave reflected from the retro-reflector.
Ultrasonic Distance Sensor : PWM Output
The PING ))) Ultrasonic Sensor detects objects or measure distance by emitting a short ultrasonic burst and listening for its echo. Its operation is explained in the following steps.
1.The host microcontroller provides a trigger pulse.
2.The sensor emits a short 40 KHz ultrasonic burst.
3.The output of the Sensor becomes High.
4.The ultrasonic burst travels through air about a speed of 1300 feet per second.
5.The ultrasonic waves hits a target and gets reflected back.
6.The sensor detects the echo.
7.The output of the Sensor becomes Low.
Ultrasonic Distance Sensor : Serial ASCII Output
Compared to PWM output sensor, ASCII output sensors are more easier to programming. It directly provides the measured distance in ASCII format. It can be easily interfaced with a microcontroller using USART. Just connect the output of the sensor to RX pin of the microcontroller. For example take Rhydolabz product. It can accurately measure distances from 2cm to 4m and works at 5V DC power. Unlike PWM output sensors it is automatically triggered in every 500ms. It provides ASCII output at 9600 baud rate via UART and the output distance is in centimeters (cm).
Article courtesy of electrosome.com
How to use Ultrasonic Sensors
Re: How to use Ultrasonic Sensors
Simple PIC program for HS-SR04
Code: Select all
#include <16F876a.h>
#FUSES NOWDT, HS, NOPUT, PROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG
#use delay(clock=20000000)
#define use_portb_lcd true
#include "flex_lcd.c"
int16 distance, time; // Defining variables
// Defining the pins
#define trig pin_A0 // Change as you wish, can use any pin in the MCU
#define echo pin_A1 // Change as you wish, can use any pin in the MCU
void main()
{
lcd_init(); // initiating the LCD
delay_ms(50);
printf(LCD_PUTC, "\f Sonar test");// for LCD & MCU restart troubleshooting
delay_ms(300); // Boot-up delay, for troubleshooting
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); // initiating timer
while(true)
{
output_high(trig); // ping the sonar
delay_us(20); // sending 20us pulse
output_low(trig);
while(!input(ECHO)); // wait for high state of echo pin
set_timer1(0); // setting timer zero
while(input(ECHO)); // Wait for high state of echo pin
time = get_timer1(); // Getting the time
distance = time * 0.028 + 1.093 ; // Calculating the distance
lcd_gotoxy(1,1);
printf(lcd_putc, "\fTime :%Lu",time); // Display the time
lcd_gotoxy(1,2);
printf(lcd_putc, "\fDistance = %Lu", distance); //Display distance
delay_ms(1000);
}
}
Re: How to use Ultrasonic Sensors
Another C (CCS compiler) code for PIC
Code: Select all
/*
* main.c
*
* Description:
* This is a driver for the SRF04 ultrasonic module for the CCS
* PICC compiler.
*
* For information of the SRF04 module, go to:
* http://www.robot-electronics.co.uk/htm/srf04.htm
*
* Author: Martin Dubuc ([email protected])
* http://members.rogers.com/martin.dubuc/Robotics/Tips.html
*
* Creation date: February 26, 2003
*/
/*
* Calculation of the distance with the ultrasonic module relies
* on the microcontroller timing services. The distance is
* calculated according to the amount of time an ultrasound takes
* to echo on obstacles. The shorter it takes for the echo to come
* back, the closer the obstacle.
*/
#ifdef __PCM__
#include <16f877.h>
/* Microcontroller configuration bits */
#fuses HS,NOPROTECT,NOWDT,BROWNOUT,PUT,NOLVP
#ORG 0x1F00,0x1FFF {} /* Reserve memory for bootloader for the 8k 16F876/7 */
#device PIC16F877 *=16 /* Allow RAM to expand beyond 256 bytes */
#else // PIC18F
#include <18f452.h>
#fuses NOOSCSEN,HS,BORV20,NOBROWNOUT,PUT,WDT128,NOWDT,CCP2C1,NODEBUG,NOLVP,STVREN,NOPROTECT,NOWRT,NOWRTD,NOWRTB
#device PIC18F452 *=16 /* Allow RAM to expand beyond 256 bytes */
/* Remap reset and interrupt vector for the PIC18F bootloader */
#BUILD(reset=0x200)
#BUILD(interrupt=0x208)
/* Reserve memory for the PIC18F bootloader */
#ORG 0,0x1FF
dummy() {
#ASM
NOP
#ENDASM
}
#endif /* __PCM__ */
/* The 20_MHZ_CLOCK define is used to indicate whether we are using
a 4 MHz or 20 MHz clock */
#define 20_MHZ_CLOCK
/* Set the clock speed according to the 20_MHZ_CLOCK definition.
If 20_MHZ_CLOCK is defined, set clock speed to 20 MHz,
otherwise, set it to 4 MHz. */
#ifdef 20_MHZ_CLOCK
#use delay(clock=20000000)
#else
#use delay(clock=4000000)
#endif
/* Directive for RS-232 interface */
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
/* Ultrasonic module definitions */
/* Delay definitions */
#define INPUT_TRIGGER_DELAY 10 /* In microseconds */
#define DELAY_BETWEEN_ECHO_PULSE 10 /* Delay between end of echo and
trigger pulse */
/* Maximum elapsed time for an echo pulse is approx. 36 ms */
#ifdef 20_MHZ_CLOCK
#define MAX_DELAY_ECHO_PULSE 44000 /* Number of timer increments
for 35 ms using prescale of 4 */
#else
#define MAX_DELAY_ECHO_PULSE 35000 /* Number of timer increments
for 35 ms using prescale of 1 */
#endif
/* State definitions */
#define START_TX 0
#define WAIT_FOR_RX_HIGH 1
#define WAIT_FOR_RX_LOW 2
#ifdef 20_MHZ_CLOCK
/* Every Timer1 increment takes 0.8 us with prescale of 4 */
/* t us / 1000000 us/s * (347 m/s) * (100 cm/m) / 2 */
/* = # increments * 0.8 / 5000 * 347 or roughly t / 72 */
#define GET_DISTANCE(t) (t / 72)
#else /* 4 MHz clock */
/* Every increment takes 1 us with prescale of 1 */
/* t us / 1000000 us/s * (347 m/s) * (100 cm/m) / 2 */
/* = # increments / 5000 * 347 or roughly t / 58 */
#define GET_DISTANCE(t) (t / 58)
#endif
/* Hardware pin definition */
#define ULTRASONIC_TX PIN_B3
#define ULTRASONIC_RX PIN_B4
#define INFINITE (0xffff)
/* Type definitions */
typedef int uint8_t;
typedef long uint16_t;
/* Variable definitions */
uint16_t echo_delay;
uint8_t state;
boolean distance_ready = FALSE;
/* Global variable definitions */
uint16_t distance = INFINITE; /* This is the distance of the closest
object ahead of the ultrasonic
module (in cm). If set to INFINITE,
there are no objects in sight. */
/* Function prototypes */
/* Public interface */
void main(void);
void init_pins(void);
void init_globals(void);
void init_timers(void);
void init(void);
void rtcc_isr(void);
void rb_isr(void);
/* Driver implementation */
/* Init hardware pins: Set up the TRIS and set the pins to their
* default values.
*/
void
init_pins(void) {
/* Set up the various pins in/out */
set_tris_b(0b00010000); /* B3 is output. B4 is input.
Rest is unused */
/* Set initial condition for ultrasonic transmitter */
output_low(ULTRASONIC_TX);
} /* init_pins */
/* Initialize all global variables. This is not strictly required
* because we initialize all global variables to default values, but
* would be important if we ever re-initialized the values after the
* microcontroller starts running.
*/
void
init_globals(void) {
distance_ready = FALSE;
state = START_TX;
} /* init_globals */
/* Driver initialization. Initialize pins, global variables,
* interrupts and timers.
*/
void
init(void) {
init_pins();
init_globals();
init_timers();
// Enable Timer0 and RB4-RB7 interrupts
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
printf("SRF04 Ultrasonic Module Driver\r\n");
} /* init */
/* Initialize the Timer0 timer. */
void
init_timers(void) {
/* Set up Timer1 */
/* Following settings will allow for 1 cm precision */
#ifdef 20_MHZ_CLOCK
setup_timer_1(T1_INTERNAL | T1_DIV_BY_4);
#else // 4 MHz
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
#endif
} /* init_timers */
/* This is the main control loop. */
void
main(void) {
init();
for ( ; ; ) {
if (state == START_TX) {
/* First, toggle the ULTRASONIC_TX pin to generate echo signal. */
/* Pull ultrasonic TX pin high */
output_high(ULTRASONIC_TX);
/* Get the other side the chance to see this */
delay_us(INPUT_TRIGGER_DELAY);
output_low(ULTRASONIC_TX);
/* Wait for pulse on ULTRASONIC_RX pin. Distance is measured by
using time it takes for ultrasound to echo, which is
calculated according to length of echo pulse on ULTRASONIC_RX
pin. Will detect the pulse in the RB interrupt service
routine (ISR). We use ISR to allow us to continue processing
while transmitting/receiving ultrasounds. */
set_timer1(0);
state = WAIT_FOR_RX_HIGH;
}
if (get_timer1() > MAX_DELAY_ECHO_PULSE)
distance_ready = TRUE;
/* In state 1, wait for low to high transition on ULTRASONIC_RX pin.
We will detect this transition in the RB interrupt
service routine. */
/* In state 2, wait for high to low transition on ULTRASONIC_RX pin.
We will detect this transition in the RB interrupt
service routine. */
if (distance_ready) {
#ifdef 20_MHZ_CLOCK
if (get_timer1() >= 44000) {
#else
if (get_timer1() >= 35000) {
#endif
printf("distance = INFINITE\r\n");
distance = INFINITE;
}
else {
distance = GET_DISTANCE(echo_delay);
printf("distance = %lu\r\n", distance);
}
distance_ready = FALSE;
// Prepare for next reading
state = START_TX;
/* Make sure there is an appropriate delay between end of echo
and trigger pulse. */
delay_ms(DELAY_BETWEEN_ECHO_PULSE);
delay_ms(500);
}
delay_us(20);
}
} /* main */
#int_rb
void rb_isr(void) {
if ((state == WAIT_FOR_RX_HIGH) && input(ULTRASONIC_RX)) {
/* Detected a low to high transition */
state = WAIT_FOR_RX_LOW;
set_timer1(0);
}
if ((state == WAIT_FOR_RX_LOW) && !input(ULTRASONIC_RX)) {
/* Detected a high to low transition */
echo_delay = get_timer1();
distance_ready = TRUE;
}
} /* rb_isr */