Servo Motor Interfacing with ESP32

Overview of Servo Motor

Servo Motor
Servo Motor

 

A servo motor is an electric device used for precise control of angular rotation. It is used in applications that demand precise control over motion, like in the case of control of a robotic arm.

The rotation angle of the servo motor is controlled by applying a PWM signal to it.

By varying the width of the PWM signal, we can change the rotation angle and direction of the motor.

For more information about Servo Motor and how to use it, refer the topic Servo Motor in the sensors and modules section.

 

Servo Motor Connection with ESP32

Servo Motor Connection with ESP32
ESP32 interfacing with Servo Motor

 

 

Servo Motor Control using ESP32 Web Server

Controlling the position of a servo motor using a web server.

Here, we will be using Kevin Harrington’s ESP32Servo library.

Now let’s see how to install this library

Step 1.

            Open the Arduino IDE

 

Step 2.

            Click on Sketch ► Include Library ► Manage Libraries… as shown in fig below

 

 

Step 3.

            The library Manager window will pop up. Now enter ESP32Servo into the search box and click Install. (Install version 2.6.0 or higher.)

 

Now let’s take an example using this library to control the servo motor using a web server. Copy the below code and paste it into your Arduino IDE.

Before uploading the code make sure you have added your SSID and Password as follows.

const char* ssid = "*Your SSID*";         /*Enter Your SSID*/
const char* password = "*Your Password*"; /*Enter Your Password*/

Code for Servo Motor control using ESP32

#include <WiFi.h>
#include <ESP32Servo.h>

WiFiClient client;
WiFiServer server(80);
Servo MyServo;

static const int servoPin = 18;             /*Connect the servo motor to GPIO18*/

const char* ssid = "*Your SSID*";         /*Enter Your SSID*/
const char* password = "*Your Password*"; /*Enter Your Password*/

String _readString, AngleVlue;

void html_page(){
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();

client.println("<!DOCTYPE html>");
client.println("<html>");
client.println("<head>");
client.println("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"ico\" href=\"data:,\">");
client.println("<style>");
client.println("body {text-align:center;font-family:\"Roboto\";margin-left:auto;margin-right:auto;}");
client.println(".slidecontainer {width: 400px; margin:0 auto;}");
client.println(".slider {");
  client.println("-webkit-appearance: none;  width: 100%;  height: 25px; background: #d3d3d3;  outline: none;  ");
  client.println("opacity: 0.7;  -webkit-transition: .2s;  transition: opacity .2s;}");

client.println(".slider:hover { opacity: 1;}");

client.println(".slider::-webkit-slider-thumb {");
  client.println("-webkit-appearance: none;  appearance: none;  width: 25px; height: 25px;  background: #04AA6D;  cursor: pointer;}");

client.println(".slider::-moz-range-thumb {");
  client.println("width: 25px;  height: 25px; background: #04AA6D;  cursor: pointer;}");
client.println("</style>");

client.println("<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\"></script>");

client.println("</head><body>");
client.println("<h1>Servo Motor With ESP32</h1>");
client.println("<p>Drag the slider to change the servo motor angle.</p>");

client.println("<div class=\"slidecontainer\">");
  client.println("<input type=\"range\" min=\"0\" max=\"180\" value=\"150\" class=\"slider\" id=\"myRange\" onchange=\"servoMotor(this.value)\" value=\"+AngleVlue+\">");
  client.println("<p>Angle: <span id=\"demo\"></span>&deg</p>");
client.println("</div>");

client.println("<script>");
client.println("var slider = document.getElementById(\"myRange\");");
client.println("var output = document.getElementById(\"demo\");");
client.println("output.innerHTML = slider.value;");

client.println("slider.oninput = function() {slider.value = this.value; output.innerHTML = this.value;}");

  client.println("$.ajaxSetup({timeout:1000});");

  client.println("function servoMotor(angle) { ");
      client.println("$.get(\"/@position$\"+angle + \"*\");");
      client.println("{Connection: close};");
  client.println("}");

client.println("</script></body></html>");
}

