Digital ChallengeArduino × Processing
P3Project module

Sonar — Ultrasonic Sensor HC-SR04

Measure distance with sound and build a working radar screen.

Use the HC-SR04 to measure distance with ultrasound, control an SG90 servo from Processing, make the servo react to obstacles, and finally combine everything into a sweeping radar display.

4 × 45 min difficultyPhysicsMathematicsComputer Science
Sonar — Ultrasonic Sensor HC-SR04
pulseIn()Speed of soundServo libraryTrigonometryTwo-way serial
01Before you start

What you’ll learn

By the end of this module you can…
  • 1Explain how an ultrasonic sensor measures distance using the echo time.
  • 2Calculate distance from time with d = v·t / 2 and explain the factor 2.
  • 3Control a servo motor with the Servo library and commands from Processing.
  • 4Write non-blocking code so Arduino can react to new commands at any time.
  • 5Convert polar coordinates (angle, distance) to screen coordinates with sin() and cos().
Key vocabulary
Ultrasound
Sound above human hearing (> 20 kHz). The HC-SR04 uses 40 kHz.
Echo
A reflected sound wave that returns to the sensor.
pulseIn()
Arduino function that measures how long a pin stays HIGH, in microseconds.
Servo motor
A motor that turns to a precise angle (0–180°) controlled by a PWM signal.
PWM
Pulse-Width Modulation — switching a signal on and off quickly; the pulse width carries the information.
Polar coordinates
Describing a point by an angle and a distance from the centre, like a radar does.
02Kit list

Required equipment

ComponentQtyPurpose
Arduino Uno1Microcontroller
HC-SR04 ultrasonic sensor1Distance measurement (2–400 cm)
SG90 servo motor1Radar sweep (Ex. 2–4)
Plastic holder for sensor1Mount the sensor on the servo
Breadboard + jumper wires1 setComponent connection
USB cable1Connection to computer
Processing IDE1Visualization
03Theory

Physics of Ultrasonic Sensing

The sensor emits a short burst of ultrasound (~40 kHz). When the wave hits an object it bounces back. The sensor measures the time until the echo returns — just like bats and dolphins do.

Formula
distance = (speed of sound × time) / 2
Speed of sound ≈ 343 m/s = 0.0343 cm/µs in air at 20 °C. We divide by 2 because the sound travels there and back.
InteractiveEcho labMove the obstacle and watch the pulse travel. Change the air temperature to see why the speed of sound matters.
HC-SR0460 cmtrigger → ping
Speed of sound
343.4m/s
pulseIn() returns
3,494µs
Code reports (343 m/s)
59.9cm
Error
-0.1%
04Hands-on

Exercise 1 — Measure Distance & Display in Processing

HC-SR04 connected to the Arduino Uno.
HC-SR04 connected to the Arduino Uno.
HC-SR04 pinArduino pin
VCC5V
GNDGND
TRIGPin 3
ECHOPin 2
Note
TRIG starts a measurement with a 10 µs pulse. ECHO stays HIGH for as long as the sound was travelling.
Distance.inoArduino · C++
#define trigPin 3
#define echoPin 2

void setup() {
  Serial.begin(9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);          // 10 µs trigger pulse
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  long duration = pulseIn(echoPin, HIGH, 30000);  // timeout 30 ms ≈ 5 m
  float distance = duration * 0.0343 / 2;         // cm
  Serial.println(distance);
  delay(200);
}
DistanceBar.pde — text + horizontal barProcessing · Java
import processing.serial.*;

Serial myPort;
float distance;

void setup() {
  size(600, 200);
  printArray(Serial.list());
  myPort = new Serial(this, Serial.list()[0], 9600);
  myPort.bufferUntil('\n');
}

void draw() {
  background(255);
  fill(0);
  textSize(24);
  text("Distance: " + nf(distance, 0, 2) + " cm", 50, 50);

  fill(100, 200, 255);                                    // horizontal bar
  rect(50, 100, map(constrain(distance, 0, 200), 0, 200, 0, width - 100), 30);
}

void serialEvent(Serial p) {
  String data = p.readStringUntil('\n');
  if (data != null) distance = float(trim(data));
}
05Hands-on

Exercise 2 — Control the SG90 Servo from Processing

SG90 servo wiring.
SG90 servo wiring.
Servo wireArduino pin
Signal (orange)Pin 9
VCC (red)5V
GND (brown)GND

Background reading: The Beginner’s Guide to Micro Servos — docs.arduino.cc/learn/electronics/servo-motors

