ESP32 - Controla Servo Motor pela Web

Este tutorial ensina como usar o ESP32 para controlar um servo motor pela web, a partir de um navegador no seu celular ou PC. Vamos usar o WebSocket para controlar o servo motor de forma suave e dinâmica por meio de uma interface web gráfica.

O vídeo abaixo é uma demonstração:

Por que usar o WebSocket? Veja a ideia:

Vamos começar!

Sobre o Servo Motor e o WebSocket

Temos tutoriais específicos sobre servo motor e WebSocket. Cada tutorial traz informações detalhadas e instruções passo a passo sobre a pinagem do hardware, o princípio de funcionamento, a ligação com o ESP32, o código do ESP32... Saiba mais nos links a seguir:

Como Funciona

O código do ESP32 cria um servidor web e também um servidor WebSocket. Veja como funciona:

  • Quando você digita o endereço IP do ESP32 em um navegador, ele solicita ao ESP32 a página web (interface de usuário).
  • O servidor web do ESP32 responde enviando o conteúdo da página (HTML, CSS, JavaScript).
  • Em seguida, o navegador exibe a página web.
  • O código JavaScript da página estabelece uma conexão WebSocket com o servidor WebSocket do ESP32.
  • Depois que a conexão WebSocket é estabelecida, se você girar o botão na página web, o código JavaScript envia o valor do ângulo ao ESP32 discretamente, em segundo plano, por essa conexão WebSocket.
  • O servidor WebSocket do ESP32, ao receber o valor do ângulo, controla o servo motor de acordo com ele.

Resumindo, a conexão WebSocket permite o controle suave e em tempo real do ângulo do servo motor.

Diagrama de Ligação entre o Servo Motor e o ESP32

ESP32 Servo Motor Diagrama de Ligação

This image is created using Fritzing. Click to enlarge image

Se você não sabe como alimentar o ESP32 e outros componentes, veja as instruções no tutorial a seguir: Como alimentar o ESP32.

Para simplificar, o diagrama de ligação acima serve para testes ou aprendizado e para servo motores de baixo torque. Na prática, recomendamos fortemente usar uma fonte de alimentação externa para o servo motor. O diagrama de ligação abaixo mostra como conectar o servo motor a uma fonte de alimentação externa.

ESP32 servo motor diagrama de ligação com fonte de alimentação externa

This image is created using Fritzing. Click to enlarge image

A imagem abaixo mostra a ligação real entre o servo motor e o ESP32.

ESP32 servo motor diagrama de ligação da alimentação

Código ESP32

O conteúdo da página web (HTML, CSS, JavaScript) fica armazenado separadamente em um arquivo index.h. Assim, teremos dois arquivos de código no Arduino IDE:

  • Um arquivo .ino, que é o código do ESP32, o qual cria um servidor web e um servidor WebSocket e controla o servo motor
  • Um arquivo .h, que contém o conteúdo da página web.

Passos Rápidos

  • Se esta é a primeira vez que você usa o ESP32, veja como configurar o ambiente do ESP32 no Arduino IDE.
  • Faça a ligação como na imagem acima.
  • Conecte a placa ESP32 ao seu PC com um cabo micro USB
  • Abra o Arduino IDE no seu PC.
  • Selecione a placa ESP32 correta (por exemplo, ESP32 Dev Module) e a porta COM.
  • Abra o Library Manager clicando no ícone Library Manager na barra de navegação à esquerda do Arduino IDE.
  • Pesquise “DIYables ESP32 WebServer” e encontre a biblioteca Web Server criada pela DIYables.
  • Clique no botão Install para instalar a biblioteca Web Server.
Biblioteca ESP32 Web Server
  • Digite ESP32Servo na caixa de pesquisa e procure a biblioteca de servo de Kevin Harrington,John K. Bennett.
  • Clique no botão Install para instalar a biblioteca de servo motor para ESP32.
Biblioteca de servo motor ESP32
  • No Arduino IDE, crie um novo sketch. Dê um nome a ele, por exemplo, newbiely.com.ino
  • Copie o código abaixo e abra no Arduino IDE
