Challenge

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

/*

* Ultrasonic_32.c

*

* Created: 25-02-2024 15:58:49

* Author : Vishnu V Nair

*/

#include <avr/io.h>

#define F_CPU 8000000UL

#include <util/delay.h>

#include <avr/interrupt.h>

#include <string.h>

#include <stdlib.h>

#define EN 6

#define RS 5

#define RW 4

int Timer_Overflow = 0;

//Function for LCD command

void lcd_cmd(unsigned char cmd)

{

PORTC = cmd;

PORTB &= ~(1<<RS) | (1<<RW);

PORTB &= ~(1<<EN);

_delay_ms(100);

PORTB |= (1<<EN);

}

//Function for LCD command

void lcd_data(unsigned char data)

{

PORTC = data;

PORTB |= (1<<RS);

PORTB &= ~(1<<EN);

_delay_ms(100);

PORTB |= (1<<EN);

}

//Function to display string in LCD

void lcd_display(char x,char y, unsigned char *s)

{

cursor_pos(x,y); //To set cursor position

for(int i = 0; s[i] != 0; i++)

{

lcd_data(s[i]); //Sending each char to display 1 by 1

}

}

//Function to set cursor position

void cursor_pos(char row, char coloumn)

{

//Checking the position are in valid LCD range(16*2)

if( (row < 1 || row > 2) || (coloumn < 1 || coloumn > 16) )

{

row = 1;

coloumn = 1;

}

//If cursor position in the first row

if(row == 1)

{

lcd_cmd(0x80 + coloumn); //In the beginning of first line with coloumn position

}

else //If not cursor position in the beginning of 2nd line

{

lcd_cmd(0xC0 + coloumn); //beginning of 2nd line with coloumn position

}

}

//To initialize LCD

void lcd_init()

{

lcd_cmd(0x38); //2 line & 5*7 matrix

lcd_cmd(0x02); //Return home

lcd_cmd(0x01); //Clear display screen

lcd_cmd(0x0c); //Display ON, cursor OFF

lcd_cmd(0x06); //Increment cursor to right

lcd_cmd(0x80); //Force cursor to the begenning of first line

}

//Function to print LCD data

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

{

unsigned int temp;

unsigned int ones;

unsigned int tens;

unsigned int hundred;

unsigned int thousand;

unsigned int million;

unsigned char flag=0;

//if the Row & coloumn is 0 set cursor position to(1,1)

if(row == 0 || coloumn == 0)

{

cursor_pos(1,1);

}

else //Else set to the desired position

{

cursor_pos(row,coloumn);

}

//If the value digit is in 5th position display million th place

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

{

million=value/10000+48; //Convert to ASII

lcd_data(million);

flag=1;

}

//If the value digit is in 4th position display thousand th place

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

{

temp = value/1000; //Extact 1000th value

thousand = temp%10 +48; //Convert to ASII

lcd_data(thousand);

flag=1;

}

//If the value digit is in 3rd position display hundred th place

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

{

temp = value/100; //Extact 100th value

hundred = temp%10 +48; //Convert to ASII

lcd_data(hundred);

flag=1;

}

//If the value digit is in 2nd position display ten th place

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

{

temp = value/10; //Extact 10th value

tens= temp%10 +48; //Convert to ASII

lcd_data(tens);

flag=1;

}

//If the value digit is in 1st position display one's place

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

{

ones = value%10 + 48; //Extact 1's value

lcd_data(ones);

}

//if value exceeds 5th value indicate over flow

if(digits>5)

{

lcd_data('e');

}

}

//Interrupt for timer over flow

ISR(TIMER1_OVF_vect)

{

Timer_Overflow++; //Incrementing overflow counter

}

int main(void)

{

char dis[10];

long count; //Variable to store timer count

double distance; //Variable to store distance

//Sensor part

DDRA |= (1<<PA0); //Trigger pin as o/p

DDRD |= 0x00; //Echo pin (turning on pull-up)

PORTD |= 0xff;

//LCD part

DDRC |= 0xff; //LCD data pin

DDRB |= (1<<RS) | (1<<EN); //RS & EN pin

DDRA = 0x01; /* Make trigger pin as output */

PORTD = 0xFF; /* Turn on Pull-up */

DDRB = 0xff; //Set the data direction register DDRB as output

DDRD |=(1<<0); //Set the Data direction Register port d pin 0as output

DDRD |=(1<<1); //Set the Data direction Register port d pin 1as output

lcd_init(); //Initialize LCD

lcd_display(1,0,"Distance:");

sei(); //Enable global interrupt

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

TCCR1A = 0; //Normal mode

while(1)

{

//Triggering sensor for 10us

PORTA |= (1<< PA0); //Triggering sensor

_delay_ms(10);

PORTA &= ~(1<< PA0); //Clearing trig pin

TCNT1 = 0; //Timer reset

TCCR1B = 0x41; //Input Capture and no prescaler(ICES1 & CS10)

TIFR = 1<<ICF1; //Clearing input capture flag

TIFR = 1<<TOV1; //Clearing timer overflow flag

//Calculating Echo

while ((TIFR & (1<<ICF1)) == 0); //Wait for the rising edge echo pulse

TCNT1 = 0; //Timer reset

TCCR1B = 0x01; //No prescaler

TIFR = 1<<ICF1; //Clearing input capture flag

TIFR = 1<<TOV1; //Clearing timer overflow flag

Timer_Overflow = 0; //Resetting overflow count

while ((TIFR & (1<< ICF1))== 0); //Waiting for falling edge of echo pulse

//Calculating distance

count = ICR1 +(65535 * Timer_Overflow);

distance = (double)count/466.47;

//Converting decimal to string

lcd_print(2,0,distance,4);

}

}

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.