Build an ultrasonic radar with the UNO

A servo sweeps an ultrasonic sensor from side to side while your computer draws a live green radar screen. Three LEDs and a buzzer warn you when something gets close.
  • Level:Intermediate
  • Duration: 1 h 15 min
  • Ages 12+
  • Platform: Arduino

Tools for this lesson

Helpful for this build. Open a tool to see tips and more projects that use it.

Build an ultrasonic radar with the UNO – EEMENTOR STEM™ lesson

A real radar spins an antenna and listens for echoes. Yours does the same with sound you can't hear: a servo turns the ultrasonic sensor from side to side, the UNO measures the distance at every degree, and your computer draws it all as a green radar screen. Three LEDs and a buzzer work as a warning light on the desk, so the radar is useful even without the computer.

What you'll learn

  • How to sweep a servo and take a measurement at every step
  • How to send data to the computer over the serial port
  • How a program on the computer reads that data and draws it
  • How to turn a distance into a traffic-light warning

What you need

  • UNO R3 board and USB cable (UNO R3 Starter Kit)
  • Ultrasonic sensor HC-SR04 (UNO R3 Starter Kit)
  • SG90 micro servo (UNO R3 Starter Kit)
  • Green, yellow and red LEDs and three 220 Ω resistors (UNO R3 Starter Kit)
  • Active buzzer (UNO R3 Starter Kit)
  • Breadboard and jumper wires, including four female-to-male wires for the sensor (UNO R3 Starter Kit)
  • Double-sided tape or a small printed bracket to hold the sensor on the servo
  • A computer with the free Processing app for the radar screen

Build the radar turret

  1. Push the long two-sided horn onto the servo, but don't screw it on yet.
  2. Centre the servo before you fix the horn: wire the servo as shown below, upload a sketch with turret.attach(9); turret.write(90); in setup(), then take the horn off and put it back pointing straight forward.
  3. Stick the HC-SR04 on the horn with double-sided tape, with its "eyes" facing forward and its pins pointing up.
  4. Connect the sensor with four female-to-male jumper wires, and leave them loose enough for the servo to turn through its whole sweep.

Have a 3D printer? A small bracket that clips the sensor onto the servo horn makes the turret sturdier. Any HC-SR04 servo bracket works.

Wiring

Breadboard wiring diagram: Build an ultrasonic radar with the UNO
Breadboard view. Check each connection against the wiring table below.
From To
Ultrasonic VCC + rail (5V)
Ultrasonic Trig UNO pin 10
Ultrasonic Echo UNO pin 11
Ultrasonic GND − rail (GND)
Servo signal (orange) UNO pin 9
Servo + (red) + rail (5V)
Servo − (brown) − rail (GND)
Green LED, long leg UNO pin 7
Yellow LED, long leg UNO pin 6
Red LED, long leg UNO pin 5
Each LED's short leg 220 Ω resistor to the − rail
Active buzzer + UNO pin 8
Active buzzer − − rail (GND)
UNO 5V + rail
UNO GND − rail

Use the active buzzer: it beeps on its own when its pin goes HIGH. The long leg of each LED is the + side.

The Arduino sketch

#include <Servo.h>

const int TRIG_PIN = 10;
const int ECHO_PIN = 11;
const int SERVO_PIN = 9;
const int GREEN_LED = 7;
const int YELLOW_LED = 6;
const int RED_LED = 5;
const int BUZZER_PIN = 8;

const int MIN_ANGLE = 15;    // the servo sweeps from here...
const int MAX_ANGLE = 165;   // ...to here and back
const int RANGE_CM = 40;     // the radar only "sees" this far
const int NEAR_CM = 15;      // closer than this: red LED and beep

Servo turret;

long readCm() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  long us = pulseIn(ECHO_PIN, HIGH, 30000);  // give up after 30 ms (about 5 m)
  if (us == 0) return 0;                     // 0 means "nothing found"
  return us / 58;
}

void showDistance(long cm) {
  bool found = cm > 0 && cm <= RANGE_CM;
  bool near = found && cm <= NEAR_CM;
  digitalWrite(GREEN_LED, !found);           // green: all clear
  digitalWrite(YELLOW_LED, found && !near);  // yellow: something in range
  digitalWrite(RED_LED, near);               // red: something close
  digitalWrite(BUZZER_PIN, near);            // and the buzzer beeps
}

void scanAt(int angle) {
  turret.write(angle);
  delay(30);                                 // let the servo arrive
  long cm = readCm();
  showDistance(cm);
  Serial.print(angle);                       // send "angle,distance." to the PC
  Serial.print(",");
  Serial.print(cm);
  Serial.print(".");
}