/* * Este código de ESP32 foi desenvolvido por pt.newbiely.com * Este código de ESP32 é disponibilizado ao público sem nenhuma restrição. * Para tutoriais completos e diagramas de ligação, visite: * https://pt.newbiely.com/tutorials/esp32/esp32-controls-servo-motor-via-web */ #include <ESP32Servo.h> #include <DIYables_ESP32_WebServer.h> #include "index.h" #define SERVO_PIN 26 // ESP32 pin GPIO26 connected to servo motor Servo servo; // WiFi credentials const char WIFI_SSID[] = "YOUR_WIFI_SSID"; const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD"; // Create web server instance DIYables_ESP32_WebServer server; DIYables_ESP32_WebSocket* webSocket; // Web Page handlers void handleHome(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { // HTML_CONTENT from the index.h file server.sendResponse(client, HTML_CONTENT); } // WebSocket event handlers void onWebSocketOpen(net::WebSocket& ws) { Serial.println("New WebSocket connection"); // Send welcome message const char welcome[] = "Connected to ESP32 WebSocket Server!"; } void onWebSocketMessage(net::WebSocket& ws, const net::WebSocket::DataType dataType, const char* message, uint16_t length) { String angle = String(message); int angle_value = angle.toInt(); Serial.println(angle_value); servo.write(angle_value); } void onWebSocketClose(net::WebSocket& ws, const net::WebSocket::CloseCode code, const char* reason, uint16_t length) { Serial.println("WebSocket client disconnected"); } void setup() { Serial.begin(9600); delay(1000); servo.attach(SERVO_PIN); // attaches the servo on ESP32 pin Serial.println("ESP32 Web Server and WebSocket Server"); // Configure web server routes server.addRoute("/", handleHome); // Start web server with WiFi connection server.begin(WIFI_SSID, WIFI_PASSWORD); // Enable WebSocket functionality webSocket = server.enableWebSocket(81); if (webSocket != nullptr) { // Set up WebSocket event handlers webSocket->onOpen(onWebSocketOpen); webSocket->onMessage(onWebSocketMessage); webSocket->onClose(onWebSocketClose); } else { Serial.println("Failed to start WebSocket server"); } } void loop() { // Then handle HTTP requests server.handleClient(); // Handle WebSocket server.handleWebSocket(); }
  • Modifique as informações de WiFi (SSID e senha) no código para corresponder às credenciais da sua rede.
  • Crie o arquivo index.h no Arduino IDE assim:
    • Clique no botão logo abaixo do ícone do Serial Monitor e escolha New Tab, ou use as teclas Ctrl+Shift+N.
    Arduino IDE 2 adiciona arquivo
    • Dê ao arquivo o nome index.h e clique no botão OK
    Arduino IDE 2 adiciona arquivo index.h
    • Copie o código abaixo e cole no index.h.
    /* * Este código de ESP32 foi desenvolvido por pt.newbiely.com * Este código de ESP32 é disponibilizado ao público sem nenhuma restrição. * Para tutoriais completos e diagramas de ligação, visite: * https://pt.newbiely.com/tutorials/esp32/esp32-controls-servo-motor-via-web */ const char *HTML_CONTENT = R"=====( <!DOCTYPE html> <html> <head> <title>ESP32 Controls Servo Motor via Web</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 = "https://esp32io.com/images/tutorial/servo-bracket.png"; function init() { var servo = document.getElementById("servo"); servo.width = canvas_width; servo.height = canvas_height; servo.style.backgroundImage = "url('https://esp32io.com/images/tutorial/servo-body.png')"; 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 - Servo Motor via Web<br> <canvas id="servo"></canvas> <p> WebSocket : <span id="ws_state" style="color:blue">null</span><br> Angle : <span id="debug" style="color:blue">90</span> </p> </h2> <div class="sponsor">Sponsored by <a href="https://amazon.com/diyables">DIYables</a></div> </body> </html> )=====";
    • Agora você tem o código em dois arquivos: newbiely.com.ino e index.h
    • Clique no botão Upload do Arduino IDE para fazer upload do código para o ESP32
    • Abra o Serial Monitor
    • Confira o resultado no Serial Monitor.
    ∞
    Newbiely | Arduino IDE 2.3.8
    ──
    ☐
    ✕
    File
    Edit
    Sketch
    Tools
    Help
    ESP32 Dev Module
    Newbiely.ino
    ···
    8 Serial.println("Hello World!");
    Output
    Serial Monitor
    Message (Enter to send message to 'ESP32 Dev Module' on 'COM15')
    New Line
    9600 baud
    Connecting to WiFi... Connected to WiFi ESP32 Web Server's IP address IP address: 192.168.0.2
    Ln 11, Col 1
    ESP32 Dev Module on COM15
    2
    • Anote o endereço IP exibido e digite esse endereço na barra de endereços de um navegador no seu celular ou PC.
    • Você verá a página web como abaixo:
    ESP32 controla servo motor pelo navegador web
    • O código JavaScript da página web cria automaticamente a conexão WebSocket com o ESP32.
    • Agora você pode controlar o ângulo do servo motor pela interface web.

    Para economizar a memória do ESP32, as imagens do servo motor NÃO ficam armazenadas no ESP32. Elas ficam armazenadas na internet, então seu celular ou PC precisa ter conexão com a internet para carregar as imagens da página web de controle.

    ※ Nota:

    • Se você modificar o conteúdo HTML no index.h e não mexer em nada no arquivo newbiely.com.ino, ao compilar e fazer upload do código para o ESP32, o Arduino IDE não vai atualizar o conteúdo HTML.
    • Para fazer o Arduino IDE atualizar o conteúdo HTML nesse caso, faça uma alteração no arquivo newbiely.com.ino (por exemplo, adicione uma linha vazia ou um comentário....)

    Explicação do Código Linha por Linha

    O código do ESP32 acima contém uma explicação linha por linha. Leia os comentários no código!

※ NOSSAS MENSAGENS

  • Fique à vontade para compartilhar o link deste tutorial. Porém, por favor, não use nosso conteúdo em outros sites. Investimos muito esforço e tempo para criar este conteúdo, por favor respeite nosso trabalho!