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>

#define TRIGGER_PIN PD2

#define ECHO_PIN PD3

#define SOUND_SPEED 0.034 // Speed of sound in cm/µs

volatile uint16_t pulse_width = 0;

volatile uint8_t measurement_complete = 0;

void timer1_init(void) {

// Configure Timer1 for Input Capture

TCCR1A = 0; // Normal mode

TCCR1B = (1 << ICES1) | (1 << CS10); // Capture on rising edge, no prescaling

TIMSK = (1 << ICIE1); // Enable Input Capture Interrupt

}

void usart_init(uint16_t ubrr) {

// Set baud rate

UBRRH = (unsigned char)(ubrr >> 8);

UBRRL = (unsigned char)ubrr;

// Enable receiver and transmitter

UCSRB = (1 << RXEN) | (1 << TXEN);

// Set frame format: 8 data bits, 1 stop bit

UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);

}

void usart_transmit(unsigned char data) {

// Wait for empty transmit buffer

while (!(UCSRA & (1 << UDRE)));

// Put data into buffer, sends the data

UDR = data;

}

void trigger_ultrasonic(void) {

// Send a 10µs pulse to the trigger pin

PORTD |= (1 << TRIGGER_PIN);

_delay_us(10);

PORTD &= ~(1 << TRIGGER_PIN);

}

int main(void) {

// Initialize USART

usart_init(51); // 9600 baud rate for 8 MHz clock

// Set TRIGGER_PIN as output and ECHO_PIN as input

DDRD |= (1 << TRIGGER_PIN);

DDRD &= ~(1 << ECHO_PIN);

// Initialize Timer1

timer1_init();

// Enable global interrupts

sei();

while (1) {

if (measurement_complete) {

// Calculate distance

float distance = (pulse_width * SOUND_SPEED) / 2; // Distance = (Pulse width in µs * Speed of sound) / 2 (round trip)

// Convert distance to string and send via USART

char buffer[20];

snprintf(buffer, sizeof(buffer), "Distance: %.2f cm\r\n", distance);

for (char *ptr = buffer; *ptr; ptr++) {

usart_transmit(*ptr);

}

measurement_complete = 0; // Reset flag

}

// Trigger ultrasonic sensor every 1 second

trigger_ultrasonic();

_delay_ms(1000);

}

return 0;

}

// Input Capture Interrupt Service Routine

ISR(TIMER1_CAPT_vect) {

static uint16_t start_time = 0;

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

// Rising edge: Capture the time

start_time = ICR1;

TCCR1B &= ~(1 << ICES1); // Switch to capture on falling edge

} else {

// Falling edge: Capture the time and calculate pulse width

pulse_width = ICR1 - start_time;

TCCR1B |= (1 << ICES1); // Switch back to capture on rising edge

measurement_complete = 1; // Set measurement complete flag

}

}

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.