Project 2 - Measuring distance of an object using ultrasonic sensor (HC-SR04)
CHALLENGE 10 : PROJECT 2
Project 2 - Measuring distance of an object using ultrasonic sensor (HC-SR04)
Overview of the Project:
In this project, the implementation of code for “Measuring distance of an object using ultrasonic distance sensor (HC-SR04)
Program:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define TRIGGER_PIN PB0
#define ECHO_PIN PB1
volatile uint8_t timerOverflow = 0;
volatile uint32_t pulseWidth = 0;
void init()
{
// Set trigger pin as output
DDRB |= (1 << TRIGGER_PIN);
// Set echo pin as input
DDRB &= ~(1 << ECHO_PIN);
// Set Timer1 in Normal Mode with prescaler = 8
TCCR1B |= (1 << CS11);
// Enable Input Capture Interrupt
TIMSK1 |= (1 << ICIE1);
// Enable global interrupts
sei();
}
void triggerPulse()
{
// Generate a 10us pulse on trigger pin
PORTB |= (1 << TRIGGER_PIN);
_delay_us(10);
PORTB &= ~(1 << TRIGGER_PIN);
}
int main()
{
// Initialize
init();
while (1)
{
// Send a trigger pulse
triggerPulse();
// Wait for the echo pin to go high
while (!(PINB & (1 << ECHO_PIN)));
// Start Timer1
TCNT1 = 0;
TCCR1B |= (1 << ICES1);
// Wait for the echo pin to go low
while (PINB & (1 << ECHO_PIN));
// Stop Timer1
TCCR1B &= ~(1 << ICES1);
// Calculate the pulse width in microseconds
pulseWidth = (timerOverflow * 65536 + ICR1) / 2;
// Calculate the distance in centimeters
uint32_t distance = pulseWidth * 0.034 / 2;
// Print the distance
printf("Distance: %d cm\n", distance);
// Delay before taking the next measurement
_delay_ms(500);
}
return 0;
}
ISR(TIMER1_CAPT_vect)
{
// Increment timer overflow count if needed
if (TIFR1 & (1 << TOV1))
{
timerOverflow++;
TIFR1 |= (1 << TOV1);
}
}

Output:
Distance: 25 cm
Distance: 30 cm
Distance: 15 cm
...

Description of the program:
- The program starts by including the necessary libraries and defining the pin configurations for the trigger and echo pins of the ultrasonic sensor.
- Global variables `timerOverflow` and `pulseWidth` are declared. `timerOverflow` is used to track the number of Timer1 overflows, and `pulseWidth` stores the measured pulse width.
- The `init()` function is called to initialize the necessary configurations for the program. It sets the trigger pin as an output and the echo pin as an input. Timer1 is set in Normal Mode with a prescaler of 8, and the input capture interrupt is enabled. Global interrupts are also enabled.
- The `triggerPulse()` function generates a 10μs pulse on the trigger pin. It sets the trigger pin high for 10μs and then sets it low again. This pulse triggers the ultrasonic sensor to start measuring.
- Inside the main loop, the program waits for the echo pin to go high, indicating the start of the echo pulse. It continuously checks the echo pin until it becomes high.
- Once the echo pin goes high, Timer1 is started. The Timer1 value is reset to 0 (`TCNT1 = 0`), and the input capture edge select (`ICES1`) is set to capture the rising edge of the echo pulse (`TCCR1B |= (1 << ICES1)`).
- The program then waits for the echo pin to go low, indicating the end of the echo pulse. It continuously checks the echo pin until it becomes low.
- Once the echo pin goes low, Timer1 is stopped by clearing the input capture edge select (`TCCR1B &= ~(1 << ICES1)`).
- The pulse width is calculated using the Timer1 overflow count (`timerOverflow`) and the value stored in the input capture register (`ICR1`). If Timer1 overflows during the pulse, the overflow count is incremented accordingly. The pulse width is calculated as `(timerOverflow * 65536 + ICR1) / 2`.
- The pulse width is converted to a distance value in centimeters using the formula `distance = pulseWidth * 0.034 / 2`. The value 0.034 is derived from the speed of sound (approximately 343 meters per second) divided by 10,000 to convert it to centimeters per microsecond.
- The calculated distance is printed to the console using `printf()`.
- After printing the distance, the program delays for 500 milliseconds using `_delay_ms(500)` before taking the next measurement.
- The program continues looping, repeating the process of triggering the ultrasonic pulse, measuring the pulse width, calculating the distance, and printing it to the console.
- The program runs indefinitely until manually terminated.
In summary, the program continuously measures the distance of an object using an ultrasonic distance sensor. It triggers the sensor by sending a 10μs pulse, measures the pulse width using Timer1 in input capture mode, calculates the distance based on the pulse width, and prints the distance to the console. The process repeats at regular intervals to provide continuous distance measurements.