ServoSweep.inoArduino · C++
#include <Servo.h>

Servo servo;
bool sweeping = false;
int angle = 0;
int step = 1;

void setup() {
  Serial.begin(9600);
  servo.attach(9);
}

void loop() {
  if (Serial.available()) {
    String command = Serial.readStringUntil('\n');
    command.trim();
    sweeping = (command == "1");      // "1" = START, anything else = STOP
  }

  if (sweeping) {                     // one small step per loop()
    angle += step;
    if (angle >= 180 || angle <= 0) step = -step;
    servo.write(angle);
    delay(10);
  }
}
UpdatedRewritten as a non-blocking sweep: the original nested for-loops could not react to STOP until a full sweep had finished.
ServoButtons.pde — START / STOPProcessing · Java
import processing.serial.*;

Serial myPort;
boolean isSweeping = false;

void setup() {
  size(400, 200);
  myPort = new Serial(this, Serial.list()[0], 9600);
  textAlign(CENTER, CENTER);
}

void draw() {
  background(240);
  textSize(16);
  fill(0);
  text("Servo Control", width/2, 30);
  drawButton("START", 100, 100, isSweeping);
  drawButton("STOP", 250, 100, !isSweeping);
}

void drawButton(String label, int x, int y, boolean active) {
  fill(active ? color(0, 200, 0) : color(180));
  rect(x, y, 100, 40, 7);
  fill(0);
  text(label, x + 50, y + 20);
}

void mousePressed() {
  if (mouseX > 100 && mouseX < 200 && mouseY > 100 && mouseY < 140) {
    myPort.write("1\n");
    isSweeping = true;
  } else if (mouseX > 250 && mouseX < 350 && mouseY > 100 && mouseY < 140) {
    myPort.write("0\n");
    isSweeping = false;
  }
}
  • ▸START sends "1" → Arduino begins sweeping the servo.
  • ▸STOP sends "0" → Arduino halts the movement immediately.
  • ▸Expand it with an angle slider, speed control or real-time feedback.
06Hands-on

Exercise 3 — Ultrasonic Sensor Controlling the Servo

The servo turns to 90° when an object is closer than 50 cm and returns to 0° otherwise — like an automatic barrier.

HC-SR04 (TRIG 6, ECHO 7) and servo (pin 9) together.
HC-SR04 (TRIG 6, ECHO 7) and servo (pin 9) together.
ProximityServo.inoArduino · C++
#include <Servo.h>

const int TRIG_PIN = 6;
const int ECHO_PIN = 7;
const int SERVO_PIN = 9;
const int DISTANCE_THRESHOLD = 50;   // centimetres

Servo servo;
float duration_us, distance_cm;

void setup() {
  Serial.begin(9600);
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  servo.attach(SERVO_PIN);
  servo.write(0);
}

void loop() {
  digitalWrite(TRIG_PIN, HIGH);      // 10 µs pulse
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  duration_us = pulseIn(ECHO_PIN, HIGH);
  distance_cm = 0.017 * duration_us; // = 0.0343 / 2

  if (distance_cm < DISTANCE_THRESHOLD) servo.write(90);
  else                                  servo.write(0);

  Serial.print("distance: ");
  Serial.print(distance_cm);
  Serial.println(" cm");
  delay(500);
}
Student task
Write a Processing program that shows the distance (a) as a number with text() and (b) as a horizontal bar. Careful: this sketch sends distance: 23.4 cm, not just a number — see exercise P3.4.
07Project

Exercise 4 — Build a Radar Scanner

Level up
This exercise is suitable as a full project topic.
InteractiveRadar previewLive preview of what you are building. Click inside the radar to place obstacles.
ANGLE   000°
DIST    000.0 cm
Serial: 0,0.0
< 30 cm< 60 cm≥ 60 cmclick to add an obstacle

The servo sweeps from 0° to 180°; at each step Arduino measures the distance and sends angle,distance. Processing converts each pair to an (x, y) point.

RadarSweep.inoArduino · C++
#include <Servo.h>

Servo myServo;
#define trigPin 9
#define echoPin 10

float measure() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  long duration = pulseIn(echoPin, HIGH, 30000);
  return duration * 0.0343 / 2;
}

void setup() {
  Serial.begin(9600);
  myServo.attach(6);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  for (int angle = 0; angle <= 180; angle += 2) {
    myServo.write(angle);
    delay(50);
    Serial.print(angle);
    Serial.print(",");
    Serial.println(measure());
  }
  for (int angle = 180; angle >= 0; angle -= 2) {   // sweep back too
    myServo.write(angle);
    delay(50);
    Serial.print(angle);
    Serial.print(",");
    Serial.println(measure());
  }
}
RadarBasic.pdeProcessing · Java
import processing.serial.*;