void setup() {
  Serial.begin(9600);
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  pinMode(GREEN_LED, OUTPUT);
  pinMode(YELLOW_LED, OUTPUT);
  pinMode(RED_LED, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  turret.attach(SERVO_PIN);
}

void loop() {
  for (int angle = MIN_ANGLE; angle <= MAX_ANGLE; angle++) scanAt(angle);
  for (int angle = MAX_ANGLE; angle >= MIN_ANGLE; angle--) scanAt(angle);
}

The radar screen (Processing)

Install Processing, start it, paste this sketch into a new window and click Run. Close the Arduino IDE's Serial Monitor first: only one program can use the port at a time.

import processing.serial.*;

final int RANGE_CM = 40;          // must match RANGE_CM in the Arduino sketch
Serial port;
String buffer = "";
int angle = 0;
int distance = 0;
int[] seen = new int[181];        // the last distance found at each angle

void setup() {
  size(1200, 700);
  smooth();
  println(Serial.list());         // the list of ports, in the console
  port = new Serial(this, Serial.list()[0], 9600);  // change [0] if needed
}

void serialEvent(Serial p) {
  char c = p.readChar();
  if (c == '.') {                 // one full "angle,distance" has arrived
    String[] parts = split(trim(buffer), ',');
    if (parts.length == 2) {
      angle = int(parts[0]);
      distance = int(parts[1]);
      if (angle >= 0 && angle <= 180) seen[angle] = distance;
    }
    buffer = "";
  } else {
    buffer += c;
  }
}

void draw() {
  fill(0, 20);                    // a see-through black: old lines fade out
  noStroke();
  rect(0, 0, width, height);

  float cx = width / 2.0;
  float cy = height - 70;
  float r = width * 0.45;         // radius of the radar on screen

  // rings and angle lines
  noFill();
  stroke(60, 220, 100);
  strokeWeight(2);
  for (int i = 1; i <= 4; i++) arc(cx, cy, 2 * r * i / 4, 2 * r * i / 4, PI, TWO_PI);
  for (int a = 30; a <= 150; a += 30) line(cx, cy, cx + r * cos(radians(a)), cy - r * sin(radians(a)));

  // objects: a red line from the object to the edge
  stroke(230, 60, 60);
  strokeWeight(5);
  for (int a = 0; a <= 180; a++) {
    int d = seen[a];
    if (d > 0 && d <= RANGE_CM) {
      float p = r * d / RANGE_CM;
      line(cx + p * cos(radians(a)), cy - p * sin(radians(a)),
           cx + r * cos(radians(a)), cy - r * sin(radians(a)));
    }
  }

  // the sweep line
  stroke(60, 255, 120);
  strokeWeight(6);
  line(cx, cy, cx + r * cos(radians(angle)), cy - r * sin(radians(angle)));

  // the status bar
  noStroke();
  fill(0);
  rect(0, height - 50, width, 50);
  fill(60, 255, 120);
  textSize(24);
  boolean inRange = distance > 0 && distance <= RANGE_CM;
  text("Angle: " + angle + "°", 40, height - 17);
  text("Status: " + (inRange ? "In range  " + distance + " cm" : "Out of range"), width / 2 - 120, height - 17);
  for (int i = 1; i <= 4; i++) text(RANGE_CM * i / 4 + " cm", cx + r * i / 4 - 50, cy - 8);
}
Example screen for: Build an ultrasonic radar with the UNO
Example radar screen with sample values. Yours updates live.

Try it

  1. Upload the Arduino sketch. The servo starts sweeping slowly from left to right and back, and the green LED is on.
  2. Run the Processing sketch. A green line sweeps across the screen in time with the servo.
  3. Put your hand or a toy about 30 cm in front of the sensor. A red line appears on the screen at that angle, and the yellow LED lights up.
  4. Move it closer than 15 cm. The red LED comes on and the buzzer beeps.

How it works

For every angle the UNO sends a short message such as 87,23.: the angle, a comma, the distance in centimetres and a full stop. The full stop marks the end of the message, so the computer knows when it has the whole thing. A distance of 0 means nothing came back.

Processing turns each angle and distance into a point with a little trigonometry: x = cos(angle) × distance and y = sin(angle) × distance, scaled to fit the screen. It keeps the last distance for each angle in an array, so objects stay on the screen until the sweep comes round again. Drawing a see-through black rectangle over the whole window every frame makes the old sweep lines fade away slowly, just like a real radar screen.

Try this next

  • Change RANGE_CM in both sketches to 60 to see further. Readings get less reliable beyond about 1 m.
  • Make the servo sweep faster by changing delay(30) to delay(15). What happens to the picture?
  • Add the LCD from the LCD lesson and show the angle and distance of the nearest object.
  • Go wireless: the ESP32 radar shows the same picture on your phone, with no cable to the computer.

Troubleshooting

  • Processing says the port is busy or doesn't exist: close the Serial Monitor. Look at the list printed in Processing's console and change Serial.list()[0] to the number of the port your UNO uses (often the last one).
  • The UNO resets or the servo jitters: the servo pulls a lot of current when it starts. Plug the UNO into a USB port directly, not through a hub, or power the servo from the breadboard power module.
  • Objects appear in the wrong place: the horn is not pointing forward at 90°. Take it off and put it back while the servo is at 90°.
  • Everything shows as "Out of range": check that Trig is on pin 10 and Echo on pin 11. Swapping them is the most common mistake.

Build it yourself

Everything used in this lesson comes in one kit, with parts tested by our engineers.

UNO R3 Starter Kit | Arduino IDE Compatible | Free Tutorials $56.00

Shop the kit