ESP32 - Encoder Rotativo

Neste guia, você vai aprender a usar o encoder rotativo com um ESP32. Veja o que vamos aprender:

Sobre o Encoder Rotativo

Um botão giratório, como o de um rádio, pode enviar sinais que se transformam em eletricidade. Ele nos ajuda a saber o quanto ele girou e em que posição está. Existem dois tipos principais:

  • Encoder incremental: este usa sinais rápidos para medir o quanto algo mudou de posição.
  • Encoder absoluto: este tipo fornece um código secreto para cada posição, o que nos ajuda a descobrir onde algo está, mesmo se a energia for cortada.

Esta lição trata principalmente do primeiro tipo, o encoder incremental.

Pinagem do Módulo Encoder Rotativo

pinagem do encoder rotativo

Um módulo encoder rotativo tem 4 pinos:

  • Pino CLK (Saída A): é o pulso principal que nos diz quanto de rotação ocorreu. Sempre que você gira o botão um detent (clique) em qualquer direção, o pino CLK emite um sinal que completa um ciclo completo (LOW → HIGH → LOW).
  • Pino DT (Saída B): funciona como o pino CLK, mas emite um sinal atrasado 90 graus em relação ao sinal CLK. Ele nos ajuda a descobrir a direção da rotação (sentido horário ou anti-horário).
  • Pino SW: vem do botão do encoder. Ele é normalmente aberto. Quando adicionamos um resistor de pull-up a este pino, o pino SW fica em HIGH quando o botão não está pressionado e em LOW quando está pressionado.
  • Pino VCC (+): precisa ser conectado ao VCC (entre 3,3 e 5 volts)
  • Pino GND: precisa ser conectado ao GND (0V)

Encoder Rotativo vs Potenciômetro

Você pode confundir o encoder rotativo com o potenciômetro, mas eles são componentes distintos. Aqui está uma comparação entre eles:

  • O encoder rotativo é como a versão moderna do potenciômetro, mas pode fazer mais coisas.
  • O encoder rotativo pode girar em um círculo completo sem parar, enquanto o potenciômetro só consegue girar cerca de três quartos do círculo.
  • O encoder rotativo emite pulsos, enquanto o potenciômetro emite uma tensão analógica.
  • O encoder rotativo é útil quando você só precisa descobrir o quanto o botão se moveu, e não exatamente onde ele está. O potenciômetro é útil quando você realmente precisa saber exatamente onde um botão está.

Como o Encoder Rotativo Funciona

saída do encoder rotativo

Dentro do encoder, há um pequeno disco com ranhuras conectado a um pino chamado C, que funciona como um terra compartilhado. Você tem mais dois pinos, A e B.

  • Quando você gira o botão, os pinos A e B tocam esse pino de terra compartilhado C, mas a ordem em que eles o tocam depende do sentido em que você gira o botão (horário ou anti-horário).
  • Esses toques criam dois sinais. Eles são um pouco diferentes no tempo porque um pino toca o terra antes do outro. Esses sinais ficam defasados em 90 graus, o que é chamado de codificação em quadratura.
  • Se você girar o botão no sentido horário, o pino A toca o terra antes do pino B. Mas se você girar no sentido anti-horário, o pino B toca o terra primeiro, antes do pino A.
  • Verificando quando cada pino toca ou deixa o terra, podemos descobrir para que lado o botão está girando. Fazemos isso verificando o que acontece com o pino B quando o pino A muda.
Como o encoder rotativo funciona

Quando A muda de estado de LOW para HIGH:

  • Se B estiver em HIGH, o botão foi girado no sentido anti-horário.
  • Se B estiver em LOW, o botão foi girado no sentido horário.

※ Nota:

Os pinos A e B são conectados aos pinos CLK e DT. No entanto, dependendo do fabricante, a ordem pode ser diferente. Os códigos fornecidos abaixo foram testados com o encoder rotativo da DIYables

