Index
Introduction
Servo motors are precise actuators that rotate to a specific angle between 0° and 180°.
Using the ESP32’s PWM (Pulse Width Modulation) capabilities, you can control servo position easily.
This is useful for robotics, camera gimbals, and automation systems.
Required Components
- ESP32 Board
- Servo Motor
- Jumper wires
- Breadboard
- 5V Power Supply, Battery
Pinout

Circuit Diagram / Wiring
- SERVO (5V) → ESP32 VIN an external 5V power supply
- SERVO (GND) → ESP32 GND
- SERVO (Signal) → ESP32 GPIO 13

Code / Programming
/*
Filename: ol_servo_sweep.ino
Description: ESP32 code to control a servo motor by sweeping it to 0°, 90°, and 180° positions with 1-second delay.
Author: www.oceanlabz.in
Modification: 1/4/2025
*/
#include <Servo.h> // Include Servo library
Servo myServo; // Create Servo object
void setup() {
myServo.attach(13); // Attach the servo to GPIO 13
}
void loop() {
myServo.write(0); // Move to 0°
delay(1000); // Wait for 1 second
myServo.write(90); // Move to 90°
delay(1000); // Wait for 1 second
myServo.write(180); // Move to 180°
delay(1000); // Wait for 1 second
}
Explanation
Servo.h
library simplifies PWM control of servos.attach(13)
links the servo signal to GPIO 13.write(angle)
rotates the servo to the desired position.
Testing & Troubleshooting
- If the servo jitters or doesn’t move, check power supply stability.
- Make sure the GPIO pin used supports PWM (most ESP32 GPIOs do).
- Always connect the GND of the servo and ESP32 together.
Project 1: Creating Ultrasonic Radar Scanner with Servo Control
Introduction
Smart Radar System Using Sonar and ESP32 is a real-time object detection project that combines an ultrasonic sensor, servo motor, and ESP32. It scans the surroundings, measures distances, and sends the data to a radar-style interface created using Processing. Ideal for IoT, robotics, and automation, it enables accurate detection and environmental mapping. Perfect for learning sensor control, wireless data handling, and visualization with the ESP32.
Required Components
- ESP32 Board
- SG90 servo motor
- Ultrasonic Sensor
- Jumper wires
- Breadboard (optional)
- Computer: With Processing IDE software installed.
Circuit Diagram / Wiring
- Ultrasonic Sensor with ESP32
- ULTRASONIC SENSOR VCC → 5V (ESP32)
- ULTRASONIC SENSOR GND → GND (ESP32)
- ULTRASONIC SENSOR TRIG → GPIO 5 (ESP32)
- ULTRASONIC SENSOR ECHO → GPIO 18 (ESP32)
- Servo motor with ESP32
- SERVO MOTOR VCC → VIN (ESP32) an external 5V power supply
- SERVO MOTOR GND → GND (ESP32)
- SERVO MOTOR PWM → GPIO 13 (ESP32)

