ESP32-C3 com ESP-NOW: Controle um Robô com Joystick KY-023, DRV8833 e Motores N20 (Tutorial Completo)


Robô ESP32-C3 controlado por ESP-NOW utilizando joystick KY-023, driver DRV8833 e dois motores N20 para movimentação sem fio.
Projeto de robô sem fio com ESP32-C3 e ESP-NOW. O joystick KY-023 envia comandos de frente, ré, esquerda, direita e acionamento de LED para outro ESP32-C3 que controla dois motores N20 através do driver DRV8833.

Controle de Robô com ESP-NOW usando ESP32-C3 Super Mini, Joystick KY-023, Motor N20 e Driver DRV8833

Introdução

Neste projeto vamos construir um pequeno robô controlado sem fio utilizando dois módulos ESP32-C3 Super Mini comunicando-se através do protocolo ESP-NOW.

O sistema utiliza:

  • 2x ESP32-C3 Super Mini

  • 1x Módulo Joystick KY-023

  • 2x Motores N20

  • 1x Driver DRV8833

  • 1x LED

  • ESP-NOW para comunicação sem fio

O controle permite:

  • Frente

  • Esquerda

  • Direita

  • Parar

  • Acender e apagar um LED remoto através do botão do joystick


O que é o módulo Joystick KY-023?

O KY-023 é um módulo joystick analógico semelhante ao encontrado em controles de videogame.

Ele possui:

  • Eixo X (esquerda e direita)

  • Eixo Y (frente e ré)

  • Botão SW (pressionamento do joystick)

Componentes internos

O módulo possui:

  • Dois potenciômetros de aproximadamente 10 kΩ

  • Uma alavanca mecânica

  • Um botão tátil interno

Quando movimentamos a alavanca, os potenciômetros alteram sua resistência elétrica e produzem tensões diferentes nas saídas analógicas.


Como funciona o potenciômetro?

O potenciômetro é um resistor variável.

Internamente existe:

  • Uma trilha resistiva

  • Um contato móvel

Quando movemos o joystick, o contato desliza sobre a trilha alterando a tensão de saída.

Essa tensão é lida pelo conversor ADC do ESP32.


Leitura Analógica

O ESP32 possui conversores ADC (Conversor Analógico-Digital).

Eles transformam tensões em números.

No ESP32-C3 a leitura normalmente varia entre:

0 até 4095

Exemplo do eixo X

Joystick totalmente para a esquerda:

Valor próximo de:

0

Joystick centralizado:

Valor próximo de:

2048

Joystick totalmente para a direita:

Valor próximo de:

4095


Exemplo do eixo Y

Joystick para baixo:

Valor próximo de:

0

Joystick centralizado:

Valor próximo de:

2048

Joystick para cima:

Valor próximo de:

4095


Leitura do botão SW

Além dos eixos X e Y, o joystick possui um botão.

Quando não está pressionado:

SW = HIGH

Quando pressionado:

SW = LOW

No código utilizamos:

pinMode(SW, INPUT_PULLUP);

Assim o ESP32 mantém o pino em nível alto internamente.


O KY-023 Trabalha de 0 a 1023?

Uma dúvida muito comum entre iniciantes é acreditar que o joystick KY-023 trabalha com valores de 0 a 1023 por causa do número "023" presente em seu nome. Porém, isso não é verdade.

O número KY-023 é apenas o código do módulo na linha de sensores e módulos da Keyes. Ele não indica resolução, faixa de leitura ou quantidade de bits.

A confusão acontece porque muitos tutoriais utilizam o Arduino Uno, cujo conversor analógico-digital (ADC) possui resolução de 10 bits. Nesse caso, as leituras analógicas variam de:

0 a 1023

Neste projeto estamos utilizando um ESP32-C3, que possui ADC com resolução de até 12 bits. Por isso, as leituras analógicas podem variar de:

0 a 4095

Isso explica por que no código são utilizadas comparações como:

if (y > 3000)

e

if (y < 1000)

Esses valores fazem sentido para um ADC de 12 bits e não para um ADC de 10 bits.

Como Funciona o Joystick KY-023

O módulo KY-023 possui dois potenciômetros internos:

  • Um para o eixo X (esquerda e direita)

  • Um para o eixo Y (frente e ré)