Como Programar o Encoder Rotativo

  • O ESP32 lê o sinal do pino CLK
  • Se o estado mudar de LOW para HIGH, então o ESP32 lê o estado do pino DT.
    • Se o pino DT estiver em HIGH, o botão foi girado no sentido anti-horário, e o ESP32 aumenta o contador em 1
    • Se o pino DT estiver em LOW, o botão foi girado no sentido horário, e o ESP32 diminui o contador em 1

Diagrama de Ligação

Diagrama de Ligação do encoder rotativo com ESP32

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.

Código ESP32 – Encoder Rotativo

O código ESP32 abaixo faz o seguinte:

  • Detecta a direção e a quantidade de rotação do encoder.
    • Se detectar que o botão foi girado um detent (clique) no sentido horário, aumenta o contador em um.
    • Se detectar que o botão foi girado um detent (clique) no sentido anti-horário, diminui o contador em um.
  • Detecta se o botão está pressionado.
/* * 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-rotary-encoder */ #include <ezButton.h> // the library to use for SW pin #define CLK_PIN 25 // ESP32 pin GPIO25 connected to the rotary encoder's CLK pin #define DT_PIN 26 // ESP32 pin GPIO26 connected to the rotary encoder's DT pin #define SW_PIN 27 // ESP32 pin GPIO27 connected to the rotary encoder's SW pin #define DIRECTION_CW 0 // clockwise direction #define DIRECTION_CCW 1 // counter-clockwise direction int counter = 0; int direction = DIRECTION_CW; int CLK_state; int prev_CLK_state; ezButton button(SW_PIN); // create ezButton object that attach to pin 7; void setup() { Serial.begin(9600); // configure encoder pins as inputs pinMode(CLK_PIN, INPUT); pinMode(DT_PIN, INPUT); button.setDebounceTime(50); // set debounce time to 50 milliseconds // read the initial state of the rotary encoder's CLK pin prev_CLK_state = digitalRead(CLK_PIN); } void loop() { button.loop(); // MUST call the loop() function first // read the current state of the rotary encoder's CLK pin CLK_state = digitalRead(CLK_PIN); // If the state of CLK is changed, then pulse occurred // React to only the rising edge (from LOW to HIGH) to avoid double count if (CLK_state != prev_CLK_state && CLK_state == HIGH) { // if the DT state is HIGH // the encoder is rotating in counter-clockwise direction => decrease the counter if (digitalRead(DT_PIN) == HIGH) { counter--; direction = DIRECTION_CCW; } else { // the encoder is rotating in clockwise direction => increase the counter counter++; direction = DIRECTION_CW; } Serial.print("Rotary Encoder:: direction: "); if (direction == DIRECTION_CW) Serial.print("Clockwise"); else Serial.print("Counter-clockwise"); Serial.print(" - count: "); Serial.println(counter); } // save last CLK state prev_CLK_state = CLK_state; if (button.isPressed()) { Serial.println("The button is pressed"); } }

Para simplificar o código de debounce do botão, a biblioteca ezButton é utilizada.

Passos Rápidos

Se esta é a primeira vez que você usa o ESP32, veja como configurar o ambiente para o ESP32 na Arduino IDE.

  • Instale a biblioteca ezButton na Arduino IDE.
  • Copie o código acima e abra-o com a Arduino IDE
  • Clique no botão Upload na Arduino IDE para carregar o código no ESP32
  • Gire o botão no sentido horário e depois no sentido anti-horário
  • Pressione o botão
  • Veja 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
Rotary Encoder:: direction: CLOCKWISE - count: 1 Rotary Encoder:: direction: CLOCKWISE - count: 2 Rotary Encoder:: direction: CLOCKWISE - count: 3 Rotary Encoder:: direction: CLOCKWISE - count: 4 Rotary Encoder:: direction: CLOCKWISE - count: 5 Rotary Encoder:: direction: ANTICLOCKWISE - count: 4 Rotary Encoder:: direction: ANTICLOCKWISE - count: 3 Rotary Encoder:: direction: ANTICLOCKWISE - count: 2 Rotary Encoder:: direction: ANTICLOCKWISE - count: 1 Rotary Encoder:: direction: ANTICLOCKWISE - count: 0 The button is pressed
Ln 11, Col 1
ESP32 Dev Module on COM15
2

