← Portfolio
Hardware

Sonar Guard

Sep 2026

An ultrasonic turret that learns what a room normally looks like, then sweeps it and flags anything new.

Try the live demo →

What it does

An ultrasonic sensor on a servo sweeps back and forth across 160°. It spends its first four sweeps learning where the walls and furniture are, then compares every sweep after that against what it learned. When something new shows up, it locks on, follows it, and gives you 20 seconds to enter a 4-digit code before the siren goes off. A browser dashboard shows the live radar, the learned room and the raw data coming over USB.

The real turret: arming, learning the room, then locking onto a hand and asking for the code. Sound on for the pings.
The turret. The servo in the lower box turns the upper box and the sensor, with the LCD in front and the dashboard behind.
The turret. The servo in the lower box turns the upper box and the sensor, with the LCD in front and the dashboard behind.
HC-SR04 sensor on the rotating box, which rides on the servo horn.
HC-SR04 sensor on the rotating box, which rides on the servo horn.
Arduino UNO, LCD1602, IR receiver and buzzer on the breadboard.
Arduino UNO, LCD1602, IR receiver and buzzer on the breadboard.
Disarmed and waiting, with the IR remote and the live dashboard.
Disarmed and waiting, with the IR remote and the live dashboard.
The dashboard in Demo mode, locked onto a simulated person. Red dots are readings closer than the learned room.
The dashboard in Demo mode, locked onto a simulated person. Red dots are readings closer than the learned room.
The session report after the code is entered. These numbers come from the simulator, not the real turret.
The session report after the code is entered. These numbers come from the simulator, not the real turret.

How it works

  1. Learn

    Press Arm on the IR remote, the button or the dashboard. After a 5-second exit delay the turret does 4 full sweeps. For every 4° slice of the room it saves the median distance as the baseline and half the spread as that slice's noise.

  2. Patrol

    It sweeps from 10° to 170° without stopping, about 3.5 seconds per pass, and compares every slice to its baseline.

  3. Detect

    A slice counts as changed when something within 250 cm is closer than the baseline by more than 20 cm, 3 times that slice's noise, or 10% of the distance, whichever is largest. Two neighboring slices have to change in the same sweep before it triggers.

  4. Track

    The sweep narrows to 30° either side of the object and re-centers on it every pass, so it follows someone walking. The LCD shows the bearing and range, and the buzzer pings higher the closer they get. If the object disappears for 3 passes, it goes back to sweeping the whole room.

  5. Code

    You have 20 seconds to enter the code on the remote, the dashboard keypad or the laptop keyboard. The right code disarms it and the dashboard shows a session report. No code in time, or 3 wrong tries, sets off a two-tone siren.

Technical details

Controller
Arduino UNO R3
Sensor
HC-SR04 ultrasonic rangefinder on an SG90 micro servo
Other parts
LCD1602 display, IR receiver and remote, passive buzzer and a push button, all from an Elegoo starter kit. The housing is two Advil boxes.
Echo timing
A pin-change interrupt timestamps the echo pulse, so the main loop never waits on the sensor. It fires a ping every 30 ms and collects the result later.
Sweep
The servo steps 1° every 22 ms. Each reading is tagged with the angle it was fired at, minus 2° to make up for the servo lagging its command.
Slices
Readings are grouped into 41 slices of 4°. Each slice keeps the median of up to 6 readings per sweep.
Target size
Apparent width is 2 × range × tan(span / 2). The sensor's beam is about 15° wide, so width and speed are estimates.
Dashboard
One HTML file with no dependencies. It talks to the Arduino over USB with the Web Serial API in Chrome or Edge. Demo mode ray-casts a virtual room and a person walking in, and speaks the same serial protocol as the real turret.

Engineering decisions

A loop that never waits

The Arduino has to sweep, listen for the remote, beep and update the screen at the same time, so nothing in the loop blocks. An interrupt times each echo in the background, the servo steps on a timer, and sounds go into a small queue. The sweep is continuous and the remote is read on every pass through the loop.

Sharing the hardware timers

The UNO has limited hardware timers. The Servo library uses Timer1, tone() uses Timer2, and the standard IR receiver also wants Timer2. I used IRremote's TinyIRReceiver instead, which decodes on an external interrupt and needs no timer, so all three run together. That's why the IR receiver is on pin 2 and the button is on A1.

A threshold for every slice

Some parts of a room read steadier than others, so each 4° slice gets its own threshold, scaled to the noise measured while learning. Requiring two neighboring slices to agree before triggering keeps a single stray reading from setting it off.

A dashboard with nothing to install

The laptop side is a single web page that talks to the Arduino over Web Serial. Anyone can open it in Chrome or Edge, and the same page doubles as the public demo.

What I'd do next

Links