Arduino Nano ESP32 - Controla Servo Motor via Web

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

Arduino Nano ESP32 controls Servo Motor via Web

Agora, por que usar o WebSocket? Veja a ideia:

Vamos começar!

Hardware Necessário

1×Arduino Nano ESP32
1×Cabo USB Tipo-A para Tipo-C (para PC com USB-A)
1×Cabo USB Tipo-C para Tipo-C (para PC com USB-C)
1×Servo Motor
1×Protoboard
1×Fios Jumper
1×(Opcional) Conector de Alimentação DC
1×(Recomendado) Placa de Expansão com Bornes de Parafuso para Arduino Nano
1×(Recomendado) Placa de Expansão Breakout para Arduino Nano
1×(Recomendado) Divisor de Alimentação para Arduino Nano ESP32

Or you can buy the following kits:

1×DIYables Sensor Kit (18 sensors/displays)
Divulgação: Alguns dos links desta seção são links de afiliado da Amazon. Podemos receber uma comissão pelas compras feitas por meio desses links, sem custo adicional para você. Agradecemos o seu apoio.

Buy Note: For controlling multiple servo motors, use the PCA9685 16 Channel PWM Servo Driver Module to save MCU pins and simplify wiring.

Sobre o Servo Motor e o WebSocket

Temos tutoriais específicos sobre servo motor e WebSocket. Cada tutorial contém 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 Arduino Nano ESP32... Saiba mais sobre eles nos links a seguir:

Como Funciona

O código do Arduino Nano ESP32 cria tanto um servidor web quanto um servidor WebSocket. Veja como funciona:

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

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

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

  • Quando você alimenta a placa Arduino Nano ESP32 pela porta USB.
The wiring diagram between Arduino Nano ESP32 and Servo Motor

This image is created using Fritzing. Click to enlarge image

  • Quando você alimenta a placa Arduino Nano ESP32 pelo pino Vin.
The wiring diagram between Arduino Nano ESP32 and servo motor external power supply

This image is created using Fritzing. Click to enlarge image

※ Nota:

Ao alimentar a placa Arduino Nano ESP32 pela porta USB, você NÃO deve alimentar o servo motor pelo pino Vin pino VBUS. Se você alimentar o servo motor por esse pino, sua placa pode queimar.

Código Arduino Nano ESP32

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

  • Um arquivo .ino que é o código do Arduino Nano ESP32, que 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

Para começar com o Arduino Nano ESP32, siga estes passos:

  • Se você é novo no Arduino Nano ESP32, consulte o tutorial sobre como configurar o ambiente para o Arduino Nano ESP32 na Arduino IDE.
  • Faça a ligação dos componentes de acordo com o diagrama fornecido.
  • Conecte a placa Arduino Nano ESP32 ao seu computador usando um cabo USB.
  • Abra a Arduino IDE no seu computador.
  • Selecione a placa Arduino Nano ESP32 e a porta COM correspondente.
  • Abra o Library Manager clicando no ícone Library Manager na barra de navegação à esquerda da Arduino IDE.
  • Pesquise por “DIYables ESP32 WebServer” e encontre a biblioteca Web Server criada pela DIYables.
  • Clique no botão Install para instalar a biblioteca Web Server.
Arduino Nano ESP32 Web Server library
  • 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 o Arduino Nano ESP32.
Arduino Nano ESP32 servo motor library
  • Na Arduino IDE, crie um novo sketch e dê um nome a ele, por exemplo, newbiely.com.ino
  • Copie o código abaixo e abra-o na Arduino IDE
/* * Este código de Arduino Nano ESP32 foi desenvolvido por pt.newbiely.com * Este código de Arduino Nano ESP32 é disponibilizado ao público sem nenhuma restrição. * Para tutoriais completos e diagramas de ligação, visite: * https://pt.newbiely.com/tutorials/arduino-nano-esp32/arduino-nano-esp32-controls-servo-motor-via-web */ #include <ESP32Servo.h> #include <DIYables_ESP32_WebServer.h> #include "index.h" #define SERVO_PIN D2 // The Arduino Nano ESP32 pin 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("Arduino Nano 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(); }
  • Crie o arquivo index.h na Arduino IDE da seguinte forma:
    • 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 adds file
    • Dê ao arquivo o nome index.h e clique no botão OK
    Arduino IDE 2 adds file index.h
    • Copie o código abaixo e cole-o no index.h.
    /* * Este código de Arduino Nano ESP32 foi desenvolvido por pt.newbiely.com * Este código de Arduino Nano ESP32 é disponibilizado ao público sem nenhuma restrição. * Para tutoriais completos e diagramas de ligação, visite: * https://pt.newbiely.com/tutorials/arduino-nano-esp32/arduino-nano-esp32-controls-servo-motor-via-web */ const char *HTML_CONTENT = R"=====( <!DOCTYPE html> <html> <head> <title>Arduino Nano 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> Arduino Nano 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 na Arduino IDE para fazer o upload do código para o Arduino Nano ESP32
    • Abra o Serial Monitor
    • Veja o resultado no Serial Monitor.
    ∞
    Newbiely | Arduino IDE 2.3.8
    ──
    ☐
    ✕
    File
    Edit
    Sketch
    Tools
    Help
    Arduino Nano ESP32
    Newbiely.ino
    ···
    8 Serial.println("Hello World!");
    Output
    Serial Monitor
    Message (Enter to send message to 'Arduino Nano ESP32' on 'COM15')
    New Line
    9600 baud
    Connecting to WiFi... Connected to WiFi Arduino Nano ESP32 Web Server's IP address IP address: 192.168.0.3
    Ln 11, Col 1
    Arduino Nano ESP32 on COM15
    2
    • Anote o endereço IP exibido e digite esse endereço na barra de endereços de um navegador web no seu celular ou PC.
    • Você verá a página web como abaixo:
    Arduino Nano ESP32 controls servo motor via web browser
    • O código JavaScript da página web cria automaticamente a conexão WebSocket com o Arduino Nano 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 são armazenadas no Arduino Nano ESP32. Em vez disso, 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, quando você compilar e fizer o upload do código para o ESP32, a Arduino IDE não atualizará o conteúdo HTML.
    • Para fazer a Arduino IDE atualizar o conteúdo HTML nesse caso, faça uma alteração no arquivo newbiely.com.ino (por exemplo, adicionar uma linha vazia, adicionar um comentário....)

    Explicação do Código Linha por Linha

    O código do Arduino Nano ESP32 acima contém uma explicação linha por linha. Por favor, 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!