 |
| Demonstração prática do funcionamento de um encoder utilizando um ESP32 DevKit, sensor Hall KY-003 e ímãs de neodímio. Cada ímã gera um pulso quando passa em frente ao sensor. O ESP32 detecta esses eventos através de interrupções e realiza a contagem dos pulsos para calcular velocidade, RPM e posição. |
Como Funciona um Encoder? Aprenda na Prática com ESP32 e Sensor Hall KY-003
Quando começamos a trabalhar com motores, robôs e controle de velocidade, logo aparece uma palavra muito importante: encoder.
Mas afinal, o que é um encoder?
Como ele consegue medir a velocidade de um motor?
E por que praticamente todo robô mais avançado utiliza esse componente?
Neste artigo vamos entender esse conceito de forma simples utilizando um ESP32, um sensor Hall KY-003 e alguns ímãs de neodímio.
O objetivo é visualizar exatamente como os pulsos são gerados e como o ESP32 consegue contá-los através de interrupções.
O Que é um Encoder?
Um encoder é um dispositivo capaz de gerar pulsos conforme um eixo gira.
Esses pulsos podem ser contados por um microcontrolador para determinar:
- Velocidade do motor
- RPM (Rotações por Minuto)
- Distância percorrida
- Posição do eixo
Quanto maior a quantidade de pulsos gerados por volta, maior será a precisão da medição.
Simulando um Encoder com um Sensor Hall
Para facilitar o entendimento, vamos criar um encoder simples utilizando:
- ESP32 DevKit
- Sensor Hall KY-003
- Motor DC de 50 RPM
- Ímãs de neodímio
O princípio é muito simples.
Sempre que um ímã passar em frente ao sensor Hall, um pulso será gerado.
O ESP32 detecta esse pulso e incrementa um contador.
 |
| ESP32 DevKit, um sensor Hall KY-003 e ímãs de neodímio para demonstrar na prática como funcionam os pulsos utilizados para medir velocidade e posição. |
Como Funciona o Sensor Hall KY-003?
O KY-003 utiliza o efeito Hall para detectar campos magnéticos.
Normalmente sua saída permanece em nível lógico alto.
Quando um ímã passa próximo ao sensor, a saída muda de estado.
Essa mudança é suficiente para gerar uma interrupção no ESP32.
Na prática temos:
Ímã → Sensor Hall → Pulso → ESP32
 |