Cada potenciômetro gera uma tensão variável entre:

0V e 3,3V

O ADC do ESP32-C3 converte essa tensão em valores numéricos.

Eixo X

Posição do JoystickValor Aproximado
Esquerda0
Centro2048
Direita4095

Eixo Y

Posição do JoystickValor Aproximado
0
Centro2048
Frente4095

ADC de 10 Bits vs ADC de 12 Bits


nfográfico explicando por que o joystick KY-023 não significa leitura de 0 a 1023, mostrando a diferença entre o ADC de 10 bits do Arduino Uno e o ADC de 12 bits do ESP32-C3 com leituras de 0 a 4095.
O código KY-023 identifica o módulo joystick da linha Keyes. A faixa de leitura depende do ADC do microcontrolador utilizado, como Arduino Uno (0 a 1023) ou ESP32-C3 (0 a 4095).

Um ADC de 10 bits divide a faixa de tensão em 1024 níveis:

0 a 1023

Já um ADC de 12 bits divide a mesma faixa em 4096 níveis:

0 a 4095

Isso permite que o ESP32-C3 faça leituras mais detalhadas e precisas do joystick, oferecendo maior sensibilidade e melhor controle do robô.

Uma Observação Importante

Na prática, dificilmente os valores serão exatamente:

0
2048
4095

O mais comum é encontrar algo semelhante a:

Esquerda  = 50 a 200
Centro    = 1900 a 2200
Direita   = 3900 a 4095

Essas pequenas variações acontecem devido às tolerâncias dos potenciômetros, alimentação, ruídos elétricos e características do ADC.

Por esse motivo, é sempre recomendado medir os valores reais utilizando o Serial Monitor antes de definir os limites utilizados no programa.

Resumo

Ao utilizar o joystick KY-023 com o ESP32-C3, considere que a faixa típica de leitura será:

Leitura típica do ESP32-C3

Esquerda  ≈ 0
Centro    ≈ 2048
Direita   ≈ 4095

(Os valores reais podem variar conforme o joystick)

Dessa forma evitamos a interpretação incorreta de que o KY-023 possui uma resolução fixa de 1023 pontos. Na realidade, quem define a resolução da leitura é o ADC do microcontrolador utilizado.


Comunicação ESP-NOW

ESP-NOW é um protocolo criado pela Espressif.

Suas vantagens:

  • Não precisa de roteador

  • Comunicação rápida

  • Baixo consumo

  • Baixa latência

  • Ideal para robôs

Neste projeto:

ESP32 Controle → Transmissor

ESP32 Robô → Receptor

O transmissor envia apenas um caractere representando cada comando.

Exemplos:

'F' = Frente
'R' = Ré
'D' = Direita
'E' = Esquerda
'P' = Parar
'L' = Liga LED
'O' = Desliga LED

Funcionamento do Robô

Quando o joystick é movimentado:

Frente

y > 3000

Envia:

'F'

y < 1000

Envia:

'R'

Direita

x > 3000

Envia:

'D'

Esquerda

x < 1000

Envia:

'E'

Centro

Quando o joystick retorna ao centro:

'P'

O robô para.


Controle do LED pelo botão SW

Ao pressionar o botão:

Primeira vez:

'L'

Liga o LED.

Segunda vez:

'O'

Desliga o LED.

O sistema funciona como um interruptor eletrônico.


Driver DRV8833

O DRV8833 é um driver de motores DC muito utilizado em robótica.

Principais características:

  • Alimentação de 2,7 V a 10,8 V

  • Controle de dois motores DC

  • Baixo consumo

  • Pequeno tamanho

  • Ideal para motores N20


Motores N20

Os motores N20 são pequenos motores com caixa de redução.

Vantagens:

  • Compactos

  • Baixo consumo

  • Boa força

  • Excelente para mini robôs

Neste projeto utilizamos:

Motor A → Lado esquerdo

Motor B → Lado direito


Controle dos motores

Frente

Motor esquerdo:

AIN1 = HIGH
AIN2 = LOW

Motor direito:

BIN1 = HIGH
BIN2 = LOW

Motor esquerdo:

AIN1 = LOW
AIN2 = HIGH

