Wednesday 7 May 2014

Interfacing Ultrasonic Rangefinder with AVR

In this tutorial, we are going to interface ultrasonic rangefinder with the all popular ATMEGA8. Ultrasonic rangefinder is used to find range of an obstacle or a wall from the sensor. However, when there are cheap methods available to find range like the IR sensor or even a combination of LED’s and LDR would do but the question is why we use a more costly sensor. The reason is:-
  • IR sensors are not accurate
  • Result varies from object to object
  • Calibration is required
  • Works good only for shot range
Normally the IR sensors have a range from 30-80 cm or even less depending upon the manufacturer and also the LED’s used. However for an ultrasonic rangefinder, the distance can be measured accurately up to 400cm with an accuracy of 1cm.
HC-SR04 sensor
Ultrasonic rangefinders find application to measure level of a liquid, object sensing. Also, the great thing with this sensor is they required no calibration; no conversion from analog to digital data and the code are is not limited to any particular manufacturer sensor. The code will work pretty much with almost all sensors available in the market.
Another advantage of using ultrasonic sensor is that ultrasonic waves are narrower than infrared or any other sound beam. This is useful to detect objects that are exactly in line with the sensor.
In this tutorial, we will find the distance of any object. You should know how to use AVR timers. However as mentioned above you can use any other sensor but before buying just make sure that these sensors are microcontroller compatible.

The sensors I am using is a 4 pin sensor, one for Vcc, one for ground and the other two pins are echo and trigger However there are sensors, that have three pins, mainly Vcc, ground, and the third pin to connect to microcontroller. The working principle is pretty much the same, but it will have one input lines instead of two and also since the number of input line has changed, the coding will also changed, but the main logic will remain the same. If you want to interface these types of sensors, you may comment below and I will give you the required changes or the algorithm.

Program:
#include <avr/io.h>
#include <util/delay.h>
#include "lcd.h"
/********************************************************************
Configuration Area.
UltraSonic (US) sensor connection.
in this example it is connected to as follows
Sensor | MCU
_____________
Trig   | PC0
Echo   | PC1
********************************************************************/
#define US_PORT PORTC
#define US_PIN PINC
#define US_DDR DDRC
#define US_TRIG_POS PC0
#define US_ECHO_POS PC1
/********************************************************************
This function measures the width of high pulse in micro second.
********************************************************************/
#define US_ERROR -1
#define US_NO_OBSTACLE -2
void HCSR04Init();
void HCSR04Trigger();
void HCSR04Init()
{
US_DDR|=(1<<US_TRIG_POS);
}
void HCSR04Trigger()
{
//Send a 10uS pulse on trigger line
US_PORT|=(1<<US_TRIG_POS); //high
_delay_us(15); //wait 15uS
US_PORT&=~(1<<US_TRIG_POS); //low
}
uint16_t GetPulseWidth()
{
uint32_t i,result;
      //Wait for the rising edge
for(i=0;i<600000;i++)
{
if(!(US_PIN & (1<<US_ECHO_POS))) 
continue; //Line is still low, so wait
else 
                        break; //High edge detected, so break.
}
          if(i==600000)
return US_ERROR; //Indicates time out
  //High Edge Found
        //Setup Timer1
TCCR1A=0X00;
TCCR1B=(1<<CS11); //Prescaler = Fcpu/8
TCNT1=0x00; //Init counter
       //Now wait for the falling edge
for(i=0;i<600000;i++)
{
if(US_PIN & (1<<US_ECHO_POS))
{
if(TCNT1 > 60000) break; else continue;
}
else
break;
}

if(i==600000)
return US_NO_OBSTACLE; //Indicates time out
      //Falling edge found
       result=TCNT1;
       //Stop Timer
TCCR1B=0x00;
        if(result > 60000)
return US_NO_OBSTACLE; //No obstacle
else
return (result>>1);
}
int main()
{
uint16_t r;
_delay_ms(100); //Let the LCD Module start
       //Initialize the LCD Module
LCDInit(LS_NONE);
//Set io port direction of sensor
HCSR04Init();
        LCDClear();
LCDWriteString("Ultra Sonic");
LCDWriteStringXY(0,1,"Sensor Test");
        _delay_ms(2500);
LCDClear();
       while(1)
{
//Send a trigger pulse
HCSR04Trigger();
          //Measure the width of pulse
r=GetPulseWidth();
            //Handle Errors
if(r==US_ERROR)
{
LCDWriteStringXY(0,0,"Error !");
}
else if(r==US_NO_OBSTACLE)
{
LCDWriteStringXY(0,0,"Clear !");
}
else
{
                      int d;
                      d=(r/58.0); //Convert to cm
                      LCDWriteIntXY(0,0,d,4);
LCDWriteString(" cm");
                      _delay_ms(500);
}
}
   return 0;
}
Download : click here

No comments:

Post a Comment