| ESP32, um sensor Hall KY-003 e quatro ímãs para demonstrar na prática como os pulsos são gerados e contados pelo microcontrolador. |
Teste com Um Ímã
Começamos colocando apenas um ímã na roda.
Cada vez que a roda completa uma volta, o ímã passa uma vez em frente ao sensor.
Resultado:
Ou seja:
1 ímã = 1 pulso por volta
Esse é o cenário mais simples possível.
Teste com Dois Ímãs
Agora adicionamos um segundo ímã.
Sem alterar nenhuma linha do código.
A única diferença é que o sensor passa a detectar dois eventos durante cada volta da roda.
Resultado:
Ou seja:
2 ímãs = 2 pulsos por volta
Teste com Três Ímãs
Adicionando mais um ímã:
Temos agora uma resolução maior.
O ESP32 recebe mais informações sobre o movimento da roda.
Teste com Quatro Ímãs
Com quatro ímãs distribuídos igualmente:
Resultado:
4 ímãs = 4 pulsos por volta
É exatamente esse conceito que existe dentro de muitos encoders comerciais.
O Que São Interrupções?
Imagine que o ESP32 está executando várias tarefas ao mesmo tempo.
Enquanto isso, o ímã passa rapidamente pelo sensor.
Como garantir que nenhum pulso seja perdido?
A resposta é: interrupções.
Uma interrupção funciona como um aviso urgente para o microcontrolador.
Quando o sensor detecta o ímã:
- O ESP32 interrompe temporariamente o que estava fazendo.
- Executa uma função específica.
- Conta o pulso.
- Retorna para a execução normal.
Tudo acontece em poucos microssegundos.
Código
/***************************************************************************
* Projeto : ESP32 + KY-003 + OLED SSD1306
* Autor : RodRobot
*
* Objetivo:
* Demonstrar o funcionamento das interrupções do ESP32
* utilizando um Sensor Hall KY-003.
*
* Conceito:
* ---------------------------------------------------------
* 1 ímã = 1 pulso por volta
* 2 ímãs = 2 pulsos por volta
* 3 ímãs = 3 pulsos por volta
* 4 ímãs = 4 pulsos por volta
* ---------------------------------------------------------
*
* Cada vez que o ímã passa pelo sensor Hall,
* uma interrupção é gerada no ESP32.
*
* Este é exatamente o mesmo conceito utilizado
* por encoders para medir velocidade e posição.
*
* Ligações OLED SSD1306
* ---------------------------------------------------------
* VCC -> 3V3
* GND -> GND
* SDA -> GPIO 21
* SCL -> GPIO 22
*
* Ligações KY-003
* ---------------------------------------------------------
* VCC -> 3V3
* GND -> GND
* OUT -> GPIO 4
***************************************************************************/
#include <Wire.h> // Comunicação I2C
#include <Adafruit_GFX.h> // Biblioteca gráfica
#include <Adafruit_SSD1306.h> // Biblioteca OLED
//======================================================================
// Configuração OLED
//======================================================================
#define SCREEN_WIDTH 128 // Largura display
#define SCREEN_HEIGHT 64 // Altura display
#define OLED_RESET -1 // Sem pino reset
#define SDA_PIN 21 // SDA OLED
#define SCL_PIN 22 // SCL OLED
Adafruit_SSD1306 display(
SCREEN_WIDTH,
SCREEN_HEIGHT,
&Wire,
OLED_RESET
);
//======================================================================
// Sensor Hall
//======================================================================
const byte HALL_PIN = 4; // Saída KY-003
//======================================================================
// Variáveis da interrupção
//======================================================================
volatile unsigned long pulsos = 0; // Contador total
volatile bool novoPulso = false; // Indica novo evento
//======================================================================
// Rotina de Interrupção
//======================================================================
void IRAM_ATTR detectarPulso()
{
pulsos++; // Soma 1 pulso
novoPulso = true; // Marca evento
}
//======================================================================
// Setup
//======================================================================
void setup()
{
Serial.begin(115200); // Monitor Serial
Wire.begin(
SDA_PIN,
SCL_PIN
); // Inicializa I2C
pinMode(
HALL_PIN,
INPUT_PULLUP
); // Entrada sensor Hall
//--------------------------------------------------------------------
// Inicializa OLED
//--------------------------------------------------------------------
if (!display.begin(
SSD1306_SWITCHCAPVCC,
0x3C))
{
Serial.println("OLED nao encontrado");
while (true); // Para execução
}
//--------------------------------------------------------------------
// Tela inicial
//--------------------------------------------------------------------
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("ESP32 + KY-003");
display.setCursor(0,15);
display.println("Interrupcoes");
display.setCursor(0,30);
display.println("1 Ima = 1 Pulso");
display.display();
delay(3000);
//--------------------------------------------------------------------
// Configura interrupção
//--------------------------------------------------------------------
attachInterrupt(
digitalPinToInterrupt(HALL_PIN), // GPIO monitorado
detectarPulso, // Função chamada
FALLING // Borda de descida
);
Serial.println();
Serial.println("Sistema iniciado");
Serial.println("Aguardando pulsos...");
}
//======================================================================
// Loop Principal
//======================================================================
void loop()
{
static unsigned long ultimoValor = 0;
//--------------------------------------------------------------------
// Copia variáveis da interrupção com segurança
//--------------------------------------------------------------------
noInterrupts(); // Desabilita interrupções
unsigned long total = pulsos; // Copia contador
bool evento = novoPulso; // Copia flag
novoPulso = false; // Limpa flag
interrupts(); // Reabilita interrupções
//--------------------------------------------------------------------
// Exibe no Serial quando houver novo pulso
//--------------------------------------------------------------------
if (total != ultimoValor)
{
ultimoValor = total;
Serial.print("Pulso detectado: ");
Serial.println(total);
}
//--------------------------------------------------------------------
// Atualiza OLED
//--------------------------------------------------------------------
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,0);
display.println("KY-003 ESP32");
display.drawLine(
0,
10,
128,
10,
WHITE
);
//--------------------------------------------------------------------
// Total de pulsos
//--------------------------------------------------------------------
display.setCursor(0,18);
display.print("Pulsos:");
display.setCursor(70,18);
display.print(total);
//--------------------------------------------------------------------
// Estado da interrupção
//--------------------------------------------------------------------
display.setCursor(0,35);
display.print("INT:");
display.setCursor(70,35);
if (evento)
{
display.print("DISPAROU");
}
else
{
display.print("OK");
}
//--------------------------------------------------------------------
// Informação didática
//--------------------------------------------------------------------
display.setCursor(0,52);
display.print("1 Ima = 1 Pulso");
display.display(); // Atualiza OLED
delay(50); // Pequena pausa
}
Configurando a Interrupção
No código utilizamos:
attachInterrupt(
digitalPinToInterrupt(HALL_PIN),
detectarPulso,
FALLING
);
Essa linha informa:
- Qual pino será monitorado
- Qual função será executada
- Qual evento deve disparar a interrupção
O Que Significa FALLING?
O sensor normalmente mantém sua saída em nível alto.
Quando o ímã é detectado:
HIGH → LOW
Essa transição é chamada de:
Falling Edge
Por isso utilizamos:
FALLING
para disparar a interrupção.
Como o ESP32 Conta os Pulsos?
A função de interrupção é extremamente simples:
void IRAM_ATTR detectarPulso()
{
pulsos++;
}
Cada vez que um ímã passa pelo sensor:
- Uma interrupção ocorre
- O contador aumenta
- Um novo pulso é registrado
Exemplo:
Antes:
10
Depois:
11
Calculando RPM
Agora vem a parte interessante.
Sabendo quantos pulsos existem por volta, podemos calcular o RPM do motor.
A fórmula é:
RPM = (Pulsos por Segundo × 60) ÷ Pulsos por Volta
Suponha um motor de 50 RPM com 4 ímãs.
Temos:
- 50 voltas por minuto
- 4 pulsos por volta
Logo:
50 × 4 = 200 pulsos por minuto
Ou aproximadamente:
3,33 pulsos por segundo
Calculando:
RPM = (3,33 × 60) ÷ 4
Resultado:
50 RPM
Exatamente a velocidade do motor.
O Que Acontece Dentro de um Encoder Real?
Agora que entendemos esse experimento, ficou fácil compreender um encoder verdadeiro.
Em vez de ímãs colados na roda, o encoder possui sensores internos capazes de gerar dezenas ou centenas de pulsos por volta.
O ESP32 faz exatamente o mesmo processo:
- Recebe pulsos
- Conta pulsos
- Calcula velocidade
- Calcula posição
- Calcula RPM
Ou seja, o conceito é exatamente o mesmo.
Conclusão
Neste projeto utilizamos um sensor Hall KY-003 para demonstrar de forma visual e prática como um encoder funciona.
Vimos que:
✔ Um ímã gera um pulso por volta
✔ Dois ímãs geram dois pulsos por volta
✔ Quatro ímãs geram quatro pulsos por volta
✔ O ESP32 utiliza interrupções para não perder nenhum pulso
✔ A partir dos pulsos é possível calcular RPM, velocidade e posição
Esse é um dos conceitos mais importantes para quem deseja trabalhar com motores DC, encoders, PID e robôs equilibrando.
E o melhor de tudo: usando componentes simples e de baixo custo é possível compreender exatamente o que acontece dentro de um encoder real.
🔧 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
Postar um comentário