Challenge

Project 2 - Measuring distance of an object using ultrasonic sensor (HC-SR04)

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

Solution:

#include <avr/io.h> //Include AVR I/O library

#define F_CPU 16000000UL // Define the CPU frequency for delay functions

#include <util/delay.h> //Include delay library for _delay_ms

#include <avr/interrupt.h> //Include interrupt library for interrupt handling

#include <string.h> //Include string manipulation functions

#include <stdlib.h> //Include standard library functions

#define en_high PORTC |= (1 << 2) //Set the Enable (EN) pin of the LCD to high

#define en_low PORTC &= ~(1 << 2) //Set the Enable (EN) pin of the LCD to low

#define rw_high PORTC |= (1 << 3) //Set the Read/Write (RW) pin of the LCD to high

#define rw_low PORTC &= ~(1 << 3) //Set the Read/Write (RW) pin of the LCD to low

#define rs_high PORTC |= (1 << 4) //Set the Register Select (RS) pin of the LCD to high

#define rs_low PORTC &= ~(1 << 4) //Set the Register Select (RS) pin of the LCD to low

#define lcdport PORTD //Define the data port for the LCD as PORTD

#define trigger_pin 0 //Define the trigger pin for the ultrasonic sensor as pin 0

#define echo_pin 1 //Define the echo pin for the ultrasonic sensor as pin 1

int TimerOverFlow = 0; //Initialize a variable to keep track of timer overflows

void lcd_cmd(unsigned char cmd)

{

lcdport = cmd; //Function to send a command to the LCD

rs_low; //Set Register Select (RS) to command mode

rw_low; //Set Read/Write (RW) to write mode

en_high; //Enable the LCD

_delay_ms(1); //Delay for a short time

en_low; //Disable the LCD

}

void lcd_data(unsigned char data)

{

lcdport = data; //Function to send data to the LCD

rs_high; //Set RS to data mode

rw_low; //Set RW to write mode

en_high; //Enable the LCD

_delay_ms(1); //Delay for a short time

en_low; //Disable the LCD

}

void lcd_init()

{

// Function to initialize the LCD

lcd_cmd(0x38); //Initialize the LCD: 2 lines, 5x7 matrix.

_delay_ms(5);

lcd_cmd(0x02); //Return to the home position.

_delay_ms(5);

lcd_cmd(0x01); //Clear the screen.

_delay_ms(5);

lcd_cmd(0x0c); //Display on, cursor off.

_delay_ms(5);

lcd_cmd(0x06); //Increment cursor.

_delay_ms(5);

lcd_cmd(0x80); //Set the cursor to start from the 1st line.

_delay_ms(5);

}

void cursorpos(char x, char y)

{

if ((x < 1 || x > 2) || (y < 1 || y > 16)) {

x = 1;

y = 1;

}

if (x == 1) {

lcd_cmd(0x80 + y); //Set the cursor to start from the 1st row

} else {

lcd_cmd(0xc0 + y); //Set the cursor to start from the 2nd row

}

}

void lcd_out(char a, char b, char *str)

{

cursorpos(a, b); //Set the cursor position.

while (*str) {

lcd_data(*str); //Send characters one by one to the LCD.

str++;

}

}

void lcd_print(char row, char column, unsigned int value, int digits)

{

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 || column == 0)

{

cursorpos(1, 1);

}

else

{

cursorpos(row, column);

}

if (digits == 5 || flag == 1)

{

million = value / 10000 + 48;

lcd_data(million);

flag = 1;

}

if (digits == 4 || flag == 1)

{

temp = value / 1000;

thousand = temp % 10 + 48;

lcd_data(thousand);

flag = 1;

}

if (digits == 3 || flag == 1)

{

temp = value / 100;

hundred = temp % 10 + 48;

lcd_data(hundred);

flag = 1;

}

if (digits == 2 || flag == 1)

{

temp = value / 10;

tens = temp % 10 + 48;

lcd_data(tens);

flag = 1;

}

if (digits == 1 || flag == 1)

{

unit = value % 10 + 48;

lcd_data(unit);

}

if (digits > 5)

{

lcd_data('e');

}

}

ISR(TIMER1_OVF_vect)

{

TimerOverFlow++; //This interrupt service routine (ISR) increments the TimerOverFlow variable when a Timer1 overflow interrupt occurs

}

//Main function

int main(void)

{

//Declare variables

char string[10];

long count;

double distance;

DDRD = 0xff; //Set all pins on Port D as outputs.

DDRC |= (1 << 2); //Set Pin 2 on Port C as an output.

DDRC |= (1 << 3); //Set Pin 3 on Port C as an output.

DDRC |= (1 << 4); //Set Pin 4 on Port C as an output.

DDRA |= (1 << trigger_pin); //Set Pin 0 on Port A as an trigger pin

DDRA |= (1 << echo_pin); //Set Pin 1 on Port A as an echo pin

lcd_init(); //Initialize the LCD.

sei(); //Enable global interrupts.

TIMSK = (1 << TOIE1); //Enable Timer1 overflow interrupt.

TCCR1A = 0; //Configure Timer1 Control Register A.

while (1)

{

PORTA |= (1 << trigger_pin); //Set echo pin Pin to HIGH.

_delay_ms(10); //Delay for 10 milliseconds

PORTA &= ~(1 << trigger_pin); //set trigger pin to LOW

_delay_ms(10); //Delay for 10 milliseconds

PORTA |= (1 << echo_pin); //Set echo pin to HIGH

_delay_ms(10); //Delay for 10 milliseconds

PORTA &= ~(1 << echo_pin); //set echo pin to LOW

_delay_ms(10); //Delay for 10 milliseconds.

while ((TIFR & (1 << ICF1)) == 0); //Wait for Input Capture Flag to be set

TCNT1 = 0; //Reset the Timer1 counter

TCCR1B = 0x41; //Configure Timer1 Control Register B

TIFR = 1 << ICF1; //Clear the Input Capture Flag

TIFR = 1 << TOV1; //Clear the Timer1 overflow flag

TimerOverFlow = 0; //Reset the TimerOverFlow variable

while ((TIFR & (1 << ICF1)) == 0); //Wait for Input Capture Flag to be set again.

count = ICR1 + (65535UL * TimerOverFlow); //Calculate the count based on Input Capture and Timer overflow

distance = (double)count / 466.47; // Calculate the distance based on the count

lcd_out(1, 1, "ultrasonic"); // Display "ultrasonic" on the LCD

lcd_print(2, 6, distance ,4); // Display the distance on the LCD with 4 decimal places

lcd_out(2, 1, "dist= "); // Display "dist= " on the LCD

lcd_out(2, 12, "cm"); // Display "cm" on the LCD

_delay_ms(1000); // Delay for 1000 milliseconds

}

}

Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.