Motor direito:

BIN1 = LOW
BIN2 = HIGH

Esquerda

Motor esquerdo parado.

Motor direito girando para frente.

O robô faz curva para a esquerda.


Direita

Motor direito parado.

Motor esquerdo girando para frente.

O robô faz curva para a direita.


Parar

Todos os pinos em LOW.


Ligações do Controle (ESP32-C3 + KY-023)

Esquema de ligação completo de um robô controlado por ESP-NOW utilizando dois ESP32-C3 Super Mini, driver DRV8833, dois motores N20, joystick KY-023 e LED indicador.
Montagem completa do projeto: um ESP32-C3 atua como transmissor conectado ao joystick KY-023, enquanto o segundo ESP32-C3 recebe os comandos via ESP-NOW e controla dois motores N20 através do driver DRV8833, além de um LED remoto.



KY-023                     ESP32-C3
VRX                     GPIO 0
VRY                      GPIO 1
SW                     GPIO 10
GND                     GND
VCC                     3.3V

Ligações do Robô (ESP32-C3 + DRV8833)

DRV8833ESP32-C3
AIN1GPIO 2
AIN2GPIO 3
BIN1GPIO 4
BIN2GPIO 5

LED:

LED                 ESP32-C3
Anodo                 GPIO 7
Catodo                 GND


Código Transmissor



/***********************************************************************
 * Projeto : Controle ESP-NOW com Joystick
 * Autor   : RodRobot
 * Data    : 31/05/2026
 *
 * Descrição:
 *
 * Frente
 * Ré
 * Esquerda
 * Direita
 * Parar
 *
 * Botão SW:
 * Aperta uma vez  -> Liga LED
 * Aperta novamente -> Desliga LED
 *
 ***********************************************************************/

#include <WiFi.h>
#include <esp_now.h>

// ==================== Joystick ====================

#define VRX 0              // Eixo X
#define VRY 1              // Eixo Y
#define SW  10             // Botão

// ==================== MAC Receptor ====================

uint8_t enderecoReceptor[] =
{
  0xAC, 0xA7, 0x04, 0xD6, 0x67, 0xD4
};

// ==================== Estrutura ====================

typedef struct
{
  char comando;
} DadosEnviar;

DadosEnviar dados;

// ==================== Variáveis ====================

bool estadoLED = false;
bool ultimoSW = HIGH;

// ==================== Enviar ====================

void enviarComando(char cmd)
{
  dados.comando = cmd;

  esp_now_send(
      enderecoReceptor,
      (uint8_t *)&dados,
      sizeof(dados));
}

// ==================== Setup ====================

void setup()
{
  Serial.begin(115200);

  pinMode(SW, INPUT_PULLUP);

  WiFi.mode(WIFI_STA);

  if (esp_now_init() != ESP_OK)
  {
    Serial.println("Erro ESP-NOW");
    return;
  }

  esp_now_peer_info_t peerInfo = {};

  memcpy(peerInfo.peer_addr,
         enderecoReceptor,
         6);

  peerInfo.channel = 0;
  peerInfo.encrypt = false;

  esp_now_add_peer(&peerInfo);

  Serial.println("Controle iniciado");
}

// ==================== Loop ====================

void loop()
{
  int y = analogRead(VRX);      // Esquerda/Direita
  int x = analogRead(VRY);      // Frente/Ré

  // ---------- Frente ----------

  if (y > 3000)
  {
    enviarComando('F');
  }

  // ---------- Ré ----------

  else if (y < 1000)
  {
    enviarComando('R');
  }

  // ---------- Direita ----------

  else if (x > 3000)
  {
    enviarComando('E');
  }

  // ---------- Esquerda ----------

  else if (x < 1000)
  {
    enviarComando('D');
  }

  // ---------- Centro ----------

  else
  {
    enviarComando('P');
  }

  // ---------- Botão SW ----------

  bool leituraSW = digitalRead(SW);

  if (ultimoSW == HIGH && leituraSW == LOW)
  {
    estadoLED = !estadoLED;

    if (estadoLED)
    {
      enviarComando('L');
      Serial.println("LED ON");
    }
    else
    {
      enviarComando('O');
      Serial.println("LED OFF");
    }

    delay(250); // debounce
  }

  ultimoSW = leituraSW;

  delay(50);
}


