Tutorial ESP32 30/55 - Controle de Servo pela web usando MQTT com o serviço Adafruit IO | Kit de Aprendizagem IoT ESP32 da SunFounder
Neste tutorial, aprenderemos como controlar a posição de um motor de passo usando o microcontrolador ESP32 e o protocolo MQTT pela web. Aproveitando o serviço Adafruit IO, você poderá posicionar o servo em vários ângulos, como 0°, 90° ou 180°, remotamente. Este projeto demonstra as capacidades do ESP32, que inclui Wi-Fi e Bluetooth embutidos, tornando-o uma ferramenta poderosa para aplicações de IoT.

Neste projeto, configuraremos um broker MQTT usando Adafruit IO, criaremos um painel para controlar o servo e conectaremos o ESP32 a ele. A posição do servo será ajustável por meio de um controle deslizante no painel, permitindo o controle em tempo real de qualquer dispositivo com acesso à internet (no vídeo às 5:30).
Hardware Explicado
Os componentes principais deste projeto incluem o microcontrolador ESP32 e o motor de servo. O ESP32 é um microcontrolador versátil com capacidades integradas de Wi-Fi e Bluetooth, tornando-o ideal para aplicações de IoT. Ele se comunica com o serviço Adafruit IO usando o protocolo MQTT, que é leve e eficiente para transmissão de mensagens pela internet.
O motor de servo é um atuador rotativo que permite o controle preciso da posição angular. Ele funciona recebendo um sinal de modulação por largura de pulso (PWM) que dita sua posição. Neste projeto, conectaremos o servo a um dos pinos digitais no ESP32, permitindo-nos controlar seu ângulo remotamente.
Detalhes da Ficha Técnica
| Fabricante | Paralaxe |
|---|---|
| Número da peça | SG90 |
| Tensão de Lógica/IO | 3,3 V - 5 V |
| Tensão de alimentação | 4,8 V - 6,0 V |
| Corrente de saída (por canal) | 1 A max |
| Orientação sobre a frequência PWM | 50 Hz |
| Limiares de lógica de entrada | 0,3 V - 0,7 V |
| Queda de tensão / RDS(on)/ saturação | 0,2 V máx |
| Limites térmicos | Temperatura de operação: -10°C a 60°C |
| Pacote | Capa de plástico |
| Notas / variantes | Mini servo, rotação de 180° |
- Garanta o fornecimento de tensão adequado ao servo (4,8 V - 6,0 V).
- Use um terra comum entre o ESP32 e o servo.
- Monitore o sinal PWM para evitar exceder os limites do servomotor.
- Conecte o servo de forma segura para evitar desconexões durante a operação.
- Atualize a biblioteca Adafruit MQTT para garantir compatibilidade.
Diagramas MQTT
Instruções de Fiação

