Project 2 - Measuring distance of an object using ultrasonic sensor (HC-SR04)
AIM:
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.
Calculation (distance in cm):
Sound velocity = 343.00 m/s = 34300 cm/s
The distance of Object (in cm) = Sound velocity *Timer/2
= 32300*Timer/2
= 17150*Timer
Now, here we have selected an internal 8 MHz oscillator frequency for ATmega16, with No-presale for timer frequency. Then time to execute 1 instruction is 0.125 us.
So, the timer gets incremented after 0.125 us time elapse.
= 17150 x (TIMER value) x 0.125 x 10^-6 cm
= 0.125 x (TIMER value)/58.30 cm
= (TIMER value) / 466.47 cm
CODE:
Without using Potentiometer:
#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>
#include <stdlib.h>
#define LCD_Data_Dir DDRD /* Define LCD data port direction */
#define LCD_Command_Dir DDRC /* Define LCD command port direction register */
#define LCD_Data_Port PORTD /* Define LCD data port */
#define LCD_Command_Port PORTC /* Define LCD data port */
#define EN PC2 /* Define Enable signal pin */
#define RW PC3 /* Define Read/Write signal pin */
#define RS PC4 /* Define Register Select (data reg./command reg.) signal pin */
void LCD_Command (char); /* LCD command write function */
void LCD_Char (char); /* LCD data write function */
void LCD_Init (void); /* LCD Initialize function */
void LCD_String (char*); /* Send string to LCD function */
void LCD_String_xy (char,char,char*); /* Send row, position and string to LCD function */
void LCD_Command (char cmd) /* LCD command write function */
{
LCD_Data_Port = cmd; /* Write command data to LCD data port */
LCD_Command_Port &= ~((1<<RS)|(1<<RW)); /* Make RS LOW (command reg.), RW LOW (Write) */
LCD_Command_Port |= (1<<EN); /* High to Low transition on EN (Enable) */
_delay_us(1);
LCD_Command_Port &= ~(1<<EN);
_delay_ms(3); /* Wait little bit */
}
void LCD_Char (char char_data) /* LCD data write function */
{
LCD_Data_Port = char_data; /* Write data to LCD data port */
LCD_Command_Port &= ~(1<<RW); /* Make RW LOW (Write) */
LCD_Command_Port |= (1<<EN)|(1<<RS); /* Make RS HIGH (data reg.) and High to Low transition on EN (Enable) */
_delay_us(1);
LCD_Command_Port &= ~(1<<EN);
_delay_ms(1); /* Wait little bit */
}
void LCD_Init (void) /* LCD Initialize function */
{
LCD_Command_Dir |= (1<<RS)|(1<<RW)|(1<<EN); /* Make LCD command port direction as o/p */
LCD_Data_Dir = 0xFF; /* Make LCD data port direction as o/p */
_delay_ms(20); /* LCD power up time to get things ready, it should always >15ms */
LCD_Command (0x38); /* Initialize 16X2 LCD in 8bit mode */
LCD_Command (0x0C); /* Display ON, Cursor OFF command */
LCD_Command (0x06); /* Auto Increment cursor */
LCD_Command (0x01); /* Clear LCD command */
LCD_Command (0x80); /* 8 is for first line and 0 is for 0th position */
}
void LCD_String (char *str) /* Send string to LCD function */
{
int i;
for(i=0;str[i]!=0;i++) /* Send each char of string till the NULL */
{
LCD_Char (str[i]); /* Call LCD data write */
}
}
void LCD_String_xy (char row, char pos, char *str) /* Send string to LCD function */
{
if (row == 1)
LCD_Command((pos & 0x0F)|0x80); /* Command of first row and required position<16 */
else if (row == 2)
LCD_Command((pos & 0x0F)|0xC0); /* Command of Second row and required position<16 */
LCD_String(str); /* Call LCD string function */
}
#define Trigger_pin PA0 /* Trigger pin */
int TimerOverflow = 0;
ISR(TIMER1_OVF_vect)
{
TimerOverflow++; /* Increment Timer Overflow count */
}
int main(void)
{
char string[10];
long count;
double distance;
DDRA = 0x01; /* Make trigger pin as output */
PORTB = 0xFF; /* Turn on Pull-up */
LCD_Init();
LCD_String_xy(1, 0, "Ultrasonic");
sei(); /* Enable global interrupt */
TIMSK = (1 << TOIE1); /* Enable Timer1 overflow interrupts */
TCCR1A = 0; /* Set all bit to zero Normal operation */
while(1)
{
/* Give 10us trigger pulse on trig. pin to HC-SR04 */
PORTA |= (1 << Trigger_pin);
_delay_us(10);
PORTA &= (~(1 << Trigger_pin));
TCNT1 = 0; /* Clear Timer counter */
TCCR1B = 0x41; /* Capture on rising edge, No prescaler*/
TIFR = 1<<ICF1; /* Clear ICP flag (Input Capture flag) */
TIFR = 1<<TOV1; /* Clear Timer Overflow flag */
/*Calculate width of Echo by Input Capture (ICP) */
while ((TIFR & (1 << ICF1)) == 0);/* Wait for rising edge */
TCNT1 = 0; /* Clear Timer counter */
TCCR1B = 0x01; /* Capture on falling edge, No prescaler */
TIFR = 1<<ICF1; /* Clear ICP flag (Input Capture flag) */
TIFR = 1<<TOV1; /* Clear Timer Overflow flag */
TimerOverflow = 0;/* Clear Timer overflow count */
while ((TIFR & (1 << ICF1)) == 0);/* Wait for falling edge */
count = ICR1 + (65535 * TimerOverflow); /* Take count */
/* 8MHz Timer freq, sound speed =343 m/s */
distance = (double)count / 466.47;
dtostrf(distance, 2, 2, string);/* distance to string */
strcat(string, " cm "); /* Concat unit i.e.cm */
LCD_String_xy(2, 0, "Dist = ");
LCD_String_xy(2, 7, string); /* Print distance */
_delay_ms(200);
}
}
With Potentiometer:
#define F_CPU 8000000L
#define rs_high PORTA |=(1<<6)//enabling lcd register high
#define rs_low PORTA &=~(1<<6)//enabling lcd register low
#define en_high PORTA |=(1<<7)//enabling lcd enable high
#define en_low PORTA &=~(1<<7)//enabling lcd enable low
#include <avr/io.h> // This header file includes the appropriate Input/output definitions for the device
#include <util/delay.h> // to use delay function we need to include this library
#include <avr/interrupt.h>
#include <stdlib.h> // we'll be using itoa() function to convert integer to character array that resides in this library
#define Trigger_pin PB1
void lcd_cmd(unsigned char cmd)
{
PORTC = cmd;//giving cmd to the LCD
rs_low;//making register low
en_high;//making enable high
_delay_ms(1);
en_low;//making enable low
}
void lcd_data(unsigned char data)
{
PORTC = data;//giving data to the LCD
rs_high;//making register high
en_high;//making enable high
_delay_ms(1);
en_low;//making enable low
}
void lcd_init()
{
//Making lcd ready for displaying the output//
lcd_cmd(0x38);
_delay_ms(5);
lcd_cmd(0x02);
_delay_ms(5);
lcd_cmd(0x01);
_delay_ms(5);
lcd_cmd(0x0c);
_delay_ms(5);
lcd_cmd(0x06);
_delay_ms(5);
lcd_cmd(0x80);
_delay_ms(5);
}
void cursorpos(char x,char y)
{
if((x<1 || x>2)||(y<1 || y>16))//condtion check the 2 rows and 16 columns
{
x=1;
y=1;
}
if (x==1)
{
lcd_cmd(0x7F+y);//{80-1=7f} for starting the 1st line hex decimal value(80) y we r using means we need to dtart from that column
}
else
{
lcd_cmd(0xBF+y);//0c-1=0b for starting 2nd line,2nd row
}
}
void lcd_out(char a, char b,char *str)
{
cursorpos(a,b);//checking the cursor position or setting the position
while(*str)
{
lcd_data(*str);//sending the data to lcd function with string as argument
str++;
}
}
int Timeroverflow=0;
ISR(TIMER1_OVF_vect)
{
Timeroverflow++;/* Increment Timer Overflow count */
}
int main()
{
char dist[10];
long count;
double dis;
DDRB |=0b00000010; /* Make trigger pin as output */
DDRD&=~(1<<6);
PORTD |=(0b010000000);
DDRC |=0xFF;/* Make trigger pin as output */
DDRA |=0xFF;/* Make trigger pin as output */
lcd_init();
lcd_out(1,1,"Ultrasonic");
sei();/* Enable global interrupt */
TIMSK=(1<<TOIE1);/* Enable Timer1 overflow interrupts */
TCCR1A=0;/* Set all bit to zero Normal operation */
while(1)
{
/* Give 10us trigger pulse on trig. pin to HC-SR04 */
PORTB |=(1<<Trigger_pin);
_delay_ms(10);
PORTB &=(~(1<<Trigger_pin));
TCNT1=0;/* Clear Timer counter */
TCCR1B=0x41;/* Capture on rising edge, No prescaler*/
TIFR=(1<<ICF1);/* Clear ICP flag (Input Capture flag) */
TIFR=(1<<TOV1); //Clear Timer Overflow flag */
/*Calculate width of Echo by Input Capture (ICP) */
while ((TIFR &(1<<ICF1))==0);/* Wait for rising edge */
TCNT1=0; /*Clear Timer counter */
TCCR1B=0X01;/* Capture on falling edge, No prescaler */
TIFR=(1<<ICF1);/* Clear ICP flag (Input Capture flag) */
TIFR=(1<<TOV1);/* Clear Timer Overflow flag */
Timeroverflow=0;/* Clear Timer overflow count */
while ((TIFR & (1 << ICF1))==0);/* Wait for falling edge */
count = ICR1 + (65535 * Timeroverflow); /* Take count */
/* 8MHz Timer freq, sound speed =343 m/s */
dis = (double)count / 466.47;
itoa(dis,dist,4);
lcd_out(2,1,dist);
lcd_out(2,5,"CM");
_delay_ms(10);
}
}