Serial myPort;
int angle;
float distance;

void setup() {
  size(600, 600);
  myPort = new Serial(this, Serial.list()[0], 9600);
  background(0);
}

void draw() {
  if (myPort.available() > 0) {
    String data = myPort.readStringUntil('\n');
    if (data != null && data.contains(",")) {
      String[] parts = split(trim(data), ",");
      if (parts.length == 2) {
        angle = int(parts[0]);
        distance = float(parts[1]);
        float r = map(distance, 0, 100, 0, 250);
        float x = width/2 + r * cos(radians(angle));
        float y = height  - r * sin(radians(angle));
        stroke(0, 255, 0);
        fill(0, 255, 0);
        ellipse(x, y, 5, 5);
      }
    }
  }
}
Formula
x = cx + r·cos(θ) y = cy − r·sin(θ)
Minus, because Y grows downward on screen.
LevelTask
BasicDisplay distance as text on the radar screen
IntermediateDraw radar grid lines and circles
AdvancedColour-code dots by distance (green / yellow / red)
ChallengeAdd sweep-line animation and a sound alert
08From the original handbook

Student tasks

Basic
Display distance as text
Serial + text()
Intermediate
Draw radar grid lines and circles
arc(), line(), loops
Advanced
Colour-code dots by distance (green/yellow/red)
Conditionals, colour
Challenge
Add sweep-line animation and a sound alert
Trigonometry, fading, Minim
09When it doesn’t work

Troubleshooting

ProblemLikely causeFix
Distance always 0No echo (timeout) or TRIG/ECHO swappedCheck pins; aim at a flat object 10–100 cm away.
Random big jumpsSoft or angled surfaces absorb/deflect soundUse flat, hard targets; average 3 readings.
Servo jitters or Arduino resetsServo draws too much current from USBPower the servo from a separate 5 V supply (common GND).
Radar points drawn upside downY-axis points down on screenUse y = cy − r·sin(θ).
Golden rule
Check the physical connections first, then the code. If nothing works, unplug, close both programs, reconnect and try again.
10New in this edition

Exercises

Basic · 2Intermediate · 2Advanced · 1Challenge · 1
P3.1BasicCalculate 10 min

Echo arithmetic

pulseIn() returns 1166 µs. (a) How far away is the object? (b) What echo time do you expect for an object 2 m away?

d = t × 0.0343 / 2 (cm, with t in µs). For (b) rearrange: t = 2d / 0.0343.
(a) 1166 × 0.0343 / 2 ≈ 20.0 cm · (b) t = 2 × 200 / 0.0343 ≈ 11 662 µs ≈ 11.7 ms
P3.2BasicExplain 5 min

Why divide by two?

A classmate forgets the / 2 in the distance formula. What will their readings look like? Explain using a sketch of the sound path.

Every reading will be exactly twice the real distance, because the measured time covers the path to the object and back.
P3.3IntermediateCalculate 10 min

Temperature matters

The speed of sound depends on air temperature: v ≈ 331.3 + 0.606 × T (m/s, T in °C). At 0 °C and 35 °C, what distance would the sensor report for a real distance of 100 cm if the code always assumes 343 m/s?

First find the real echo time t = 2 × 1 m / v_real, then compute the reported distance with v = 343 m/s.
0 °C: v = 331.3 m/s → reported = 100 × 343 / 331.3 ≈ 103.5 cm (+3.5 %). · 35 °C: v ≈ 352.5 m/s → reported ≈ 97.3 cm (−2.7 %). Combine with a DHT11 (Project 1) to correct it!
P3.4IntermediateDebug 15 min

Text in the numbers

Exercise 3 sends lines like distance: 23.4 cm. A student uses distance = float(trim(data)); in Processing and the bar never moves. Why? Fix it two ways: once in Arduino, once in Processing.

float("distance: 23.4 cm") returns NaN because the text isn’t a number. Fix A (Arduino): send only the number: Serial.println(distance_cm);. Fix B (Processing): extract it: String[] m = match(data, "([0-9.]+)"); if (m != null) distance = float(m[1]);
P3.5AdvancedCalculate 15 min

Polar to screen

The radar centre is at (300, 600) and 100 cm maps to 250 px. Calculate the screen position of an object at angle 30°, distance 60 cm, and at angle 135°, distance 100 cm.

