Challenge

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

#include <avr/io.h>

#include <avr/interrupt.h>

#include <util/delay.h>

// Ultrasonic Sensor Pins

#define TRIG_PIN PD7

#define ECHO_PIN PB0 // ICP1 pin

#define SOUND_SPEED 34300 // cm/s

// LCD Connections (4-bit mode)

#define LCD_RS PD2

#define LCD_EN PD3

#define LCD_D4 PD4

#define LCD_D5 PD5

#define LCD_D6 PD6

#define LCD_D7 PD7

volatile uint16_t start_time = 0;

volatile uint16_t pulse_width = 0;

volatile uint8_t capture_flag = 0;

// Custom integer to string conversion

void int_to_str(uint16_t num, char* buffer) {

uint8_t i = 0;


// Handle zero case

if (num == 0) {

buffer[0] = '0';

buffer[1] = '\0';

return;

}


// Extract digits

while (num > 0) {

buffer[i++] = (num % 10) + '0';

num /= 10;

}

buffer[i] = '\0';

// Reverse the string

for (uint8_t j = 0; j < i/2; j++) {

char temp = buffer[j];

buffer[j] = buffer[i-j-1];

buffer[i-j-1] = temp;

}

}

// LCD Functions (unchanged from previous)

void lcd_command(uint8_t cmd) {

PORTD = (PORTD & 0x0F) | (cmd & 0xF0);

PORTD &= ~(1<<LCD_RS);

PORTD |= (1<<LCD_EN);

_delay_us(1);

PORTD &= ~(1<<LCD_EN);

_delay_us(100);

PORTD = (PORTD & 0x0F) | ((cmd << 4) & 0xF0);

PORTD |= (1<<LCD_EN);

_delay_us(1);

PORTD &= ~(1<<LCD_EN);

_delay_us(100);

}

void lcd_write(char data) {

PORTD = (PORTD & 0x0F) | (data &0xF0);

PORTD |= (1<<LCD_RS);

PORTD |= (1<<LCD_EN);

_delay_us(1);

PORTD &= ~(1<<LCD_EN);

_delay_us(100);

PORTD = (PORTD & 0x0F) | ((data << 4) & 0xF0);

PORTD |= (1<<LCD_EN);

_delay_us(1);

PORTD &= ~(1<<LCD_EN);

_delay_us(100);

}


void lcd_init() {

DDRD |= 0xFC; // Set PD2-PD7 as outputs

_delay_ms(50);

lcd_command(0x02); // 4-bit mode

lcd_command(0x28); // 2-line, 5x8 matrix

lcd_command(0x0C); // Display on, cursor off

lcd_command(0x06); // Increment cursor

lcd_command(0x01); // Clear display

_delay_ms(2);

}

void lcd_string(const char *str) {

while(*str) {

lcd_write(*str++);

}

}

// Modified display function using custom conversion

void lcd_display(uint16_t distance) {

char buffer[16];

lcd_command(0x80); // First line

lcd_string("Distance:");

lcd_command(0xC0); // Second line

int_to_str(distance, buffer);

lcd_string(buffer);

lcd_string(" cm ");

}

// Ultrasonic Functions (unchanged from previous)

void init_ultrasonic() {

DDRD |= (1<<TRIG_PIN);

DDRB &= ~(1<<ECHO_PIN);

TCCR1A = 0x00;

TCCR1B = (1<<ICES1) | (1<<CS11); // Rising edge, prescaler=8

TIMSK1 = (1<<ICIE1);

sei();

}

void trigger_pulse() {

PORTD |= (1<<TRIG_PIN);

_delay_us(10);

PORTD &= ~(1<<TRIG_PIN);

}

ISR(TIMER1_CAPT_vect) {

if (TCCR1B & (1<<ICES1)) {

start_time = ICR1;

TCCR1B &= ~(1<<ICES1);

} else {

pulse_width = ICR1 - start_time;

capture_flag = 1;

TCCR1B |= (1<<ICES1);

}

}

uint16_t calculate_distance() {

trigger_pulse();

while(!capture_flag);

capture_flag = 0;


// Distance in cm (timer at 1MHz with prescaler=8)

return (pulse_width * 8 * SOUND_SPEED) / (2 * 1000000UL);

}

int main() {

lcd_init();

init_ultrasonic();

// Display header

lcd_command(0x80);

lcd_string("Ultrasonic");

lcd_command(0xC0);

lcd_string("Range Finder");

_delay_ms(2000);

lcd_command(0x01); // Clear display

while(1) {

uint16_t distance = calculate_distance();

lcd_display(distance);

_delay_ms(200);

}

}

OUTPUT:

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.