1. Introduction
- In this tutorial, I will show you how to control a Servo motor via Arduino ESP32 Web Server.
4. Result
- In this tutorial, I will show you how to control a Servo motor via Arduino ESP32 Web Server.
Figure: Servo for this demo
- This servo:
+ Has 3 wires with colors: PWM, Vcc, Ground
+ Can rotate 180 degrees (90 degrees for each direction).
Figure: Pulse wave of trigger
- In order to control the rotation angle of servo we need to trigger pulses to Servo PWM pin. The pulses has pulse width between 0.6–2.4 ms and PWM signal period is 20 ms (50Hz). For example, if we trigger pulse with width is 0.6 ms then servo is at 0 degrees angle, 1.5 ms is 90 degrees angle and 2.4 ms is 180 degrees angle.
- We can use the map(angleDegrees, 0,180,600,2400) function to map the rotation angle to pulse width. This function will return the width of pulse in microseconds. Here 0 is minimum angle with pulse width 600 microseconds, 180 is maximum angle with pulse width 2400 microseconds.
2. Hardware
We connect:
[Servo PWM - ESP32 GPIO 12]
[Server VCC - ESP32 5V]
[Server GND - ESP32 GND]
Figure: Servo connect to ESP32
3. Software
3.1 Web server
You can refer Demo 12: How to turn the Arduino ESP32 into a Web Server
3.2 Servo
Create an Arduino project with code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | #include <WiFiClient.h> #include <ESP32WebServer.h> #include <WiFi.h> #include <ESPmDNS.h> /* change your ssid and password here */ const char* ssid = "Coffee Amy"; const char* password = "amy12345"; ESP32WebServer server(80); const int servoPin = 12; int oldAngle = 0; int PWM_WIDTH = 20000; /* this array contains the web will be responded to client it uses jquery for making GET request and processing slider UI control */ char res[900]= "<!DOCTYPE html>\ <html>\ <head>\ <meta charset='utf-8'>\ <H1>iotsharing.com Servo</H1>\ <link href='https://code.jquery.com/ui/1.10.4/themes/ui-lightness/jquery-ui.css' rel='stylesheet'>\ <script src='https://code.jquery.com/jquery-1.10.2.js'></script>\ <script src='https://code.jquery.com/ui/1.10.4/jquery-ui.js'></script>\ <script>\ $(function() {\ $('#sliVal').html('Angle: 0');\ $('#slider').slider({\ orientation:'vertical',value:0,min: 0,max: 180,step: 5\ });\ $('#slider').slider().bind({\ slidestop: function(e,ui){\ $('#res').css('background','red');\ $('#sliVal').html('Angle: '+ui.value);\ $.get('/ang?val=' + ui.value, function(d, s){\ $('#res').css('background','green');\ $('#res').html(s);\ }); \ }\ });\ });\ </script>\ </head>\ <body>\ <div id='slider'></div></br>\ <div id='sliVal'></div>\ <div id='res'></div>\ </body>\ </html>"; void handleRoot() { server.send(200, "text/html", res); } /* this function map from angle to pulse width */ int servoPulse(int angleDegrees) { int pulseWidth = map(angleDegrees, 0,180,600,2400); return pulseWidth; } /* this function check the rotation angle and trigger pulse accordingly*/ void servoGo(int oldAngle, int newAngle) { int pulseWidth; if(oldAngle == newAngle){ return; }else if(oldAngle < newAngle){ /* clockwise processing */ for (int i=oldAngle; i<=newAngle; i++){ /* convert angle to pulse width us*/ pulseWidth = servoPulse(i); /* trigger HIGH pulse */ digitalWrite(servoPin, HIGH); /* use delayMicroseconds to delay for pulseWidth */ delayMicroseconds(pulseWidth); /* trigger LOW pulse */ digitalWrite(servoPin, LOW); /* use delayMicroseconds to delay for rest time (20000 - pulseWidth) */ delayMicroseconds(PWM_WIDTH - pulseWidth); } }else if(oldAngle > newAngle){ /* anti-clockwise processing */ for (int i=oldAngle; i>=newAngle; i--){ pulseWidth = servoPulse(i); digitalWrite(servoPin, HIGH); delayMicroseconds(pulseWidth); digitalWrite(servoPin, LOW); delayMicroseconds(PWM_WIDTH - pulseWidth); } } } /* this callback will be invoked when get servo rotation request */ void handleServo() { //Serial.println(server.argName(0)); int newAngle = server.arg(0).toInt(); servoGo(oldAngle, newAngle); oldAngle = newAngle; server.send(200, "text/html", "ok"); } void handleNotFound(){ String message = "File Not Found\n\n"; server.send(404, "text/plain", message); } void setup(void){ Serial.begin(115200); WiFi.begin(ssid, password); Serial.println(""); // Wait for connection while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("Connected to "); Serial.println(ssid); Serial.print("IP address: "); Serial.println(WiFi.localIP()); if (MDNS.begin("esp32")) { Serial.println("MDNS responder started"); } server.on("/", handleRoot); server.on("/ang", handleServo); server.onNotFound(handleNotFound); server.begin(); pinMode(servoPin, OUTPUT); Serial.println("HTTP server started"); } void loop(void){ server.handleClient(); } |
Figure: ESP32 web server control servo
3 Comments