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:
