The proposed system is an intelligent parking assistant designed to monitor the rear of a vehicle using three reference points. The goal of the project is to prevent collisions by providing real-time visual, auditory, and numerical feedback.
Utility: Helps drivers estimate distance in blind spots.
Differentiator: Unlike basic systems, it uses three sensors to cover the entire width of the bumper (left, center, right).
The system reads distance data from three ultrasonic sensors and processes it using the ATmega328P microcontroller.
Features:
Component List:
| Component | Role in the project | Datasheet |
|---|---|---|
| ATmega328P-XMINI | System brain; processes signals and controls peripherals | ATmega328P-XMINI |
| 3× HC-SR04 | Distance measurement using ultrasonic waves (Left, Center, Right) | HC-SR04 |
| 3× RGB LEDs (CC) | Optical indicator for each sensor (Green = Safe, Red = Stop) | |
| 6x Resistor | A separate 220Ω resistor was used in series with the anode of each RGB LED | |
| Passive Buzzer | Variable sound alarm | Buzzer |
| LCD 16×2 | Displays measured distances | LCD 16×2 |
Electrical Diagram:
Component Justification
The HC-SR04 ultrasonic sensor was selected for distance measurement due to its operating range (2–400 cm), which perfectly covers the rear parking use case. It is also low-cost and features a simple TRIG/ECHO interface that is directly compatible with the GPIO pins of the ATmega328P. Using three sensors (left, center, right) provides full spatial coverage of the area behind the vehicle and enables detection of lateral obstacles that would not be visible with a single central sensor.
The RGB LEDs (common cathode) were chosen to provide intuitive visual feedback. They allow color-coded signaling (green → yellow → red), which is universally recognized in parking and safety systems. Compared to single-color LEDs, RGB LEDs reduce the number of physical components while enabling multiple states to be displayed for each sensing zone.
The passive buzzer was selected for auditory feedback because it allows control over the frequency of the emitted sound. This makes it possible to vary the beep rate depending on the distance to the obstacle. In contrast, an active buzzer would only produce a constant tone, limiting the ability to convey proximity information dynamically.
The 16×2 LCD with I2C interface was chosen to display numerical distance values for each zone. This provides precise, easy-to-read feedback similar to a dashboard display. The use of an I2C adapter significantly reduces the number of required microcontroller pins compared to parallel communication (4- or 8-bit mode), simplifying wiring and leaving more pins available for other components.
The firmware is built around a non-blocking main loop that coordinates four main tasks: collecting distance data from three ultrasonic sensors, controlling three RGB LEDs for visual feedback, driving a passive piezo buzzer for audio alerts, and updating a 16×2 I²C LCD display.
To keep the system responsive, sensor measurements are handled asynchronously using interrupts, so the CPU never sits idle waiting for an echo pulse. The buzzer also runs on its own timing scheduler based on millis(), which means the beep pattern remains smooth and independent from the sensor update rate.
The program logic is based on calculating the round-trip time of the sound signal:$$Distance = \frac{Time \times Speed of Sound}{2}$$
The firmware is split into five logical modules:
Algorithm structure:
The first version of the project measured echo duration using a busy-wait loop around TCNT1. While functional, this approach blocked the CPU and tied up Timer1 completely.
Moving to Pin Change Interrupts solved both issues: the CPU remains free while measurements occur in the background, and Timer1 is now available for future extensions.
An earlier implementation used PWM to create smooth color transitions between green, yellow, and red. In practice, this introduced visible glitches because the LEDs relied on timers shared with the buzzer subsystem.
Specifically, Timer2 is also used by tone(), so activating the buzzer interfered with PWM outputs on pins such as D3 and D11.
The final design uses three discrete LED states with hysteresis. Although this sacrifices continuous color gradients, it results in clearer feedback and avoids timer conflicts entirely.
Triggering all three ultrasonic sensors simultaneously would reduce measurement time, but it risks acoustic cross-talk, where one sensor receives another sensor’s echo.
To avoid this, the sensors are triggered sequentially with a 10 ms delay between measurements, ensuring each sensor only processes its own reflected pulse.
The completed system was mounted on a toy car and powered by a portable USB power bank, making it fully self-contained and independent of a development computer.
The three ultrasonic sensors achieve a ranging accuracy of approximately 1-2 cm across their effective operating range. The exponential moving average filter applied to each sensor's readings eliminates the characteristic +/-1-2 cm jitter of the raw HC-SR04 output, producing stable distance values without introducing perceptible lag (the system reacts to a real distance change in under ~600 ms).
The three-zone feedback proved intuitive: each RGB LED independently reflects the proximity state of its corresponding sensor (green / yellow / red), letting the driver instantly identify which side of the vehicle is closest to an obstacle. The buzzer, driven by the minimum of the three measured distances, varies both its beep cadence and its tone frequency continuously as the nearest obstacle approaches, culminating in a continuous tone below 10 cm. The LCD provides a precise numeric readout of all three distances simultaneously, for drivers who prefer a “dashboard” view.
The asymmetric hysteresis on the LED state machine eliminated the boundary flickering observed in early prototypes, and the non-blocking architecture keeps the buzzer responsive even while the sensors are being polled.
A demonstration of the complete system in operation:
Building this project taught me a lot about how embedded systems work in practice - not just coding, but also designing the hardware, debugging odd issues, and getting everything to run smoothly on a moving toy car.
One of the biggest lessons was learning how limited hardware resources have to be shared carefully. The ATmega328P only has three timers, and I needed them for the buzzer, LEDs, and time measurements at the same time. I ran into conflicts where the LEDs flickered whenever the buzzer was active, which forced me to better understand how the timers and pins are connected. In the end, I simplified the LEDs to basic on/off colors to avoid those conflicts.
I also learned how important pin selection is. At one point I connected a sensor to PB5, not realizing it was also used by the programmer. That caused upload failures until I rewired the sensor, and after that I became much more careful about checking pin functions beforehand.
Another challenge was dealing with noisy sensor readings. The measured distance constantly shifted by small amounts, which made the LEDs flicker and the buzzer react unpredictably. Adding a simple averaging filter and some hysteresis made the whole system feel much more stable and reliable.
Writing the I2C LCD driver and interrupt handlers from scratch also gave me a much better understanding of what happens behind the scenes, compared to just using ready-made libraries.
If I continued developing the project, I would add a low-power sleep mode, improve the LED fading effects, and possibly include more sensors for better coverage around the car.
Overall, the project showed that the ATmega328P can reliably handle multiple sensors and peripherals at once using timers and interrupts, while the modular structure makes the system easy to adapt for other small vehicles.