Código Receptor



/***********************************************************************
 * Projeto : Robô ESP-NOW Receptor
 * Autor   : RodRobot
 * Data    : 31/05/2026
 *
 * Descrição:
 * Recebe comandos via ESP-NOW e controla:
 *
 * Frente
 * Ré
 * Esquerda
 * Direita
 * Parar
 *
 * Também controla um LED remoto.
 *
 ***********************************************************************/

#include <WiFi.h>
#include <esp_now.h>

#define AIN1 2
#define AIN2 3

#define BIN1 4
#define BIN2 5

#define LED_PIN 7

typedef struct
{
  char comando;
} DadosRecebidos;

DadosRecebidos dados;

void frente()
{
  digitalWrite(AIN1, HIGH);
  digitalWrite(AIN2, LOW);

  digitalWrite(BIN1, HIGH);
  digitalWrite(BIN2, LOW);
}

void re()
{
  digitalWrite(AIN1, LOW);
  digitalWrite(AIN2, HIGH);

  digitalWrite(BIN1, LOW);
  digitalWrite(BIN2, HIGH);
}

void esquerda()
{
  digitalWrite(AIN1, LOW);
  digitalWrite(AIN2, LOW);

  digitalWrite(BIN1, HIGH);
  digitalWrite(BIN2, LOW);
}

void direita()
{
  digitalWrite(AIN1, HIGH);
  digitalWrite(AIN2, LOW);

  digitalWrite(BIN1, LOW);
  digitalWrite(BIN2, LOW);
}

void parar()
{
  digitalWrite(AIN1, LOW);
  digitalWrite(AIN2, LOW);

  digitalWrite(BIN1, LOW);
  digitalWrite(BIN2, LOW);
}

void receberDados(const esp_now_recv_info_t *info,
                  const uint8_t *incomingData,
                  int len)
{
  memcpy(&dados, incomingData, sizeof(dados));

  switch (dados.comando)
  {
    case 'F': frente(); break;
    case 'R': re(); break;
    case 'E': esquerda(); break;
    case 'D': direita(); break;
    case 'P': parar(); break;

    case 'L':
      digitalWrite(LED_PIN, HIGH);
      break;

    case 'O':
      digitalWrite(LED_PIN, LOW);
      break;
  }
}

void setup()
{
  Serial.begin(115200);

  pinMode(AIN1, OUTPUT);
  pinMode(AIN2, OUTPUT);

  pinMode(BIN1, OUTPUT);
  pinMode(BIN2, OUTPUT);

  pinMode(LED_PIN, OUTPUT);

  parar();

  WiFi.mode(WIFI_STA);

  if (esp_now_init() != ESP_OK)
  {
    Serial.println("Erro ESP-NOW");
    return;
  }

  esp_now_register_recv_cb(receberDados);

  Serial.println("Receptor iniciado");
}

void loop()
{
}



Conclusão

Este projeto é uma excelente introdução à robótica móvel utilizando ESP32-C3. Com apenas dois ESP32-C3 Super Mini, um joystick KY-023, um driver DRV8833 e dois motores N20, é possível construir um robô sem fio de baixo custo e fácil expansão.

A partir desta base você pode adicionar diversos recursos futuramente:

  • Sensor ultrassônico HC-SR04

  • Sensor seguidor de linha

  • Sensor infravermelho

  • Display OLED

  • Buzzer

  • Monitoramento de bateria

  • ESP32-CAM para vídeo sem fio

  • Controle por aplicativo ou página web

O ESP-NOW torna a comunicação extremamente rápida e ideal para projetos de robótica, automação e Internet das Coisas (IoT).


🔧 Acompanhe o RodRobot

Projetos maker com ESP32, Arduino, eletrônica e programação.

RodRobot – Projetos maker, eletrônica e programação na prática.

Comentários

Postagens mais visitadas deste blog

ESP32 Botão Touch: Como Usar o Sensor Touch (Tutorial com LED e Relé)

ESP-01 vs ESP32: NeoPixel (WS2812) Não é PWM

ESP32 para Iniciantes: Projeto LED Piscando Passo a Passo