Code / Programming
/*
Filename: ol_servo_ultrasonic_scan.ino
Description: ESP32 code to scan area using servo and ultrasonic sensor, printing angle and distance.
Author: www.oceanlabz.in
Modification: 1/4/2025
*/
#include <Servo.h>
// Define Ultrasonic Sensor pins
const int trigPin = 5; // GPIO for trigger pin
const int echoPin = 18; // GPIO for echo pin
long duration;
int distance;
Servo myServo; // Create a Servo object
void setup() {
Serial.begin(115200); // Start serial communication
pinMode(trigPin, OUTPUT); // Set trigger as output
pinMode(echoPin, INPUT); // Set echo as input
myServo.attach(13); // Attach servo to GPIO 13
}
void loop() {
// Sweep from 15 to 165 degrees
for (int i = 15; i <= 165; i++) {
myServo.write(i);
delay(30);
distance = calculateDistance();
Serial.print(i);
Serial.print(",");
Serial.print(distance);
Serial.print(".");
}
// Sweep back from 165 to 15 degrees
for (int i = 165; i > 15; i--) {
myServo.write(i);
delay(30);
distance = calculateDistance();
Serial.print(i);
Serial.print(",");
Serial.print(distance);
Serial.print(".");
}
}
// Function to calculate distance using ultrasonic sensor
int calculateDistance() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH, 30000); // 30ms timeout for ESP32
if (duration == 0) return -1; // Timeout case
distance = duration
Setup Processing Code
Install Processing Software:
Download and install Processing IDE.
Write or Paste Code:
Open Processing IDE and paste the radar visualization code provided.
- Adjust the
COM port
in the Processing code to match your ESP32 port. - Set the
baud rate
in Processing to the same value used in the Arduino IDE code (115200).
Run the Processing Code:
Click the Run button in Processing to start the radar visualization.
import processing.serial.*; // imports library for serial communication
import java.awt.event.KeyEvent; // imports library for reading the data from the serial port
import java.io.IOException;
Serial myPort; // defines Object Serial
// defubes variables
String angle="";
String distance="";
String data="";
String noObject;
float pixsDistance;
int iAngle, iDistance;
int index1=0;
int index2=0;
PFont orcFont;
void setup() {
size (1200, 700); // ***CHANGE THIS TO YOUR SCREEN RESOLUTION***
smooth();
myPort = new Serial(this,"COMX", 115200); // Replace COMX with your ESP32's port (e.g., "COM5")
myPort.bufferUntil('.'); // reads the data from the serial port up to the character '.'. So actually it reads this: angle,distance.
}
void draw() {
fill(98,245,31);
// simulating motion blur and slow fade of the moving line
noStroke();
fill(0,4);
rect(0, 0, width, height-height*0.065);
fill(98,245,31); // green color
// calls the functions for drawing the radar
drawRadar();
drawLine();
drawObject();
drawText();
}
void serialEvent (Serial myPort) { // starts reading data from the Serial Port
// reads the data from the Serial Port up to the character '.' and puts it into the String variable "data".
data = myPort.readStringUntil('.');
data = data.substring(0,data.length()-1);
index1 = data.indexOf(","); // find the character ',' and puts it into the variable "index1"
angle= data.substring(0, index1); // read the data from position "0" to position of the variable index1 or thats the value of the angle the Arduino Board sent into the Serial Port
distance= data.substring(index1+1, data.length()); // read the data from position "index1" to the end of the data pr thats the value of the distance
// converts the String variables into Integer
iAngle = int(angle);
iDistance = int(distance);
}
void drawRadar() {
pushMatrix();
translate(width/2,height-height*0.074); // moves the starting coordinats to new location
noFill();
strokeWeight(2);
stroke(98,245,31);
// draws the arc lines
arc(0,0,(width-width*0.0625),(width-width*0.0625),PI,TWO_PI);
arc(0,0,(width-width*0.27),(width-width*0.27),PI,TWO_PI);
arc(0,0,(width-width*0.479),(width-width*0.479),PI,TWO_PI);
arc(0,0,(width-width*0.687),(width-width*0.687),PI,TWO_PI);
// draws the angle lines
line(-width/2,0,width/2,0);
line(0,0,(-width/2)*cos(radians(30)),(-width/2)*sin(radians(30)));
line(0,0,(-width/2)*cos(radians(60)),(-width/2)*sin(radians(60)));
line(0,0,(-width/2)*cos(radians(90)),(-width/2)*sin(radians(90)));
line(0,0,(-width/2)*cos(radians(120)),(-width/2)*sin(radians(120)));
line(0,0,(-width/2)*cos(radians(150)),(-width/2)*sin(radians(150)));
line((-width/2)*cos(radians(30)),0,width/2,0);
popMatrix();
}
void drawObject() {
pushMatrix();
translate(width/2,height-height*0.074); // moves the starting coordinats to new location
strokeWeight(9);
stroke(255,10,10); // red color
pixsDistance = iDistance*((height-height*0.1666)*0.025); // covers the distance from the sensor from cm to pixels
// limiting the range to 40 cms
if(iDistance<40){
// draws the object according to the angle and the distance
line(pixsDistance*cos(radians(iAngle)),-pixsDistance*sin(radians(iAngle)),(width-width*0.505)*cos(radians(iAngle)),-(width-width*0.505)*sin(radians(iAngle)));
}
popMatrix();
}
void drawLine() {
pushMatrix();
strokeWeight(9);
stroke(30,250,60);
translate(width/2,height-height*0.074); // moves the starting coordinats to new location
line(0,0,(height-height*0.12)*cos(radians(iAngle)),-(height-height*0.12)*sin(radians(iAngle))); // draws the line according to the angle
popMatrix();
}
void drawText() { // draws the texts on the screen
pushMatrix();
if(iDistance>40) {
noObject = "Out of Range";
}
else {
noObject = "In Range";
}
fill(0,0,0);
noStroke();
rect(0, height-height*0.0648, width, height);
fill(98,245,31);
textSize(25);
text("10cm",width-width*0.3854,height-height*0.0833);
text("20cm",width-width*0.281,height-height*0.0833);
text("30cm",width-width*0.177,height-height*0.0833);
text("40cm",width-width*0.0729,height-height*0.0833);
textSize(40);
text("OceanLabz", width-width*0.875, height-height*0.0277);
text("Angle: " + iAngle +" °", width-width*0.48, height-height*0.0277);
text("Distance: ", width-width*0.26, height-height*0.0277);
if(iDistance<40) {
text(" " + iDistance +" cm", width-width*0.225, height-height*0.0277);
}
textSize(25);
fill(98,245,60);
translate((width-width*0.4994)+width/2*cos(radians(30)),(height-height*0.0907)-width/2*sin(radians(30)));
rotate(-radians(-60));
text("30°",0,0);
resetMatrix();
translate((width-width*0.503)+width/2*cos(radians(60)),(height-height*0.0888)-width/2*sin(radians(60)));
rotate(-radians(-30));
text("60°",0,0);
resetMatrix();
translate((width-width*0.507)+width/2*cos(radians(90)),(height-height*0.0833)-width/2*sin(radians(90)));
rotate(radians(0));
text("90°",0,0);
resetMatrix();
translate(width-width*0.513+width/2*cos(radians(120)),(height-height*0.07129)-width/2*sin(radians(120)));
rotate(radians(-30));
text("120°",0,0);
resetMatrix();
translate((width-width*0.5104)+width/2*cos(radians(150)),(height-height*0.0574)-width/2*sin(radians(150)));
rotate(radians(-60));
text("150°",0,0);
popMatrix();
}
Explanation
- Servo Motor Control: The servo motor rotates between 15° and 165° to scan the environment.
- Distance Measurement: The ultrasonic sensor sends a pulse, and the time taken for the echo to return is used to calculate distance.
- Data Output: The degree and corresponding distance values are printed to the Serial Monitor for each position of the servo motor.
- Looping Process: The servo sweeps back and forth, continuously measuring distance at each angle and sending the data for processing.