Project 2 - Measuring distance of an object using ultrasonic sensor (HC-SR04)
Overview of the Project:
In this project, the implementation of code for “Measuring distance of an object using ultrasonic distance sensor (HC-SR04)
Goals:
- Measuring the distance of an object using Ultrasonic Distance Sensor (HC-SR04)
- Usage of Input Capture Mode
Key Highlights of the Project:
- Measuring the distance travelled by the wave to the object and gets bounced back from the object to sensor.
- Measuring Pulse width using Input Capture Mode
Deliverables of this project:
- The distance travelled by a wave to the object for which we want to measure the distance using Ultrasonic Distance Sensor (HC-SR04).
- Measuring Pulse width using Input Capture Mode of Timer 1
Expected Outcomes:
The students will get the Knowledge on Ultrasonic sensor (HC-SR04) to measure the distance travelled by wave to the object, the hardware connection of Atmega328p and HC-SR04 and how to use input capture mode of Timer1
Working Principal


We are going to use PB0 (Input Capture Pin1) for the echo terminal of the HC_SR04 Ultrasonic sensor. As ICP1 will be used for Timer 1 interrupt so when the echo pin will be in the falling edge then an interrupt will be generated.
/////////////////////////////// Code //////////////////////////////
#include <avr/io.h> // avr library
#define F_CPU 16000000
#include <util/delay.h> // for using delay functions
#include "avr/interrupt.h" // include interrupt library for using global interrupts
#define ECHO 0 //Input, It is a ICP1 PIN (Input Capture Pin)
#define TRIG 3 // Output
#define rs_high() PORTB |=(1<<7); // reset pin of lcd
#define rs_low() PORTB &= ~(1<<7);
#define en_high() PORTB |= (1<<6); // enable pin of lcd
#define en_low() PORTB &= ~(1<<6);
#define lcdport PORTD // deffining port for writting data
// below are various functions declaration for lcd operation
void lcd_command(unsigned char cmd);
void lcd_data(unsigned char data);
void lcd_init();
void cursorpos(char x, char y);
void lcd_print(char row, char column, unsigned int value, int digits);
void lcd_out(char x, char y, char *str);
long count;
int main(void)
{
int distance= 0;
DDRB |= (1<<TRIG); // CONFIGURED AS OUTPUT
DDRB &= ~(1<<ECHO); // CONFIGURED AS INPUT
lcd_init(); // initializing the lcd.
sei(); // Enable global interrupt
TIMSK1 |= (1<<ICIE1); // Enable required Timer1 interrupt
TCCR1A = 0x00;
TCCR1B &= ~(1<<ICES1); // Falling Edge Capture
while (1)
{
PORTB &= ~(1<<TRIG); // off
_delay_us(2);
PORTB |= (1<<TRIG); // turn on Trigger to generate pulse
_delay_us(10); // keep the trigger "ON" for 10 micro seconds
PORTB &= ~(1<<TRIG); // Turn off trigger to stop pulse
// If pulse reached the receiver echoPin
// become high Then ultrasonic_time() returns the
// time taken by the pulse to reach the receiver
TCCR1B |= (1<<1); // Timer 1 in normal mode, 8 prescalar
// 16 MHz/8 = 2MHz => T= 0.5 microseconds.
TCNT1 = 0; // timmer counter start
// total time = counts * 0.5 micro second (Time_period) = count/2
// d = (total_time/2) * speed ==> distance = (count *speed)/4
distance = (count * 0.0344)/4;
lcd_out(1,3,"Dis = "); // for string printing in row 1
lcd_print(1,9,distance,3); // for digit print in row 1
lcd_out(1,12,"cm"); // for string printing in row 1
lcd_out(2,1,"ICRvalue= "); // for string printing in row 2
lcd_print(2,11,count,5); // for digit print in row 2
_delay_ms(250); // for stable operation
}
}
// Implement ISR Function
ISR (TIMER1_CAPT_vect)
{
count = ICR1; // transfer input capture register value to variable count
TCCR1B &= ~(1<<1); // Stop Timer1
}
///////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
/////////////////////////////// Functions for LCD ////////////////////////
void lcd_command(unsigned char cmd)
{
// function for giving predefined commands to lcd
lcdport = cmd;
rs_low();
en_high();
_delay_ms(1); // delay
en_low();
}
void lcd_data(unsigned char data)
{
// function for giving data to lcd in form of ASCI value
lcdport = data;
rs_high();
en_high();
_delay_ms(1);
en_low();
}
void lcd_init()
{
// using lcd function previously made for initialization purpose
lcd_command(0x38);_delay_ms(500);
lcd_command(0x02);_delay_ms(500);
lcd_command(0x01);_delay_ms(5);
lcd_command(0x0c);_delay_ms(5);
lcd_command(0x06);_delay_ms(5);
lcd_command(0x80);_delay_ms(5);
}
void cursorpos(char x, char y)
{
// set cursor of lcd to desired location
if( (x < 1 || x > 2) || (y < 1 || y > 16) )
{
x = 1;
y = 1;
}
if(x == 1)
lcd_command(0x80+y);
else
lcd_command(0xC0+y);
}
void lcd_print(char row, char coloumn, unsigned int value, int digits)
{
// printing integer values of sensor and variables
unsigned int temp;
unsigned int unit;
unsigned int tens;
unsigned int hundred;
unsigned int thousand;
unsigned int million;
unsigned char flag=0;
if(row==0||coloumn==0)
{
cursorpos(1,1);
}
else
{
cursorpos(row,coloumn);
}
if(digits==5|| flag==1)
{
// adding 48 last to make itEquivalent to ASCI decimal value of digits.
million=value/10000+48;
lcd_data(million);
flag=1;
}
if(digits==4 || flag==1)
{
// flag is used for ladder logic implementation
temp = value/1000;
thousand = temp%10 +48;
lcd_data(thousand);
flag=1;
}
if(digits==3 || flag==1)
{
// for 3rd digit number
temp = value/100;
hundred = temp%10 +48;
lcd_data(hundred);
flag=1;
}
if(digits==2 || flag==1)
{
// for 2nd digit number
temp = value/10;
tens= temp%10 +48;
lcd_data(tens);
flag=1;
}
if(digits==1 || flag==1)
{
// for 1st digit number
unit = value%10 + 48;
lcd_data(unit);
}
if(digits>5)
{// print error if digits are more then 5
lcd_data('e');
}
}
void lcd_out(char x,char y,char *str)
{
// for printing string on lcd screen
cursorpos(x,y);
while(*str)
{
lcd_data(*str);
str++;
}
}