void setup() {
  Serial.begin(115200);             /*Set the baud rate to 115200*/
  MyServo.attach(servoPin);
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {/*Wait while connecting to WiFi*/
    delay(100);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());       /*Print the local ip address on the serial window*/
  server.begin();                       /*Start Server*/
}

void loop(){
  client = server.available();
  if (client) {
    Serial.println("New Client Connected"); 
    String currentString = "";   
    while (client.connected()) {
      if (client.available()) { 
        char _readCharacter = client.read();      /*Read the Input data*/
        _readString += _readCharacter;
        if (_readCharacter == '\n') {             /*Read the Input data until newline comein*/
          if (currentString.length() == 0) {
            html_page();                          /*Call the HTML Page Function*/
            if(_readString.indexOf("GET /@position$")>=0) {
              AngleVlue = _readString.substring(_readString.indexOf('$')+1, _readString.indexOf('*'));  /*Parse the data between $ to * */
              MyServo.write(AngleVlue.toInt());   /*Convert the Updated string value to int and write on servo motor*/
              Serial.print("Servo Motor Position = ");
              Serial.println(AngleVlue);          /*Print the Updated Angle in Degree on Serial Monitor*/
            }
            client.println();
            break;                               /*Break the while loop*/
          }
          else {currentString = "";}
        }
        else if (_readCharacter != '\r') {currentString += _readCharacter;}
      }
    }

    _readString = ""; /*clear the string*/
    client.stop();    /*Close the Connection*/
    Serial.println("Client disconnected.");
  }
}

 

  • Now upload the code. (While uploading the code make sure your ESP32 board is in the boot mode.)
  • After uploading the code open the serial monitor and set the baud rate to 115200 then reset the ESP32 board and check the IP address as shown in the below image

 

 

Output on the webserver

  • Now open any mobile browser and type the IP address which is shown in the serial monitor and hit the enter button. 
  • If all are ok, then the web page will start the showing current temperature and humidity on the web server like in the below image.

Note: make sure your ESP32 and mobile are connected to the same router/server, if they are connected to the same router or server then only you will be able to visible the web page.

 

 

Let’s Understand the code.

To understand this code, please refer to the basics guide of “How to create the ESP32 Server”.

Once you get the basics of ESP32 server creation, it will be very simple to understand the code.

This code starts with important header files and libraries, In WiFi.h file contains all ESP32 WiFi related definitions, here we have used them for network connection purposes. 

ESP32Servo.h is used to control the servo motor using the ESP32 board.

#include <WiFi.h>
#include <ESP32Servo.h>

Let’s define HTTP port i.e., Port 80 as follows

WebServer server(80);

Set the GPIO pin of ESP32 for the Servo Motor.

staticconst int servoPin =18;             /*Connect the servo motor to GPIO18*/

create the object for the WiFiClient and Servo class

WiFiClient client;
Servo MyServo;

 

Setup Function

In the setup function, first set the baud rate to 115200.

Serial.begin(115200);             /*Set the baud rate to 115200*/

attach servopin i.e., GPIO 18 to the servo object.

MyServo.attach(servoPin);

Connect Wi-Fi to the given SSID and password.

WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {/*Wait while connecting to WiFi*/
  delay(100);
  Serial.print(".");
}

After successfully connecting to the server print the local IP address on the serial window.

Serial.print("Your Local IP address is: ");
Serial.println(WiFi.localIP());     /*Print the Local IP*/

Now start the server using server.begin() function.

server.begin();                    /*Start Server*/

 

Loop Function

In the loop function, we will read the client request and execute the program accordingly.

The ESP32 always listens to the incoming clients using server.available() function.

client = server.available()

When a request is received from a client, we’ll save the incoming data. 

The while loop that follows will be running as long as the client stays connected. 

while (client.connected())