Para conectar o motor servo ao ESP32, comece ligando o fio de aterramento do servo ao pino de aterramento no ESP32. Em seguida, conecte o fio de alimentação (geralmente vermelho) do servo ao pino de 5V no ESP32. Por fim, conecte o fio de sinal (frequentemente amarelo ou branco) ao pino digital 25 no ESP32. Certifique-se de que as conexões estejam seguras para evitar desconexões durante a operação.
Se você estiver usando uma bateria para alimentar o ESP32, certifique-se de que a voltagem da bateria esteja dentro da faixa aceitável tanto para o ESP32 quanto para o servo. Além disso, verifique novamente se a fiação corresponde às definições das portas usadas em seu código para evitar quaisquer problemas (no vídeo às 12:45).
Exemplos de Código e Passo a Passo
No texto fornecido, primeiro incluímos as bibliotecas necessárias para o ESP32 e MQTT. Definimos o objeto servo e especificamos o pino ao qual está conectado comconst int servoPin = 25;. O ângulo padrão também é configurado comconst int defaultServoAngle = 90;, que será a posição inicial quando o ESP32 iniciar.
Servo myServo;
const int servoPin = 25;
const int defaultServoAngle = 90;
int servoAngle = defaultServoAngle;
Este trecho inicializa o servo na porta 25 e define seu ângulo padrão para 90°. A variávelservoAngleserá atualizado com base nas mensagens recebidas do broker MQTT.
In thesetup()função, conectamos ao Wi-Fi e configuramos o cliente MQTT. As credenciais para Adafruit IO são definidas aqui, incluindo o nome de usuário e a chave:
#define AIO_USERNAME "robojax"
#define AIO_KEY "aio_xmIW58uNNsjJCSOqzZ9QoHyq29wu"
Esta seção estabelece a conexão com o serviço Adafruit IO. Certifique-se de substituir esses valores pelas suas próprias credenciais do Adafruit IO ao implementar o código.
Finalmente, o loop principal garante que a conexão com o servidor MQTT permaneça ativa e processe as mensagens recebidas. A posição do servo é atualizada com base no ângulo recebido:
mqtt.processPackets(500);
int pulseWidth = map(servoAngle, 0, 180, minPulseWidth, maxPulseWidth);
myServo.writeMicroseconds(pulseWidth);
Este código mapeia o ângulo do servo para a largura de pulso correspondente e a envia para o motor servo. AprocessPackets()a função permite que o ESP32 trate mensagens MQTT recebidas, garantindo que o servo reaja a comandos enviados através do painel do Adafruit IO.
Demonstração / O que Esperar
Uma vez que tudo esteja configurado, você deve ser capaz de controlar o servo a partir do painel do Adafruit IO usando o controle deslizante que você criou. À medida que você move o controle deslizante, o servo ajustará seu ângulo em tempo real. Certifique-se de que seu ESP32 esteja conectado ao Wi-Fi e que a conexão MQTT esteja estável. Se o servo não responder, verifique a fiação e a fonte de alimentação do servo (no vídeo às 20:15).
Esteja ciente dos limites de alcance do servo; enviar um valor fora de 0° a 180° pode fazer com que ele se comporte de maneira inesperada. O código inclui verificações para evitar tais ocorrências, limitando o ângulo dentro desse intervalo.
Marcação de Vídeo
- 00:00 Início
- 1:54 Introdução do projeto
- 2:52 Introdução ao MQTT
- 6:50 Configuração do Adafruit IO
- 9:54 Cabeamento do servo
- 11:07 Código explicado
- 18:59 Selecionando a placa ESP32 e a porta COM
- 22:10 Demonstração do projeto
/***********************************************************************
This is Arduino sketch for ESP32 to control Servo motor using MQTT service of Adafruit
www.Robojax.com
Written By Ahamd Shamshiri
on Feb 2nd, 2024
Watch video instruction for this code on YouTube https://youtu.be/T4DhWNg2Rb8
Adafruit MQTT Library ESP32 Adafruit IO SSL/TLS example
this code can be downloaded from https://robojax.com/RJT671
/// ref: https://www.electronicwings.com/esp32/esp32-mqtt-client
*/
#include <ESP32Servo.h>
// Define the servo and the pin it is connected to
Servo myServo;
const int servoPin = 25;
const int defaultServoAngle = 90;
int servoAngle =defaultServoAngle;
// Define the minimum and maximum pulse widths for the servo
const int minPulseWidth = 500; // 0.5 ms
const int maxPulseWidth = 2500; // 2.5 ms
#include <WiFi.h>
#include "WiFiClientSecure.h"
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
/************************* WiFi Access Point *********************************/
#define WLAN_SSID "Barqasaa"
#define WLAN_PASS "wan9&Jang~5"
/************************* Adafruit.io Setup *********************************/
#define AIO_SERVER "io.adafruit.com"
// Using port 8883 for MQTTS
#define AIO_SERVERPORT 8883
// Adafruit IO Account Configuration
// (to obtain these values, visit https://io.adafruit.com and click on Active Key)
// #define AIO_USERNAME "YOUR_ADAFRUIT_IO_USERNAME"
// #define AIO_KEY "YOUR_ADAFRUIT_IO_KEY"
#define AIO_USERNAME "robojax"
#define AIO_KEY "aio_xmIW58uNNsjJCSOqzZ9QoHyq29wu"
/************ Global State (you don't need to change this!) ******************/
// WiFiFlientSecure for SSL/TLS support
WiFiClientSecure client;
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
// io.adafruit.com root CA
const char* adafruitio_root_ca = \
"-----BEGIN CERTIFICATE-----\n"
"MIIEjTCCA3WgAwIBAgIQDQd4KhM/xvmlcpbhMf/ReTANBgkqhkiG9w0BAQsFADBh\n"
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\n"
"MjAeFw0xNzExMDIxMjIzMzdaFw0yNzExMDIxMjIzMzdaMGAxCzAJBgNVBAYTAlVT\n"
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
"b20xHzAdBgNVBAMTFkdlb1RydXN0IFRMUyBSU0EgQ0EgRzEwggEiMA0GCSqGSIb3\n"
"DQEBAQUAA4IBDwAwggEKAoIBAQC+F+jsvikKy/65LWEx/TMkCDIuWegh1Ngwvm4Q\n"
"yISgP7oU5d79eoySG3vOhC3w/3jEMuipoH1fBtp7m0tTpsYbAhch4XA7rfuD6whU\n"
"gajeErLVxoiWMPkC/DnUvbgi74BJmdBiuGHQSd7LwsuXpTEGG9fYXcbTVN5SATYq\n"
"DfbexbYxTMwVJWoVb6lrBEgM3gBBqiiAiy800xu1Nq07JdCIQkBsNpFtZbIZhsDS\n"
"fzlGWP4wEmBQ3O67c+ZXkFr2DcrXBEtHam80Gp2SNhou2U5U7UesDL/xgLK6/0d7\n"
"6TnEVMSUVJkZ8VeZr+IUIlvoLrtjLbqugb0T3OYXW+CQU0kBAgMBAAGjggFAMIIB\n"
"PDAdBgNVHQ4EFgQUlE/UXYvkpOKmgP792PkA76O+AlcwHwYDVR0jBBgwFoAUTiJU\n"
"IBiV5uNu5g/6+rkS7QYXjzkwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsG\n"
"AQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMDQGCCsGAQUFBwEB\n"
"BCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEIGA1Ud\n"
"HwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEds\n"
"b2JhbFJvb3RHMi5jcmwwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEW\n"
"HGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwDQYJKoZIhvcNAQELBQADggEB\n"
"AIIcBDqC6cWpyGUSXAjjAcYwsK4iiGF7KweG97i1RJz1kwZhRoo6orU1JtBYnjzB\n"
"c4+/sXmnHJk3mlPyL1xuIAt9sMeC7+vreRIF5wFBC0MCN5sbHwhNN1JzKbifNeP5\n"
"ozpZdQFmkCo+neBiKR6HqIA+LMTMCMMuv2khGGuPHmtDze4GmEGZtYLyF8EQpa5Y\n"
"jPuV6k2Cr/N3XxFpT3hRpt/3usU/Zb9wfKPtWpoznZ4/44c1p9rzFcZYrWkj3A+7\n"
"TNBJE0GmP2fhXhP1D/XVfIW/h0yCJGEiV9Glm/uGOa3DXHlmbAcxSyCRraG+ZBkA\n"
"7h4SeM6Y8l/7MBRpPCz6l8Y=\n"
"-----END CERTIFICATE-----\n";
/****************************** Feeds ***************************************/
// Setup a feed called 'test' for publishing and 'test2' for subscription.
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
Adafruit_MQTT_Subscribe SERVO = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/servo-angle-1");
/*************************** Sketch Code ************************************/
void setup() {
// Attach the servo to the specified pin and set its pulse width range
myServo.attach(servoPin, minPulseWidth, maxPulseWidth);
// Set the PWM frequency for the servo
myServo.setPeriodHertz(50); // Standard 50Hz servo
Serial.begin(115200);
delay(10);
Serial.println(F("Adafruit IO MQTTS (SSL/TLS) Example"));
// Connect to WiFi access point.
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(WLAN_SSID);
delay(1000);
WiFi.begin(WLAN_SSID, WLAN_PASS);
delay(2000);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// Set Adafruit IO's root CA
client.setCACert(adafruitio_root_ca);
// register callback for feed
SERVO.setCallback(servoCallback);
// Setup MQTT subscription for time feed.
mqtt.subscribe(&SERVO);
}
// uint32_t x=0;
void loop() {
// Ensure the connection to the MQTT server is alive (this will make the first
// connection and automatically reconnect when disconnected). See the MQTT_connect
// function definition further below.
MQTT_connect();
Serial.print("Angle: ");
Serial.println(servoAngle);
// wait 0.5 seconds for subscription messages
mqtt.processPackets(500);
//from lesson 17
int pulseWidth = map(servoAngle, 0, 180, minPulseWidth, maxPulseWidth);
myServo.writeMicroseconds(pulseWidth);
delay(15);
// wait a couple seconds to avoid rate limit
//delay(2000);
}
void servoCallback(char* message, uint16_t len) {
char messageBuffer[40];
snprintf(messageBuffer, sizeof(messageBuffer), "Servo status is :: %s, len :: %u", message, len);
Serial.println(messageBuffer);
Serial.println(message);
String inString = message;//sotre the message to String
servoAngle = inString.toInt();//convert the message to Integer
if(servoAngle >180 || servoAngle < 0)
{
servoAngle =0;
}
}
// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
int8_t ret;
// Stop if already connected.
if (mqtt.connected()) {
return;
}
Serial.print("Connecting to MQTT... ");
uint8_t retries = 3;
while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000); // wait 5 seconds
retries--;
if (retries == 0) {
// basically die and wait for WDT to reset me
while (1)
;
}
}
Serial.println("MQTT Connected!");
}
Common Course Links
Common Course Files
Coisas que você pode precisar
-
AliExpressCompre o motor Servo SG90 180 ou 360 no AliExpresss.click.aliexpress.com
Recursos e referências
-
DocumentaçãoTutorial ESP32 17/55 - Documentação do motorservo SunFunderdocs.sunfounder.com
-
ExternoSG90 servo na Amazon EUAamzn.to
Arquivos📁
Outros arquivos
-
Folha de dados do motor SG90 Seroo
robojax-servo-SG90_datasheet.pdf0.12 MB