In this tutorial, we’re going to show you how to control servo motor with an ESP32 Web Server. Before we build the web server, we'll take a short look at ESP32 servo control.
Parts List
You will need the following items to proceed with this project:
You can use the preceding links to find all the parts for your projects at the best price!
Connecting the Servo Motor to the ESP32
Power, ground, and signal wires are present in servo motors. The signal wire is often yellow, orange, or white; the power wire is typically red; and the GND wire is typically black or brown.
Wire | Color |
Power | Red |
GND | Black, or brown |
Signal | Yellow, orange, or white |
You can power a small servo like the S0009 directly from the ESP32 while using it, as shown in the figure below.
However, you'll probably need to use an external power supply to power your servos if you're using many servos or a different type.
If you’re using a small servo like the S0009, you need to connect:
Note: Any ESP32 GPIO can produce a PWM signal; therefore, you may use any of them in this situation. However, as GPIOs 9, 10, and 11 are linked to the integrated SPI flash and are not intended for other purposes, we do not recommend using them.
Schematic
In our case, the signal wire will be connected to GPIO 13
. As a result, you may wire your servo motor by following the next schematic.
How to Control a Servo Motor?
Various angles, ranging from 0 to 180°, may be used to position the servo's shaft. Using a pulse width modulation (PWM) signal, servos are controlled. This implies that the position of the shaft will be determined by the PWM signal sent to the motor.
The ESP32's PWM capabilities may be used to operate the motor by simply sending a signal at 50 Hz with the right pulse width. Alternatively, you may use a library to greatly simplify this task.
Preparing the Arduino IDE
The ESP32 may be programmed using the Arduino IDE and its programming language, using an add-on for that platform. If you haven't already, prepare your Arduino IDE to work with the ESP32 by following one of the next tutorials.
- How to Install ESP32 Boards in Arduino IDE 2.0
- Install ESP32 Board in Arduino IDE in less than 1 minute
After making sure you have the ESP32 add-on installed, you can continue this tutorial.
Installing the ESP32_Arduino_Servo_Library
The ESP32 Arduino Servo Library makes it simpler to use your ESP32 to operate a servo motor using the Arduino IDE. Install the library in your Arduino IDE by following the next steps:
- Click here to download the ESP32_Arduino_Servo_Library. You should have a .zip folder in your Downloads folder.
- Unzip the .zip folder and you should get ESP32-Arduino-Servo-Library-Master folder.
- Rename your folder from
ESP32-Arduino-Servo-Library-Masterto ESP32_Arduino_Servo_Library. - Move the ESP32_Arduino_Servo_Library folder to your Arduino IDE installation libraries folder.
- Finally, re-open your Arduino IDE.
Testing an Example
Go to your Arduino IDE after installing the library. Go to File > Examples > ServoESP32 > Simple Servo after making sure the ESP32 board is chosen.
/*********
LEDEdit PRO
Complete project details at https://lededitpro.com
Written by BARRAGAN and modified by Scott Fitzgerald
*********/
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards
int pos = 0; // variable to store the servo position
void setup() {
myservo.attach(13); // attaches the servo on pin 13 to the servo object
}
void loop() {
for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
// in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}
Understanding the code
The servo rotates 180 degrees to one side and 180 degrees to the other in this sketch. See how it works below.
First, you need to include the Servo library:
#include <Servo.h>
Then, you need to create a servo object. In this case, it is called “myservo“.
Servo myservo;
setup()
You attach GPIO 13
to the servo object in the setup()
and initialize serial communication for debugging purposes.
void setup() {
myservo.attach(13);
}
loop()
The motor's shaft position is changed from 0 to 180 degrees in the loop()
function, and then back to 0 degrees again. You just need to use the write()
function of the servo
object to set the shaft to a certain position. You provide an integer number with the position in degrees as an input.
myservo.write(pos);
Testing the Sketch
On your ESP32, upload the code. After uploading the code, you should see the motor's shaft rotating to one side and then to the other.
Creating the ESP32 Web Server
Let's build the web server to control the servo now that you know how to do it with the ESP32. We'll build the following web server:
- Contains a slider from 0 to 180 that you can adjust to control the servo’s shaft position;
- The current slider value is automatically updated on the web page, as is the shaft position, without the need to refresh the web page. For this, we use AJAX to send HTTP requests to the ESP32 in the background.
- Refreshing the web page doesn’t change the slider value or the shaft position.
Creating the HTML Page
Let’s start by taking a look at the HTML text the ESP32 needs to send to your browser.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
<style>
body {
text-align: center;
font-family: "Trebuchet MS", Arial;
margin-left:auto;
margin-right:auto;
}
.slider {
width: 300px;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<h1>ESP32 with Servo</h1>
<p>Position: <span id="servoPos"></span></p>
<input type="range" min="0" max="180" class="slider" id="servoSlider" onchange="servo(this.value)"/>
<script>
var slider = document.getElementById("servoSlider");
var servoP = document.getElementById("servoPos");
servoP.innerHTML = slider.value;
slider.oninput = function() {
slider.value = this.value;
servoP.innerHTML = this.value;
}
$.ajaxSetup({timeout:1000});
function servo(pos) {
$.get("/?value=" + pos + "&");
{Connection: close};
}
</script>
</body>
</html>
Creating a Slider
This project involves building a slider for the HTML page. The <input>
tag is used in HTML to create sliders. The <input>
tag specifies a field in which the user may enter data.
A wide variety of input types are available. Use the “type” property together with the “range” value to define a slider. Using the “min” and “max” properties in a slider, you also need to define the minimum and maximum ranges.
<input type="range" min="0" max="180" class="slider" id="servoSlider" onchange="servo(this.value)"/>
You also need to define other attributes, like:
- the class to style the slider.
- the id to update the current position displayed on the web page.
- And finally, the onchange attribute calls the servo function to send an HTTP request to the ESP32 when the slider moves.
Adding JavaScript to the HTML File
Using the <script>
and </script>
tags, you will now need to add some JavaScript code to your HTML file. With the current web slider position, this snippet of code updates the web page:
var slider = document.getElementById("servoSlider");
var servoP = document.getElementById("servoPos");
servoP.innerHTML = slider.value;
slider.oninput = function() {
slider.value = this.value;
servoP.innerHTML = this.value;
}
And the next lines make an HTTP GET request to the ESP IP address in this specific URL path: /?value=[SLIDER_POSITION]&.
$.ajaxSetup({timeout:1000});
function servo(pos) {
$.get("/?value=" + pos + "&");
}
For example, when the slider is at 0, you make an HTTP GET request on the following URL:
http://192.168.1.135/?value=0&
And when the slider is at 180 degrees, you’ll have something as follows:
http://192.168.1.135/?value=180&
The servo motor may then be moved to the right position when the ESP32 receives the GET request and retrieves the value parameter from the URL.
Code
Now we must include the previous HTML text in the sketch and rotate the servo as needed. This next sketch does precisely that.
Note: As previously mentioned, you need to install the ESP32 add-on in your Arduino IDE. If you haven't previously, install the ESP32 board in the Arduino IDE using one of the following tutorials:
- How to Install ESP32 Boards in Arduino IDE 2.0
- Install ESP32 Board in Arduino IDE in less than 1 minute
But before you upload it, copy the following code into your Arduino IDE: Let's take a quick look at how it works first.
/*********
LEDEdit PRO
Complete project details at https://lededitpro.com
*********/
#include <WiFi.h>
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards
// GPIO the servo is attached to
static const int servoPin = 13;
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Set web server port number to 80
WiFiServer server(80);
// Variable to store the HTTP request
String header;
// Decode HTTP GET value
String valueString = String(5);
int pos1 = 0;
int pos2 = 0;
// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0;
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;
void setup() {
Serial.begin(115200);
myservo.attach(servoPin); // attaches the servo on the servoPin to the servo object
// Connect to Wi-Fi network with SSID and password
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Print local IP address and start web server
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
}
void loop(){
WiFiClient client = server.available(); // Listen for incoming clients
if (client) { // If a new client connects,
currentTime = millis();
previousTime = currentTime;
Serial.println("New Client."); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
currentTime = millis();
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// Display the HTML web page
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
// CSS to style the on/off buttons
// Feel free to change the background-color and font-size attributes to fit your preferences
client.println("<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial; margin-left:auto; margin-right:auto;}");
client.println(".slider { width: 300px; }</style>");
client.println("<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\"></script>");
// Web Page
client.println("</head><body><h1>ESP32 with Servo</h1>");
client.println("<p>Position: <span id=\"servoPos\"></span></p>");
client.println("<input type=\"range\" min=\"0\" max=\"180\" class=\"slider\" id=\"servoSlider\" onchange=\"servo(this.value)\" value=\""+valueString+"\"/>");
client.println("<script>var slider = document.getElementById(\"servoSlider\");");
client.println("var servoP = document.getElementById(\"servoPos\"); servoP.innerHTML = slider.value;");
client.println("slider.oninput = function() { slider.value = this.value; servoP.innerHTML = this.value; }");
client.println("$.ajaxSetup({timeout:1000}); function servo(pos) { ");
client.println("$.get(\"/?value=\" + pos + \"&\"); {Connection: close};}</script>");
client.println("</body></html>");
//GET /?value=180& HTTP/1.1
if(header.indexOf("GET /?value=")>=0) {
pos1 = header.indexOf('=');
pos2 = header.indexOf('&');
valueString = header.substring(pos1+1, pos2);
//Rotate the servo
myservo.write(valueString.toInt());
Serial.println(valueString);
}
// The HTTP response ends with another blank line
client.println();
// Break out of the while loop
break;
} else { // if you got a newline, then clear currentLine
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = "";
// Close the connection
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
}
How the Code Works
First, we include the Servo library, and create a servo object called myservo
.
#include <Servo.h>
Servo myservo; // create servo object to control a servo
We also create a variable to hold the GPIO number the servo is connected to. In this case, GPIO 13
.
const int servoPin = 13;
Do not forget that you need to modify the following two lines to include your network credentials.
// Replace with your network credentials const char* ssid = "";
const char* password = "";
To extract the slider position from the HTTP request, create a couple of variables.
// Decode HTTP GET value
String valueString = String(5);
int pos1 = 0;
int pos2 = 0;
setup()
The servo has to be attached to the GPIO it is connected to in setup()
using the myservo.attach()
function.
myservo.attach(servoPin); // attaches the servo on the servoPin to the servo object
loop()
To show the web page, the first part of the loop()
builds the web server and sends the HTML text. In this web server method, we use the same method.
The following part of the code retrieves the value from the HTTP request for the slider.
//GET /?value=180& HTTP/1.1 if(header.indexOf("GET /?value=")>=0) { pos1 = header.indexOf('='); pos2 = header.indexOf('&'); valueString = header.substring(pos1+1, pos2);
Make an HTTP request to the following URL, which contains the slider position between the = and & signs, when you move the slider:
http://your-esp-ip-address/?value=[SLIDER_POSITION]&
The slider position value is saved in the valueString
variable.
Then, using myservo.write()
and the valueString
variable as parameters, we set the servo to that specific position. We need to use the toInt()
method to change the valueString
variable from a string to an integer number, which is the data type that the write()
method accepts.
myservo.write(valueString.toInt());
Testing the Web Server
The code may now be uploaded to your ESP32. Ensure that the right board and COM port are chosen. Aside from that, don't forget to modify the code to include your network credentials.
Open the Serial Monitor with a 115200 baud rate after uploading the code.
Copy the ESP32 IP address that shows up on the Serial Monitor after pressing the ESP32 “Enable” button to restart the board.
You should be able to see the web page you previously produced if you open your browser and paste the ESP IP address. To control the servo motor, slide the slider.
When you move the slider, you can also see the HTTP requests that you're sending to the ESP32 in the Serial Monitor.
Experiment with your web server for a while to see if it’s working properly.
Conclusion
In conclusion, you have learned how to create a web server with a slider to control its position as well as how to control a servo motor using the ESP32.
This is just one example of servo motor control. A text input field, several buttons with predefined angles, or any other suitable input field may be used in place of a slider.
If you like ESP32, you may also like:
- Send Email from ESP32 via SMTP Server (Arduino IDE)
- ESP32 with WiFiMulti: Connect to the Strongest Wi-Fi Network
- Use ESP32 with VS Code & Platformio IDE to Upload Files to Filesystem (SPIFFS)
- ESP32 Web Server using SPI Flash File System (SPIFFS)
We hope you find this tutorial useful. Thanks for reading.