Now read the client’s request and check the position of the slider and rotate the servo motor angle accordingly.

  if (client) {
    Serial.println("New Client Connected"); 
    String currentString = "";   
    while (client.connected()) {
      if (client.available()) { 
        char _readCharacter = client.read();      /*Read the Input data*/
        _readString += _readCharacter;
        if (_readCharacter == '\n') {             /*Read the Input data until newline comein*/
          if (currentString.length() == 0) {
           html_page();                         /*Call the HTML Page Function*/
            if(_readString.indexOf("GET /@position$")>=0) {
             AngleVlue = _readString.substring(_readString.indexOf('$')+1, _readString.indexOf('*'));  /*Parse the data between $ to * */
             MyServo.write(AngleVlue.toInt());   /*Convert the Updated string value to int and write on servo motor*/
              Serial.print("Servo Motor Position = ");
              Serial.println(AngleVlue);          /*Print the Updated Angle in Degree on Serial Monitor*/
            }
            client.println();
            break;                                /*Break the while loop*/
          }
          else {currentString = "";}
        }
        else if (_readCharacter != '\r') {currentString += _readCharacter;}
      }
    }

    _readString = ""; /*clear the string*/
    client.stop();    /*Close the Connection*/
    Serial.println("Client disconnected.");
  }

 

Let’s understand the html code step by step.

All html pages start with the <!DOCTYPE html> declaration, it is just information to the browser about what type of document is expected.

client.println("<!DOCTYPE HTML>");

The html tag is the container of the complete html page which represents on the top of the html code.

client.println("<html>");

Now here we are defining the style information for a web page using the <style> tag. Inside the style tag, we have defined the font name, size, color, test alignment, and slider style also.

client.println("<style>");
client.println("body {text-align:center;font-family:\"Roboto\";margin-left:auto;margin-right:auto;}");
client.println(".slidecontainer {width: 400px; margin:0 auto;}");
client.println(".slider {");
  client.println("-webkit-appearance: none;  width: 100%;  height: 25px; background: #d3d3d3;  outline: none;  ");
  client.println("opacity: 0.7;  -webkit-transition: .2s;  transition: opacity .2s;}");

client.println(".slider:hover { opacity: 1;}");

client.println(".slider::-webkit-slider-thumb {");
  client.println("-webkit-appearance: none;  appearance: none;  width: 25px; height: 25px;  background: #04AA6D;  cursor: pointer;}");

client.println(".slider::-moz-range-thumb {");
  client.println("width: 25px;  height: 25px;  background: #04AA6D;  cursor: pointer;}");
client.println("</style>");

Inside the body, we are defining the document body, in below we have used headings, and paragraphs if you want you can add images, hyperlinks, tables, lists, etc. also.

On the web page, we are displaying the heading of the page, and inside a paragraph, slider bar to change the Servo motor angle.

client.println("<body>");
client.println("<h2>DC Motor Control using ESP32</h2>");
client.println("<p>Click to Forward and Reverse the DC Motor</p>");

Here we have created custom range sliders with CSS and JavaScript inside the body.

client.println("<div class=\"slidecontainer\">");
  client.println("<input type=\"range\" min=\"0\" max=\"180\" value=\"150\" class=\"slider\" id=\"myRange\" onchange=\"servoMotor(this.value)\" value=\"+AngleVlue+\">");
  client.println("<p>Angle: <span id=\"demo\"></span>&deg</p>");
client.println("</div>");

Here we used the AJAX method to send the updated values to the server without refreshing the page. 

client.println("<script>");
client.println("var slider = document.getElementById(\"myRange\");");
client.println("var output = document.getElementById(\"demo\");");
client.println("output.innerHTML = slider.value;");

client.println("slider.oninput = function() {slider.value = this.value; output.innerHTML = this.value;}");

  client.println("$.ajaxSetup({timeout:1000});");

  client.println("function servoMotor(angle) { ");
      client.println("$.get(\"/@position$\"+angle + \"*\");");
      client.println("{Connection: close};");
  client.println("}");

client.println("</script></body></html>");

Components Used

Servo Motor MG995
Servo Motor MG995
1
ESP32 WROOM
WiFi Development Tools - 802.11 ESP32 General Development Kit, embeds ESP32-WROOM-32E, 4MB flash.
1

Downloads

ESP32_Servo_Control_by_webserver Download
Ad