In this tutorial to create a project where you control a servo motor angle from 0 to 180 degrees using a web interface with an image that rotates based on mouse clicks, you’ll use WebSocket communication to send angle coordinates to the ESP32, which will then adjust the servo motor accordingly. Below is a detailed guide to help you build this project.
Components Required
ESP32 Development Board
Servo Motor SG90
Power Supply (e.g., 5V battery or external power adapter)
Breadboard and Jumper Wires
Circuit Diagram
Setup Arduino IDE for ESP32
Install the ESP32 Board Package:
Open Arduino IDE.
Go to File > Preferences.
Add the following URL to the "Additional Board Manager URLs" field: https://dl.espressif.com/dl/package_esp32_index.json.
Go to Tools > Board > Boards Manager, search for ESP32, and install it.
2. Connect the Servo Motor
Wiring:
Connect the servo’s power (red) and ground (black/brown) wires to the 5V and GND pins on the ESP32.
Connect the signal (yellow/orange) wire to a PWM-capable GPIO pin on the ESP32 (e.g., GPIO 19).
Power Consideration:
Ensure the servo is adequately powered. Use an external power supply if the servo requires more current than the ESP32 can provide.
3. Install Required Libraries
Install Servo Library:
Open Arduino IDE, go to Sketch -> Include Library -> Manage Libraries, search for Servo, and install it.
Install WebSocket Library:
After installed the libraries, restart your Arduino IDE.
4. Write the ESP32 Code
Here’s the code to handle WebSocket communication and control the servo:
#include <Arduino.h>
#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
AsyncWebServer server(80);
#include <ESP32Servo.h>
#include <WiFi.h>
#include <WebSocketsServer.h>
#include "index.h"
#define SERVO_PIN 19
Servo servo;
const char* ssid = "TPLink";
const char* password = "95001121379884265554";
WebSocketsServer webSocket = WebSocketsServer(81);
void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) {
switch (type) {
case WStype_DISCONNECTED:
Serial.printf("[%u] Disconnected!\n", num);
break;
case WStype_CONNECTED:
{
IPAddress ip = webSocket.remoteIP(num);
Serial.printf("[%u] Connected from %d.%d.%d.%d\n", num, ip[0], ip[1], ip[2], ip[3]);
}
break;
case WStype_TEXT:
//Serial.printf("[%u] Received text: %s\n", num, payload);
String angle = String((char*)payload);
int angle_value = angle.toInt();
Serial.println(angle_value);
servo.write(angle_value);
break;
}
}
void setup() {
Serial.begin(9600);
servo.attach(SERVO_PIN); // attaches the servo on ESP32 pin
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.printf("WiFi Failed!\n");
return;
}
Serial.println("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
// Initialize WebSocket server
webSocket.begin();
webSocket.onEvent(webSocketEvent);
// Serve a basic HTML page with JavaScript to create the WebSocket connection
server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) {
Serial.println("Web Server: received a web page request");
String html = HTML_CONTENT; // Use the HTML content from the index.h file
request->send(200, "text/html", html);
});
server.begin();
}
void loop() {
webSocket.loop();
}
5. Create the Web Interface
Here’s the HTML for the web interface and Base64 for image data url. This will send the angle coordinates to the ESP32 when you click on the image:
Base 64
https://www.base64-image.de/ to convert the Image to Base64 online and use the result string as data URI, img src, CSS background-url, and others. Sometimes you have to send or output an image within a text document (for example, HTML, CSS, JSON, XML), but you cannot do this because binary characters will damage the syntax of the text document. To prevent this, for example, you can encode image to Base64 and embed it using the data URI.
The Allowed image types are JPG, PNG, GIF, WebP, BMP and SVG and allowed image 1mb size.
To embed a Base64-encoded image in HTML, use the data URI scheme in the src attribute of the <img> tag. Here's an example:
<!DOCTYPE html>
<html>
<head>
<title>Base64 Image Example</title>
</head>
<body>
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgAAAAASUVORK5CYII=" alt="Base64 Image">
</body>
</html>
.
Here the index.h file
const char *HTML_CONTENT = R"=====(
<!DOCTYPE html>
<html>
<head>
<title>ESP32 Websocket Controlled Servo Motor</title>
<meta name="viewport" content="width=device-width, initial-scale=0.7">
<style>
body { text-align: center; }
canvas { background-color: #ffffff; }
</style>
<script>
var canvas_width = 401, canvas_height = 466;
var pivot_x = 200, pivot_y = 200;
var bracket_radius = 160, bracket_angle = 0;
var bracket_img = new Image();
var click_state = 0;
var last_angle = 0;
var mouse_xyra = {x:0, y:0, r:0.0, a:0.0};
var ws;
bracket_img.src = " data:image/png;base64,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";
function init()
{
var servo = document.getElementById("servo");
servo.width = canvas_width;
servo.height = canvas_height;
servo.style.backgroundImage = "url(' data:image/png;base64,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iYi8RCISEZboSEQElqhKRCSWqEhEBJaoSkQklqhIRASWqEpEJDdZovWziGJEfz7yJSLSEolIRFiiIxERWKIqEZFYoiIREViiKhGRWKIiERFYoioRETmxUCMiIicWakREYomKRERgiapERGKJikREYImqRERiiYpERGCJqkREYomKRERgiapERGKJikREYImqRERiiYpERGCJqkREYomKRERgiapERGKJikREYImqRERiiYpERGCJqkREYomKRPSbvTtmjSKKwjA84+6GZSdZAkLUam3VysZ2OwuLgBYWQbRJJf7/2jG7FgnnwMlekuY+z/yGl2+4MHNJWKIqEZGxREUiImGJqkRExhIViYiEJaoSERlLVCQiEpaoSkRkLFGRiEhYoioRkbFERSIiYYmqRESDhogOthcv1yMi4vERrab5EZGIsER3RETCElWJiIwlKhIRCUtUJSIylqhIRCQsUZWIaNC4RNPFdu5pJInozSGi9yIiWqJ/WyQiEXF6RJMlEhGNr3OWSES0HixYIhFhif4TEQlLVCUico64S0RE7CkjWi+m2WI9R7R9cT7ywOroYUSjiDonIhEhooyICImoTkSERFQnIkIiqhMRIRHViYiQiOpEREhEdc8V0f7200DPRNQc0ZWIOiei9ohuPg/0TETNEb26+T7QMxE1R3T29udAz0TUGtHsw0DPRNQc0fLq90DPRNQe0f7HQM9EdHJEy6NRRJ0TkYgQUUJExERUJiJiIioTETERlYmImIjKRERMRGUiIiaiMhERE1GZiIiJqExExERUJiJiIioTETERlYmImIjKRERMRGUiokHrJV/ni+3rryOFj/KWs3ci6ty9iKaViERE88XHIhIRluhARGQsUZGISFiiKhGRsURFIiJhiapExDNZXu4s0WkRbTabcbnb7b7tbwd6NkdkidoiuhZR5yxRc0S/Lv2Lu2+W6PSIzo4RXbsVom+WqGWJPt69zv35MtAzS9S8RH/Zu3fdJoIwDMNjjx3ZMgdBgFAAcmtR0XAJSFC6SyQsOjrM4f4lnNiWMJ5R/mSSNPM86dK/+ta72p3z758TPbNEDUt08uEqop+Jrh1ENPYqxC1uLJz/SHTtIKKtWZ6+ffxswH+GeznnyYt/z2xNdO0womEeikhEWKIdEVF0vxENL/9EJCIs0ZaIqLBEUSKizBKFiYgKSxQlIho0L9H0VETViHIeHkT09Guia8dLJCIRYYm2RESFJYoSEWWWKExEVFiiKBFRZonCRESFJYoSEQ3almj8KE89bD32ZCNvvMmv8+ylh63Ul0hEIsISXRERNZYoSERUWKIoEVFjiYJERIUlihIRZSIKExFl9xnRdGc8nmUPW6+PaPMvESEiESGiOhFRJqIwEVEmojARUSaiMBFRJqIwEVEmojAR8UBGr0ZHEeWpiAomk0m+tD/ka7Bztkh0TUTNEQ2Wia6JqDmixfLbx0THRHQHEa2cwd81ETVHNJqvfyU6JqL230Tz9e9Ex0TUHtGFiPomovbLuYuViLq2edgqottFtH8pbzRfvU90TEQiQkQVIqJMRGEiokxEYSKiTERhIqJMRGEiokxEYSKiQevHG2fP8+m7AeGI1iLqmoiaIzoRUeeOP2gvohtGdOZyrnOW6C6W6E+iY5aoOaKFy7nOWaLmiJbL1SrRMUvUfndu+eVTomOWqP3Ggq/9dM4SNUc08PHGzlkiEWGJakREmSUKExEVlihKRJRZojARUWGJokREmSUKExEVXsqLeoCIHPKFiESEiOpERJmIwkREmYjCRESZiMJERJmI/rJ3N61NBAEcxncyL9lkk5Si7sSm7aZWxa3FWBBFPHjwXMSAKLEWD73Yi2i/PzjpFinNTJmytZd5fpBL7g//zb5koxER/IgoGhHBj4iiERH8iCgaEcGPiKIREfyIKBoRwY+IohER/IgoGhHBj4iiERH8iCgaEaGFtg/l6YKIPEaOdDblWBY8lAciIiL8v/9YICIiAkvUICIEsESxiAh+LFE0IkIASxSLiODHEkUjItyNyrNEA9kbEtGK8Wg07DieiH5kSFi1skREdMOI7Pz4V4aEsUStIzL18Z8MCWOJWkdUz3kFf9pYotYRzafHRJQ0lqj9EhFR4lii1hGZORGljSW6hbNznFhIm+eOhUL2elxsXTW8cDki5QiWKHFqZYmIiIjAEp0jIgSwRLGICCEsUSQiQgBLFIuIEMISRSIiBLBEsYgILbRfoi0utsZHpKbPjzMkbHWJiOimEc3PeJ4oaSxR+4jU6e8MCWOJWkck7BH3ziWNJWodkSmJKG0sUeuIbHnE4VzSWKLWEZXl6c8MCWOJ2kdkTzk7lzRVKlH1q8sv+eq6iEafBK5Y11pKqfVDqbtNRMIxxtYnXCdKGhHdRkT8JkoaERERiCiAiOBHRNGICH5EFI2I4EdE0YgIfkR0A5zixp2YW/VZVcLM9jfkha77cLF1VZ7nenivI3ujjbyJyPRVVamyPvmaIWGqVEapvpk9un8pohERBSIaLiMan0dkXUVEhCyzZS1cRLbe/XJx79wyIm778dA6l06nJ9elXEZkjftWVRzOpU6U9UQJ20TUWEY0IiLvb6JuV3Y2t6SL6M2esUYJ01dGLYgoaYvaTFTfRXS4zRJd722udXeriagY7MxqY4UyRhmx4AbUpJ0tyolyFU2eHMpGE9GGwBU7LiJ5vkS5LB7mr75P1kwtjDBm+iFDwr6dvN8T6sDax7N/SzSQo3v3Ba54uaMfNBENZVHo3cPaRaRcRHbKdaKkvT5yEVWVXVvbk40moo8CV+y/0A+GchnRePC02Nhe1M/W6toYU055PDxtUyFMXyll7HqupdSDQUcOZJfDuRX76+N8oLtuhQq59G5WVsL0D+pS8OeNaSMiIgIR+RERAogoFhEhgIhiERECiCgWESGAiGIREQKIKBYR4a5MlTDGCHEekZbafaQkomsicvQSEYGIiAhEdC0iQgARxSIiBBBRLCJCABHFIiIEEFEsIkIAEf1l725SnIqiKIzycupVQn5KqiMqiA5AKAR7Ov9xmWhLzIYNRdKptebwde7mcloiIrhpRMfjzJzm8PEgov/9eP50Kei0m8PZ7H69vFse9g97Eb15IhIRIrpORAQiaomIQEQtERGIqCUiAhG1REQgopaIiG45ts7MRkQiQkR/iIhARC0REYioJSICEbVERCCilogIRNQSEYGIWiIiuEdE21m3braKCBGJiOtE1BIRgYhaIiIQUUtEBCJqiYhARC0REYioJSKSe4ytIhIRIloWERGIqCUiAhG1REQgopaICETUEhGBiFoiIhBRS0RExtaOiAhE1BIRgYhaIiIQUUtEBCJqiYhARC0REYioJSICEbVERCCilogIRNQSEYGIWiIiEFFLRAQiaomIQEQtERGIqCUiAhG1RERw24jWWdf1aWYc+YoRbUSEiESEiCoiIhBRS0QEImqJiEBELRERiKglIgIRtUREcIOILg39jWjmMDOn2cx2XRARIhIRwe0jGhGJiNdE9CQiEfHKiD57WBARIloWERHcIaIRkYgQ0ZmIuJevj/98yluPx9NsRHTFt+cPu+O6nUtBFz9f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')";
servo.style.backgroundPosition = "center";
servo.style.backgroundSize = "contain";
servo.addEventListener("touchstart", mouse_down);
servo.addEventListener("touchend", mouse_up);
servo.addEventListener("touchmove", mouse_move);
servo.addEventListener("mousedown", mouse_down);
servo.addEventListener("mouseup", mouse_up);
servo.addEventListener("mousemove", mouse_move);
var ctx = servo.getContext("2d");
ctx.translate(pivot_x, pivot_y);
rotate_bracket(0);
ws = new WebSocket("ws://" + window.location.host + ":81");
document.getElementById("ws_state").innerHTML = "CONNECTING";
ws.onopen = function(){ document.getElementById("ws_state").innerHTML = "Connected" };
ws.onclose = function(){ document.getElementById("ws_state").innerHTML = "Closed"};
ws.onerror = function(){ alert("websocket error " + this.url) };
ws.onmessage = ws_onmessage;
}
function ws_onmessage(e_msg)
{
e_msg = e_msg || window.event; // MessageEvent
alert("msg : " + e_msg.data);
}
function rotate_bracket(angle)
{
var servo = document.getElementById("servo");
var ctx = servo.getContext("2d");
ctx.clearRect(-pivot_x, -pivot_y, canvas_width, canvas_height);
ctx.rotate(angle / 180 * Math.PI);
ctx.drawImage(bracket_img, -pivot_x, -pivot_y);
ctx.rotate(-angle / 180 * Math.PI);
}
function check_range_xyra(event, mouse_xyra)
{
var x, y, r, a, rc_x, rc_y, radian;
var min_r, max_r, width;
if(event.touches)
{
var touches = event.touches;
x = (touches[0].pageX - touches[0].target.offsetLeft) - pivot_x;
y = pivot_y - (touches[0].pageY - touches[0].target.offsetTop);
min_r = 60;
max_r = pivot_x;
width = 40;
}
else
{
x = event.offsetX - pivot_x;
y = pivot_y - event.offsetY;
min_r = 60;
max_r = bracket_radius;
width = 20;
}
/* cartesian to polar coordinate conversion */
r = Math.sqrt(x * x + y * y);
a = Math.atan2(y, x);
mouse_xyra.x = x;
mouse_xyra.y = y;
mouse_xyra.r = r;
mouse_xyra.a = a;
radian = bracket_angle / 180 * Math.PI;
/* rotate coordinate */
rc_x = x * Math.cos(radian) - y * Math.sin(radian);
rc_y = x * Math.sin(radian) + y * Math.cos(radian);
if((r < min_r) || (r > max_r))
return false;
if((rc_y < -width) || (rc_y > width))
return false;
return true;
}
function mouse_down()
{
if(event.touches && (event.touches.length > 1))
click_state = event.touches.length;
if(click_state > 1)
return;
if(check_range_xyra(event, mouse_xyra))
{
click_state = 1;
last_angle = mouse_xyra.a / Math.PI * 180.0;
}
}
function mouse_up()
{
click_state = 0;
}
function mouse_move()
{
var angle;
if(event.touches && (event.touches.length > 1))
click_state = event.touches.length;
if(click_state > 1)
return;
if(!click_state)
return;
if(!check_range_xyra(event, mouse_xyra))
{
click_state = 0;
return;
}
angle = mouse_xyra.a / Math.PI * 180.0;
if((Math.abs(angle) > 90) && (angle * last_angle < 0))
{
if(last_angle > 0)
last_angle = -180;
else
last_angle = 180;
}
bracket_angle += (last_angle - angle);
last_angle = angle;
if(bracket_angle > 90)
bracket_angle = 90;
if(bracket_angle < -90)
bracket_angle = -90;
rotate_bracket(bracket_angle);
if(ws.readyState == 1)
ws.send(Math.floor(90 - bracket_angle) + "\r\n");
debug = document.getElementById("debug");
debug.innerHTML = Math.floor(90 - bracket_angle);
event.preventDefault();
}
window.onload = init;
</script>
</head>
<body>
<h2>
ESP32 Web Image Controlled Servo Motor<br>
<canvas id="servo"></canvas>
<p>
WebSocket : <span id="ws_state" style="color:#248580">null</span><br>
Angle : <span id="debug" style="color:Red">90</span>
</p>
</h2>
</body>
</html>
)=====";
6. Upload and Test
Upload the Code:
Connect your ESP32 to your computer, select the correct board and port in the Arduino IDE, and upload the code.
Access the Web Interface:
Open the Serial Monitor to get the ESP32's IP address. Enter this IP address into your web browser to access the web interface.
Test and Debug:
Click on the image on your web interface. The servo should move according to the horizontal position of the click, translating it into an angle between 0 and 180 degrees.
If the servo does not respond as expected, check your wiring, ensure the web interface is properly sending the angle, and verify WebSocket communication in the browser’s developer tools.
Demo:
Conclusion
With this setup, you can control a servo motor's angle using mouse clicks on an image rotate in a web interface. The ESP32 receives angle data via WebSocket and adjusts the servo position accordingly. Customize the image and refine the code as needed to suit your project’s requirements!
Comments