ESP32 Sonar Servo Motor Object Detection Project

Radar and sonar systems have played critical roles in a diverse array of applications, spanning from military and aerospace to autonomous vehicles and robotics. In this article, TechSparks explores a technical project that integrates the principles of sonar, servo motors, and the ESP32 microcontroller to craft an effective object detection system. This project finds applications in various domains, including robotics, security systems, and autonomous vehicles, offering versatile use cases like obstacle avoidance, object tracking, and the development of interactive installations.

Table of Contents

Project Principle

Sonar, which stands for Sound Navigation and Ranging, is a technique that uses sound waves to determine the distance and location of objects in its path. It operates based on the principle of echolocation, where an ultrasonic transducer emits a sound wave and measures the time it takes for the sound wave to bounce off an object and return. By calculating the time delay, we can determine the distance to the object.

A servo motor is a precise and highly controllable rotary actuator that can move to a specific angle or position. It works on the feedback control principle, where a control signal (in this case, from the ESP32) dictates the desired position, and the servo adjusts itself to reach that position. The servo’s feedback mechanism ensures accuracy and stability in its movements.

Wiring Diagram

To implement the sonar detection system using ESP32 and a servo motor, it is essential to correctly wire the components. Below is a basic wiring diagram:

  • Connect the VCC and GND pins of the ESP32 to a power supply or battery.
  • Link the trigger and echo pins of the sonar sensor to specific GPIO pins 12 and 32, respectively, on the ESP32.
  • Connect the servo motor to the ESP32’s PWM (Pulse Width Modulation) capable GPIO pins, such as pin 14.
  • Ensure that all components are grounded together for a common reference point.

ESP32 Sonar Servo Motor Wiring Diagram

Installing ESP32 Servo

Select the tools form the Arduino IDE >ESP32 dev module>board manager.

Choose to use Esp32Servo

In the search bar types Esp32Servo click on the install button and click install.

Code for Interfacing Sonar Sensor, Servo Motor, and ESP32 Control

				
					#include <ESP32Servo.h>
				
			

This line includes the ‘ESP32Servo’ library, enabling servo motor control with an ESP32 microcontroller.

				
					const int trigPin = 13;
const int echoPin = 12;
				
			

The trigger pin (trigPin) sends a signal from the ESP32 to initiate ultrasonic measurements, while the echo pin (echoPin) receives the echo signal.

				
					long duration;
int distance;
				
			

These variables store the ultrasonic pulse duration and the calculated object distance.

				
					Servo myServo;
				
			

This line creates an instance of the Servo class named myServo, which will control the servo motor.

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

In the setup() function:

  • pinMode(trigPin, OUTPUT); configures trigPin as an output for sending signals to the ultrasonic sensor.
  • pinMode(echoPin, INPUT); configures echoPin as an input for receiving signals from the ultrasonic sensor.
  • Serial.begin(9600); initializes serial communication with a baud rate of 9600, facilitating debugging information transmission to your computer.
  • myServo.attach(14); attaches the servo motor to GPIO pin 14 on the ESP32.
				
					void loop() {
  for (int i = 15; i <= 165; i++) {
    myServo.write(i);
    delay(30);
    distance = calculateDistance();
    Serial.print(i);
    Serial.print(",");
    Serial.print(distance);
    Serial.print(".");
  }
  for (int i = 165; i > 15; i--) {
    myServo.write(i);
    delay(30);
    distance = calculateDistance();
    Serial.print(i);
    Serial.print(",");
    Serial.print(distance);
    Serial.print(".");
  }
}
				
			

In the loop() function, a loop oscillates the servo motor between 15 and 165 degrees. For each degree:

  • myServo.write(i); sets the servo motor angle to the value represented by the variable i.
  • delay(30); introduces a 30-millisecond delay, allowing the servo motor to reach the desired angle.
  • distance = calculateDistance(); calls the calculateDistance() function to measure object distance using the ultrasonic sensor.
  • Serial.print(i);, Serial.print(“,”);, and Serial.print(“.”); send the current servo angle and measured distance information to the serial port for later analysis.

After reaching 165 degrees, the code reverses the rotation to cover the full range of motion.

				
					int calculateDistance() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = duration * 0.034 / 2;
  return distance;
}
				
			

The calculateDistance() function measures distance using the ultrasonic sensor:

  • digitalWrite(trigPin, LOW); sets the trigger pin to a low state.
  • delayMicroseconds(2); introduces a short delay.
  • digitalWrite(trigPin, HIGH); sets the trigger pin to a high state for 10 microseconds, emitting an ultrasonic pulse.
  • delayMicroseconds(10); introduces another short delay.
  • digitalWrite(trigPin, LOW); sets the trigger pin back to a low state.
  • duration = pulseIn(echoPin, HIGH); measures the echo signal’s return time and reads the echo pin. The pulseIn function returns the sound wave travel time in microseconds.
  • distance = duration * 0.034 / 2; calculates the distance in centimeters using the formula “distance = (duration * speed of sound) / 2” (assuming the speed of sound in air is approximately 0.034 cm/µs).

The calculated distance is returned.

Installing Processing-APP

For data visualization and advanced data processing, you can develop a Processing application that retrieves data from the ESP32 and presents it in a user-friendly interface.

Download the application from the official source using the provided link: https://processing.org/download.

After downloading, extract the executable file and proceed with the installation.

The application’s code provides a visual context for the software. It enables the sonar to rotate and provides a visual representation within the application, displaying the footprint as it scans its surroundings.

Radar Data Visualization Application Based on Processing

				
					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,"COM5", 9600); // starts the serial communication
 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("Hani's Experiments", 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(); 
				
			
Visual of the radar

Conclusion

In summary, we have successfully created a radar-inspired object detection system utilizing an ESP32 microcontroller, a sonar sensor, and a servo motor. This project’s completion involved gaining insights into sonar technology, configuring the hardware components, and crafting code to collect and analyze data. The result is a versatile tool with a wide range of real-world applications. Whether you are an enthusiastic hobbyist, a curious student, or a seasoned professional, this project offers a valuable opportunity to delve into the capabilities of contemporary technology and its potential across diverse domains.

More content you may be interested in

esp32 pinout
ESP32 Pinout Reference Guide

The ESP32 is a versatile microcontroller with extensive functionalities. Its pinout includes GPIO pins for digital, analog, and capacitive touch, PWM pins for precise control,

esp32 pwm project
ESP32 PWM Tutorial

This article delves into PWM on the ESP32, crucial for precise control in applications like LED dimming, motor regulation, and audio generation. It explains the

Scroll to Top