Skip to content

Non-blocking driver written in C for the proximity Ultrasonic Sensor HC-SR04 specifically the ATmega328P used on the Arduino Uno

License

Notifications You must be signed in to change notification settings

MatGonPer/avr-ultrasonic-sensor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Non-Blocking AVR Driver for HC-SR04 Ultrasonic Sensor

A lightweight, bare-metal (AVR-C) driver for the HC-SR04 ultrasonic distance sensor, designed for AVR microcontrollers (e.g., ATmega328P on the Arduino Uno).

The key feature of this driver is its non-blocking, interrupt-driven design. It uses the Timer1 Input Capture unit (ICP1) to measure the echo pulse duration in hardware. This allows the main CPU loop to run freely without being frozen by _delay_ loops or while() polling, making it ideal for RTOS projects or concurrent task management.


## Hardware Setup

This driver is not pin-agnostic. To achieve non-blocking operation, it relies on the Timer1 Input Capture hardware, which is physically tied to a specific pin.

  • HC-SR04 VCCArduino 5V
  • HC-SR04 GNDArduino GND
  • HC-SR04 TrigArduino Pin 9 (PB1)
  • HC-SR04 EchoArduino Pin 8 (PB0 / ICP1)

Warning: The Echo pin connection to Pin 8 (ICP1) is mandatory for the hardware interrupt to function. The Trig pin can be changed by modifying the TRIGGER_PIN macro in ultrasonic.c.


## Prerequisites & Installation

To build and run the example, you need the AVR toolchain (compiler and uploader) and a serial monitor.

On Arch Linux

  1. Install the Toolchain:

    sudo pacman -S avr-gcc avr-libc avrdude make
  2. Install Serial Monitor:

    sudo pacman -S picocom
  3. Grant Serial Port Permissions: You must add your user to the group that owns the USB device. This is typically uucp on Arch/Manjaro or dialout on Debian/Ubuntu.

    # Use 'uucp' for Manjaro/Arch
    sudo usermod -aG uucp $USER
    # Or 'dialout' for Debian/Ubuntu
    # sudo usermod -aG dialout $USER

    You must log out and log back in for this change to take effect.

On Windows

  1. Install the Toolchain:

    • Download and install the Microchip AVR 8-bit Toolchain (which contains avr-gcc, avr-libc, etc.) from the Microchip website.
    • Add the toolchain's bin directory to your system's PATH environment variable.
  2. Install Make & Avrdude: The easiest way is via a package manager like Chocolatey.

    # Install make
    choco install make
    # Install avrdude
    choco install avrdude
  3. Find your COM Port:

    • Plug in your Arduino.
    • Open Device Manager.
    • Look under Ports (COM & LPT).
    • Note your Arduino's port (e.g., COM3, COM4).

## How to Build and Test

The included example (examples/SimpleTest) sends the measured distance (in cm) over the serial (UART) connection.

1. Build the Project

# 1. Clone this repository
git clone https://github.com/MatGonPer/avr-ultrasonic-sensor.git
cd avr-ultrasonic-driver

# 2. Navigate to the example directory
cd examples/SimpleTest

(Windows Only): Before building, you must edit the Makefile in this directory:

  • Open examples/SimpleTest/Makefile.
  • Change the PORT variable from /dev/ttyACM0 to your COM port.
    • From: PORT = /dev/ttyACM0
    • To: PORT = COM3 (or your port number)

Now, build the firmware:

make

This will compile main.c and link it with the driver source from ../../src/ultrasonic.c.

2. Upload the Firmware

With your Arduino still connected, run:

make upload

This will flash the compiled main.hex file to the ATmega328P.

3. View the Output

The Arduino is now running and sending data at 9600 baud.

  • On Linux:

    picocom -b 9600 /dev/ttyACM0
    # To exit: Ctrl+A, then Ctrl+X
  • On Windows: Use any serial monitor program (like PuTTY, Tera Term, or the Arduino IDE's Serial Monitor).

    • Connect to your COM3 (or other) port.
    • Set the baud rate to 9600.

You should see the following output in your terminal, with the distance updating in real-time:

Non-blocking HC-SR04 driver - Test
Distance: 55 cm
Distance: 56 cm
...

## API Overview

To use this driver in your own project, copy the src/ directory and include ultrasonic.h.

#include "ultrasonic.h"

void ultrasonic_init(void);

Initializes the driver. Configures all necessary hardware (pins, Timer1, Input Capture, and interrupts). Must be called once at startup.

void ultrasonic_trigger(void);

Triggers a new measurement. This function is non-blocking and returns immediately. The measurement is then performed by the hardware in the background.

uint8_t ultrasonic_is_ready(void);

Polls the driver to check if a new measurement is complete.

  • Returns: 1 (true) if a new echo has been received.
  • Returns: 0 (false) if the driver is still waiting.

uint16_t ultrasonic_get_distance_cm(void);

Fetches the last measured distance. This function also resets the is_ready flag, indicating the data has been "consumed".

  • Returns: The measured distance in centimeters.

About

Non-blocking driver written in C for the proximity Ultrasonic Sensor HC-SR04 specifically the ATmega328P used on the Arduino Uno

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages