How to use Ultrasonic Sensors

Microcontroller Topics
Post Reply
User avatar
Shehani
Lieutenant
Lieutenant
Posts: 61
Joined: Mon Aug 19, 2013 2:11 pm

How to use Ultrasonic Sensors

Post by Shehani » Mon Nov 25, 2013 12:32 pm

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
Ultrasonic Sensor Thru-Beam Mode
Ultrasonic Sensor Thru-Beam Mode
1.jpg (22.94 KiB) Viewed 7599 times
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
Ultrasonic Sensor Diffuse Reflective Mode
Ultrasonic Sensor Diffuse Reflective Mode
2.jpg (26.56 KiB) Viewed 7599 times
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
Ultrasonic Sensor Retro-Reflective Mode
Ultrasonic Sensor Retro-Reflective Mode
3.jpg (24.05 KiB) Viewed 7599 times
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
Ultrasonic Distance Sensor
Ultrasonic Distance Sensor
4.jpg (6.76 KiB) Viewed 7599 times
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 PING Sensor Operation
Ultrasonic PING Sensor Operation
5.png (32.95 KiB) Viewed 7599 times
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
User avatar
Saman
Lieutenant Colonel
Lieutenant Colonel
Posts: 828
Joined: Fri Jul 31, 2009 10:32 pm
Location: Mount Lavinia

Re: How to use Ultrasonic Sensors

Post by Saman » Mon Dec 23, 2013 2:53 am

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);
	}
}
User avatar
Saman
Lieutenant Colonel
Lieutenant Colonel
Posts: 828
Joined: Fri Jul 31, 2009 10:32 pm
Location: Mount Lavinia

Re: How to use Ultrasonic Sensors

Post by Saman » Mon Dec 23, 2013 2:55 am

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 */
Post Reply

Return to “Microcontrollers”