r = 60 × 2.5 = 150 px. x = 300 + r·cos θ, y = 600 − r·sin θ.
30°, 60 cm: r = 150 → x = 300 + 150·0.866 ≈ 430, y = 600 − 150·0.5 = 525. · 135°, 100 cm: r = 250 → x = 300 + 250·(−0.707) ≈ 123, y = 600 − 250·0.707 ≈ 423.
P3.6ChallengeCode 45 min

Full radar display

Build the complete radar: green grid arcs every 25 cm, angle lines every 30°, a sweep line following the current angle, a fading trail, and dots colour-coded by distance (red < 30 cm, yellow < 60 cm, green otherwise).

Instead of background(0) each frame, draw a translucent black rectangle (fill(0, 20); rect(0,0,width,height);) — older drawings slowly fade away.
RadarPro.pdeProcessing · Java
import processing.serial.*;

Serial myPort;
int angle = 0;
float distance = 0;
final float MAX_CM = 100;
float R;   // radius in px

void setup() {
  size(800, 450);
  R = width / 2 - 20;
  myPort = new Serial(this, Serial.list()[0], 9600);
  myPort.bufferUntil('\n');
  background(0);
}

void draw() {
  noStroke();
  fill(0, 18);                         // fading trail
  rect(0, 0, width, height);

  translate(width / 2, height - 10);   // radar centre at the bottom
  drawGrid();

  stroke(61, 255, 154);                // sweep line
  strokeWeight(3);
  line(0, 0, R * cos(radians(angle)), -R * sin(radians(angle)));

  if (distance > 0 && distance < MAX_CM) {
    float r = map(distance, 0, MAX_CM, 0, R);
    if (distance < 30)      fill(255, 60, 60);
    else if (distance < 60) fill(255, 210, 60);
    else                    fill(61, 255, 154);
    noStroke();
    ellipse(r * cos(radians(angle)), -r * sin(radians(angle)), 10, 10);
  }

  resetMatrix();
  fill(61, 255, 154);
  textSize(16);
  text("Angle: " + angle + "\u00B0   Distance: " + nf(distance, 0, 1) + " cm", 20, 30);
}

void drawGrid() {
  noFill();
  stroke(61, 255, 154, 90);
  strokeWeight(1);
  for (int cm = 25; cm <= MAX_CM; cm += 25) {
    float d = map(cm, 0, MAX_CM, 0, R) * 2;
    arc(0, 0, d, d, PI, TWO_PI);
  }
  for (int a = 0; a <= 180; a += 30) {
    line(0, 0, R * cos(radians(a)), -R * sin(radians(a)));
  }
}

void serialEvent(Serial p) {
  String data = p.readStringUntil('\n');
  if (data == null) return;
  String[] parts = split(trim(data), ",");
  if (parts.length != 2) return;
  angle = int(parts[0]);
  distance = float(parts[1]);
}
11Check yourself

Self-check quiz

Progress
0/5 answered · 0 correct
  1. Q01

    What frequency does the HC-SR04 use?

  2. Q02

    Why is the measured time divided by 2?

  3. Q03

    Which library controls the SG90?

  4. Q04

    A radar point at 90° is drawn…

  5. Q05

    Why was the servo sweep rewritten as “one step per loop()”?

12Beyond the classroom

Real world & extensions

Where this is used
car parking sensorsobstacle-avoiding robotswater-tank level metersship sonar and fish findersautomatic doorsmedical ultrasound imaging
Extension ideas
  • +Sound effects or alarms when objects are detected
  • +A fully animated radar interface with fading trail
  • +Multiple ultrasonic sensors for wider coverage
  • +A smart parking assistant with LEDs showing distance
  • +Store radar scans for later analysis
  • +An obstacle-avoidance robot
Cross-curricular connections
SubjectConnection
PhysicsWaves, speed of sound, reflection, temperature dependence
MathematicsTrigonometry, polar → Cartesian coordinates, radians
BiologyEcholocation in bats and dolphins
Computer ScienceNon-blocking code, protocols, event-driven UIs
13Think about it

Reflection & conclusion

?1

Bats “see” with sound. What are the advantages and disadvantages of sound compared with light for detecting objects?

?2

Which surfaces were hard for your sensor to detect? Why?

?3

Where could a radar like yours be useful at school or at home?

Conclusion

You explored ultrasonic sensing, real-time measurement, servo control and interactive visualization. Combining the HC-SR04, a servo and Processing, you built a working radar inspired by real sonar technology — and used physics, trigonometry and programming together in one system.