Explicação do Código

Confira os comentários linha por linha no código

Código ESP32 – Encoder Rotativo com Interrupção

No código anterior, usar polling para verificar continuamente o estado do pino pode desperdiçar recursos do ESP32 e causar perda de contagens se a execução de outras partes do código for lenta.

Uma solução eficaz é utilizar a interrupção, que elimina a necessidade de polling. Isso permite que o ESP32 execute outras tarefas sem perder as contagens. Abaixo está o código ESP32 que usa a interrupção para ler a direção e a posição do encoder rotativo.

/* * 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-rotary-encoder */ #include <ezButton.h> // the library to use for SW pin #define CLK_PIN 25 // ESP32 pin GPIO25 connected to the rotary encoder's CLK pin #define DT_PIN 26 // ESP32 pin GPIO26 connected to the rotary encoder's DT pin #define SW_PIN 27 // ESP32 pin GPIO27 connected to the rotary encoder's SW pin #define DIRECTION_CW 0 // clockwise direction #define DIRECTION_CCW 1 // counter-clockwise direction volatile int counter = 0; volatile int direction = DIRECTION_CW; volatile unsigned long last_time; // for debouncing int prev_counter; ezButton button(SW_PIN); // create ezButton object that attach to pin 7; void IRAM_ATTR ISR_encoder() { if ((millis() - last_time) < 50) // debounce time is 50ms return; if (digitalRead(DT_PIN) == HIGH) { // the encoder is rotating in counter-clockwise direction => decrease the counter counter--; direction = DIRECTION_CCW; } else { // the encoder is rotating in clockwise direction => increase the counter counter++; direction = DIRECTION_CW; } last_time = millis(); } void setup() { Serial.begin(9600); // configure encoder pins as inputs pinMode(CLK_PIN, INPUT); pinMode(DT_PIN, INPUT); button.setDebounceTime(50); // set debounce time to 50 milliseconds // use interrupt for CLK pin is enough // call ISR_encoder() when CLK pin changes from LOW to HIGH attachInterrupt(digitalPinToInterrupt(CLK_PIN), ISR_encoder, RISING); } void loop() { button.loop(); // MUST call the loop() function first if (prev_counter != counter) { Serial.print("Rotary Encoder:: direction: "); if (direction == DIRECTION_CW) Serial.print("CLOCKWISE"); else Serial.print("ANTICLOCKWISE"); Serial.print(" - count: "); Serial.println(counter); prev_counter = counter; } if (button.isPressed()) { Serial.println("The button is pressed"); } // TO DO: your other work here }

Agora, ao girar o botão, você verá informações aparecendo no Serial Monitor, de forma muito parecida com o que viu no código anterior.

※ Nota:

  • Você pode encontrar tutoriais em outros sites que usam duas interrupções para um único encoder, mas isso é desnecessário e um desperdício. Apenas uma interrupção é suficiente.
  • É importante usar a palavra-chave volatile para as variáveis globais usadas na interrupção. Ignorar isso pode causar problemas inesperados.
  • Mantenha o código dentro da interrupção o mais simples possível. Evite usar Serial.print() ou Serial.println() dentro da interrupção.

Aplicação do Encoder Rotativo com ESP32

Com o Encoder Rotativo, podemos fazer as seguintes aplicações, entre outras:

  • ESP32 - Encoder Rotativo controla a Posição do Servo Motor
  • ESP32 - Encoder Rotativo controla o Brilho do LED
  • ESP32 - Encoder Rotativo controla a Velocidade do Motor de Passo

Vídeo

Referências de Funções

※ 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!