ESP32 – Drehwinkelgeber
Einleitung ESP32 Drehwinkelgeber
Drehwinkelgeber dienen zur Eingabe von Werten über einen Drehknopf. Ich betrachte in diesem Artikel den preiswerten KY-04. Prinzipbedingt kann es bei einfachen Ausführungen zum Prellen des Ausgangssignales kommen.
Das Programm zu Erfassung der Daten basiert auf einer Interrupt Routine. Interrupt entkoppeln das Erfassen der Daten des Drehwinkelgebers von dem ESP32 loop(). Es ist daher kein Polling notwendig.
Die Entprellung ist relativ aufwendig, da die Drehgeschwindigkeit des Sensors variieren kann und so fest Entprellzeiten nicht in allen Situationen möglich sind. Das Programm erfasst die Zykluslänge des CLK-Signals, des Drehwinkelgeber.
Ich betreibe den Drehwinkelgeber mit 3,3V. Es gibt verschiedene Hersteller dieses Drehwinkelgebers, die Angaben zur Versorgungsspannung sind im Markt nicht eideutig, einige schreiben 5V, andere 3,3/5V. Mit 3,3V funktioniert das Bauteil bei mir.
Als ESP32 kommt bei mir der AZ-Delivery ESP32S Dev Kit C zum Einsatz. Die Funktion bei einem ESP8266 werden ich bei Gelegenheit testen.
Bauteile
- AZ-Delivery ESP32S Dev Kit C
- Drehwinkelgeber KY-04
Programm Drehwinkelgeber
//-------------------------------------------------------
// Drehwinkelgeber auf Basis eines ESP32
// 27.1.2025
//-------------------------------------------------------
//
// ESP32 Pin Definitionen
//
#define ROTENC_CLK 17 // CLK des Rotate Sensors
#define ROTENC_DT 16 // DT des Rotate Sensors
//
// Variablen
//
int RotencPosCount; // Rotate Sensor Zählerstand
int RotencPosLast; // Letzter Rotate Sensor Zählerstand
int ClkLast; // Letzter Level Clk
int IrCount = 0; // IRQ Zähler
unsigned long DeBounce=0; // Entprellungszähler
unsigned long DeBounceCycle=0; //
int DeBounceLength = 0; // Zykluszeit
//-------------------------------------------------------
// Interruptroutine zum Drehwinkelgeber
//
void IRAM_ATTR ClkChanged() {
//
// Start Entprellung
//
DeBounce = millis();
while ((millis()-DeBounce) < 2)
;
//
// Flanke High->Low
//
if (digitalRead(ROTENC_CLK) == LOW) {
//
// Entprellung Flanke Low->High
if ((millis()-DeBounceCycle) > DeBounceLength){
//
// Drehrichtung feststellen und +1 oder -1
//
if (digitalRead(ROTENC_DT) == HIGH)
RotencPosCount++;
else
RotencPosCount--;
//
// DEBUG Interrupt Zähler
//
IrCount++;
//
// Start Zykluslänge feststellen
//
DeBounceCycle = millis();
}
}
//
// Flanke Low->High
else
{
//
// Zykluslänge feststellen
//
DeBounceLength = millis()-DeBounceCycle;
}
}
//-------------------------------------------------------
// Setup ESP32
//
void setup() {
//
// Eingangssignale GPIO festlegen
//
pinMode(ROTENC_CLK, INPUT_PULLUP);
pinMode(ROTENC_DT,INPUT_PULLUP);
//
// Zähler und Richtung Reset
//
RotencPosCount = 0;
RotencPosLast = 0;
//
// Debug Baud einstellen
//
Serial.begin (115000);
//
// Start mitteilen
//
Serial.println ("Rotation Encoder Start!");
//
// Intterupt
//
attachInterrupt(ROTENC_CLK, ClkChanged,CHANGE);
}
//-------------------------------------------------------
// Verarbeitungsschleife ESP32
//
void loop() {
//
// Test auf Veränderung der Zählers
//
if (RotencPosLast != RotencPosCount){
//
// Debug Zähler ausgeben
//
// Bei Interruptaktionen kann es zu zeitichen
// Überschneidungen in der Ausgabe kommen. Die Aussage
// der Debuginfo kann fehlerhaft sein!
//
//Serial.print("Rotation Encoder Zähler: ");
Serial.print(IrCount);
Serial.print(" ");
Serial.print(DeBounceLength);
Serial.print(" ");
Serial.println(RotencPosCount);
RotencPosLast = RotencPosCount;
}
}
Aktualisiert: 27.1.2025