Arduino servo radar
Build a sweeping radar with Arduino, a micro servo, and an HC-SR04
A servo nods an ultrasonic sensor back and forth across 180°. The Arduino takes a distance reading at every degree and streams angle,distance pairs over USB. A Processing sketch on your laptop draws it as a glowing green radar sweep with red blips wherever something is in range. It's the canonical "I just built a thing that looks like sci-fi" Arduino project, and you can have it running in an evening.
What it actually does
The HC-SR04 fires a 40 kHz ultrasonic pulse and listens for the echo. The Arduino times how long the echo took, divides by two, multiplies by the speed of sound (~343 m/s, or 0.0343 cm/µs), and you have a distance — usable from about 2 cm out to ~400 cm in lab conditions, though in practice anything past ~200 cm against a soft target gets unreliable. The SG90 servo rotates the sensor through 180° (well — almost; we sweep 15°–165° to keep clear of the mechanical end-stops). Each loop pass spits one angle,distance reading down the serial port. Processing draws the rest.
What you'll need
| Item | AliExpress | Amazon |
|---|---|---|
| Arduino Uno R3 (any clone with a CH340 or 16U2 USB chip is fine) | AliExpress Link | Amazon Link |
| HC-SR04 ultrasonic distance sensor (4-pin, 5 V) | AliExpress Link | Amazon Link |
| SG90 micro servo, 9 g (the blue Tower Pro ones — clones are everywhere) | AliExpress Link | Amazon Link |
| Half-size solderless breadboard (400 tie-points) | AliExpress Link | Amazon Link |
| Dupont jumper wires (M–M and M–F mixed pack) | AliExpress Link | Amazon Link |
| HC-SR04 + SG90 servo bracket (optional but tidy — also printable) | AliExpress Link | Amazon Link |
You'll also need the Arduino IDE (free) and Processing 4 (free, separate download from processing.org). Both are about a 5-minute install.
Notes on the parts
- The SG90 is fine, but it jitters. The servo's internal pot isn't precision kit, so you'll see ±1° wobble at the end of each sweep and a faint buzz when it's holding position. If that bothers you, an MG90S (metal-gear) is a drop-in upgrade for a couple of euro more.
- HC-SR04 vs HC-SR04+ vs JSN-SR04T. The plain HC-SR04 is what every tutorial assumes — 5 V trigger, 5 V echo, two metal "eyes". The "+" variant runs at 3.3–5 V (handy for ESP32). The waterproof JSN-SR04T is overkill here and has different timing.
- Power. The Uno's 5 V rail can drive one SG90 plus the HC-SR04 with margin, off USB. If you swap to a bigger servo or a 16-channel LED ring, give the servo its own 5 V supply and tie the grounds together — the Uno's onboard regulator browns out fast.
- Mount. A laser-cut servo bracket, a 3D-printed one, or — yes, this is a tradition — a folded piece of cardboard with hot glue. The original How To Mechatronics build used cardboard. It works. It also looks like cardboard.
Wiring
Five connections to the breadboard, four to the Arduino. Power both modules from the Uno's 5 V and GND.
HC-SR04 → Arduino Uno
- VCC → 5 V
- GND → GND
- Trig → digital pin 10
- Echo → digital pin 11
SG90 servo → Arduino Uno
- Red → 5 V
- Brown (or black) → GND
- Orange (or yellow) → digital pin 12
The servo's signal pin is happy on any digital output — pin 12 is just convention from the canonical tutorial. The HC-SR04's echo line outputs 5 V, which is fine for a 5 V Uno; on a 3.3 V board you'd need a divider. The whole thing draws under 200 mA, well within USB-power limits, but if the servo browns out the Uno (you'll see it reset partway through a sweep), add a 470 µF cap across the 5 V/GND rails on the breadboard.
Mount the sensor on the servo
The mechanical bit is the only part that's fiddly. You want the HC-SR04's two transducers facing outward (the direction of travel), and the sensor's center of mass roughly over the servo shaft so the SG90 isn't lifting an unbalanced lever.
- Printed bracket: plenty of free models on Printables / Thingiverse — search "HC-SR04 SG90 bracket". Two M2 screws hold the sensor; one of the SG90 horn-screws holds the bracket.
- Cardboard: fold a strip into a U with two holes for the sensor's transducers, hot-glue it to a single-arm servo horn. Works fine, surprisingly stiff.
- Hot glue + horn directly: ugly, but you can be sweeping in 90 seconds.
Before you screw the horn down for keeps, plug everything in and run the Servo library example Sweep once — that centres the servo at 90° so you can mount the sensor pointing dead-ahead. Otherwise your radar's "north" will be 30° off and you'll spend an hour wondering why the sweep is asymmetric.
The Arduino sketch
This is essentially the canonical Arduino-Radar sketch from Dejan Nedelkovski's How To Mechatronics tutorial — the one every fork on GitHub descends from. It works.
#include <Servo.h>
const int trigPin = 10;
const int echoPin = 11;
const int servoPin = 12;
long duration;
int distance;
Servo myServo;
void setup() {
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
Serial.begin(9600);
myServo.attach(servoPin);
}
void loop() {
// sweep right
for (int angle = 15; angle <= 165; angle++) {
myServo.write(angle);
delay(30); // settle time for the SG90
distance = readDistanceCm();
Serial.print(angle); Serial.print(",");
Serial.print(distance); Serial.print(".");
}
// sweep back
for (int angle = 165; angle > 15; angle--) {
myServo.write(angle);
delay(30);
distance = readDistanceCm();
Serial.print(angle); Serial.print(",");
Serial.print(distance); Serial.print(".");
}
}
int readDistanceCm() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH, 30000UL); // 30 ms timeout ≈ 5 m
return duration * 0.034 / 2;
}
Two non-obvious bits:
delay(30)between steps. Less than ~20 ms and the SG90 hasn't finished moving when you ping; the reading is the previous angle. More than ~50 ms and the sweep gets sluggish.pulseIntimeout. The default is 1 second. Add the30000UL(microseconds) timeout or one missed echo will stall the entire sweep for a full second. With the timeout, a miss returns 0 and the sweep keeps going.
Open the Serial Monitor at 9600 baud and you should see a torrent like 15,127.16,128.17,128.…. Close the Serial Monitor before you run the Processing sketch — the port can only be open in one program at a time.
The Processing visualization
Processing is a Java-based sketching IDE that's basically built for this kind of thing. Install Processing 4, paste the sketch from the canonical How To Mechatronics tutorial (search "Arduino Radar Project Processing code" — it's the one that imports processing.serial.* and draws four arcs and a rotating line), then change two lines:
size(1200, 700); // match your screen
myPort = new Serial(this, "COM5", 9600); // your Arduino's port
On macOS the port looks like /dev/cu.usbmodem11101; on Linux, /dev/ttyUSB0 or /dev/ttyACM0; on Windows, COM3/COM4/COM5. Find it in the Arduino IDE under Tools → Port, then paste the same string into Processing.
You'll also need the OCR A Extended font (or any font of your choice, with the name updated in createFont(...)) in the sketch's data/ folder. Processing complains loudly if it's missing — there's a one-click "Create Font" button under Tools that bakes a .vlw file into data/.
Hit run. You'll get a black background, four green arcs at 10/20/30/40 cm, a rotating green line tracking the servo, and red blips wherever the sensor sees something. Wave your hand in front of it.
Common things that go wrong
- Sweep is jerky or only covers half the arc. The servo is brown-outing. Add the 470 µF cap, or power the servo from a separate 5 V supply (USB charger + buck) with a common ground.
- Distance reads 0 or stuck values. Echo wire on the wrong pin, or you forgot the
pulseIntimeout. Verify by aiming at a flat wall 30 cm away and watching Serial Monitor. - Radar shows objects "behind" the sweep line. The Processing sketch draws blips with a fade trail — they linger ~2 seconds. That's a feature. If they don't fade at all, your sketch's
redrawrect isn't covering the previous frame. - Processing says "Error opening serial port". Either the Arduino IDE Serial Monitor is still open, or you have the wrong COM/tty in
Serial(...). - Readings are noisy as soon as anything soft is in range. Cloth, hair, and curtains absorb 40 kHz pulses. The HC-SR04 is great at hard flat targets, lousy at fluffy ones. Average two or three readings per angle if it bothers you.
Where to go from here
- Drop the laptop. Swap Processing for an SSD1306 OLED or a 2.8" TFT and draw the radar onboard the Arduino — there are good libraries for both.
- Bigger sweep, smaller steps. A geared MG996R lets you carry a heavier sensor (or a small Lidar like the TF-Luna) across a full 270°.
- Detection logic. Add a buzzer that beeps when the closest blip is under 30 cm. That's a single
ifin the loop. - Wireless. Replace the Uno with an ESP32, send the data over Wi-Fi to a browser, and you've got a remote intruder radar.
Total build time, with parts on the bench: about 45 minutes for wiring and the Arduino sketch, another 15 to wrangle Processing's font and serial port. The first time the green sweep paints across your screen and a red dot appears where your hand actually is, it's hard not to grin.