Arduino - Rotary Encoder

In deze tutorial gaan we leren hoe u een incremental encoder gebruikt met Arduino. In detail behandelen we:

Hardware Benodigdheden

1×Arduino Uno R3
1×USB 2.0 kabel type A/B
1×Draaiencoder
1×Jumperdraden
1×(Aanbevolen) Schroefklem Block Shield voor Arduino Uno
1×(Aanbevolen) Breadboard-Shield voor Arduino Uno
1×(Aanbevolen) Behuizing voor Arduino Uno
1×(Aanbevolen) Prototyping Basisplaat & Breadboard Kit voor Arduino Uno

Of u kunt de volgende kits kopen:

1×DIYables Sensorkit (30 sensoren/displays)
1×DIYables Sensorkit (18 sensoren/displays)
Openbaarmaking: Sommige van de links in deze sectie zijn Amazon-affiliate links. We kunnen een commissie ontvangen voor aankopen die via deze links worden gedaan, zonder extra kosten voor u. We waarderen uw steun.

Over de Rotary Encoder

Een rotary encoder is een elektromechanisch apparaat dat rotatiebeweging omzet in een elektrisch signaal. Het meet de rotatie en positie van een as of knop. Er zijn twee hoofdtypen:

  • Incremental encoder: genereert pulsen om relatieve verandering te meten
  • Absolute encoder: geeft een unieke digitale code voor elke positie, ideaal voor precieze positiebepaling ook na een stroomuitval.

Deze handleiding gaat over de incremental encoder.

Rotary Encoder Module Pinout

rotary encoder pinout

Een rotary encoder module heeft 4 pinnen:

  • CLK-pin (Output A): dit is de hoofd puls die aangeeft hoeveel rotatie heeft plaatsgevonden. Elke keer dat u de knop een stapje (klik) draait in welke richting dan ook, geeft de CLK pin een signaal dat één volledige cyclus voltooit (LOW HIGH LOW).
  • DT-pin (Output B): werkt vergelijkbaar met de CLK pin, maar het signaal loopt 90 graden achter op het CLK-signaal. Dit helpt ons de draairichting te bepalen (met of tegen de klok in).
  • SW-pin: dit is de uitgang van de drukknop binnenin de encoder. Dit is normaal open. Als u een pull-up weerstand op deze pin toepast, is de SW pin HIGH als de knop niet wordt ingedrukt, en LOW als de knop wordt ingedrukt.
  • VCC-pin (+): moet verbonden zijn met VCC (tussen 3.3 en 5 Volt)
  • GND-pin: moet verbonden zijn met GND (0V)

Rotary Encoder versus Potentiometer

U kunt de rotary encoder verwarren met de potentiometer, maar het zijn verschillende componenten. Hieronder een vergelijking:

  • Rotary encoder is als een moderne versie van de potentiometer, maar met meer mogelijkheden.
  • Rotary encoder kan oneindig rondgedraaid worden, terwijl een potentiometer ongeveer driekwart van een cirkel draait.
  • Rotary encoder geeft pulsen als uitgang, een potentiometer geeft een analoge spanning.
  • Rotary encoder is handig als u alleen wilt weten hoeveel de knop is verzet, niet de exacte positie. Potentiometer is geschikt wanneer u de precieze positie wilt weten.

Hoe Werkt een Rotary Encoder

rotary encoder output

Binnenin de encoder zit een schijf met gleuven verbonden aan een pin genaamd C, die fungeert als gedeelde aarde (common ground). Daarnaast zijn er twee pinnen A en B.

  • Als u aan de knop draait, maken pinnen A en B afwisselend contact met de gedeelde aarde pin C, in een bepaalde volgorde afhankelijk van de draaigrichting (met of tegen de klok in).
  • Deze contacten creëren twee signalen die in tijd net iets verschillen doordat de pinnen niet gelijktijdig de aarde raken. Deze twee signalen lopen 90 graden uit fase op elkaar. Dit heet quadratuur encoding.
  • Draait u de knop met de klok mee, dan raakt pin A eerst de aarde voordat pin B deze raakt. Draait u tegen de klok in, dan raakt pin B eerst de aarde voordat pin A dat doet.
  • Door te controleren wanneer iedere pin de aarde raakt of loslaat, kunnen we bepalen welke kant de knop draait. We doen dit door te kijken wat er met pin B gebeurt als pin A verandert van toestand.
Hoe rotary encoder werkt

Wanneer pin A verandert van LOW naar HIGH:

  • Als B LOW is, dan draait de knop met de klok mee.
  • Als B HIGH is, dan draait de knop tegen de klok in.

※ Notiz:

Pin A en B zijn verbonden met de CLK en DT pinnen. Afhankelijk van de fabrikant kan de volgorde verschillen. De onderstaande code is getest met de rotary encoder van DIYables.

Hoe Arduino te Programmeren voor Rotary Encoder

  • Controleer het signaal van de CLK pin
  • Als de toestand verandert van LOW naar HIGH, controleer dan de toestand van de DT pin:
    • Als de DT pin HIGH is, draait de knop tegen de klok in, verhoog de teller met 1
    • Als de DT pin LOW is, draait de knop met de klok mee, verlaag de teller met 1

Bedradingsschema

Arduino rotary encoder Bedradingsschema

This image is created using Fritzing. Click to enlarge image

Arduino Code – Rotary Encoder zonder Interrupt

De onderstaande Arduino code doet het volgende:

  • Detecteert de draairichting en hoeveelheid rotatie van de encoder.
    • Als er wordt gedetecteerd dat de knop een „klik” met de klok mee draait, verhoog dan de teller met één.
    • Als er wordt gedetecteerd dat de knop een „klik” tegen de klok in draait, verlaag dan de teller met één.
  • Detecteert of de knop wordt ingedrukt.
/* * Deze Arduino code is ontwikkeld door newbiely.nl * Deze Arduino code wordt zonder enige beperking aan het publiek beschikbaar gesteld. * Voor volledige instructies en schema's, bezoek: * https://newbiely.nl/tutorials/arduino/arduino-rotary-encoder */ #include <ezButton.h> // the library to use for SW pin #define CLK_PIN 2 #define DT_PIN 3 #define SW_PIN 4 #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 4 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("DIRECTION: "); if (direction == DIRECTION_CW) Serial.print("Clockwise"); else Serial.print("Counter-clockwise"); Serial.print(" | COUNTER: "); Serial.println(counter); } // save last CLK state prev_CLK_state = CLK_state; if (button.isPressed()) { Serial.println("The button is pressed"); } }

Om de code te vereenvoudigen voor het ontbouncen van de knop, wordt de ezButton bibliotheek gebruikt.

Snelstartstappen

  • Installeer de ezButton bibliotheek in Arduino IDE. Zie Hoe te installeren
  • Kopieer de bovenstaande code en open deze met Arduino IDE
  • Klik op de Upload knop in Arduino IDE om de code naar de Arduino te uploaden
  • Draai de knop met de klok mee en daarna tegen de klok in
  • Druk op de knop
  • Bekijk het resultaat op de Serial Monitor.
COM6
Send
DIRECTION: Clockwise | COUNTER: 1 DIRECTION: Clockwise | COUNTER: 2 DIRECTION: Clockwise | COUNTER: 3 DIRECTION: Clockwise | COUNTER: 4 DIRECTION: Clockwise | COUNTER: 5 DIRECTION: Counter-clockwise | COUNTER: 4 DIRECTION: Counter-clockwise | COUNTER: 3 DIRECTION: Counter-clockwise | COUNTER: 2 DIRECTION: Counter-clockwise | COUNTER: 1 DIRECTION: Counter-clockwise | COUNTER: 0 The button is pressed
Autoscroll Show timestamp
Clear output
9600 baud  
Newline  

Code Uitleg

Bekijk de regel-voor-regel opmerkingen in de code voor verdere uitleg.

Arduino Code – Rotary Encoder met Interrupt

In het vorige codevoorbeeld gebruiken we de polling methode, waarbij continu de pinstatus wordt gecontroleerd. Dit heeft twee nadelen:

  • Het verbruikt onnodig Arduino bronnen
  • Sommige tellers kunnen gemist worden als andere code lang duurt om uit te voeren

Een oplossing hiervoor is het gebruik van interrupts. Interrupts maken continue controle overbodig omdat ze het programma onderbreken zodra een gebeurtenis plaatsvindt. Hierdoor kan de Arduino andere taken uitvoeren zonder events te missen.

Hier volgt een voorbeeld hoe u een rotary encoder leest met interrupts.

/* * Deze Arduino code is ontwikkeld door newbiely.nl * Deze Arduino code wordt zonder enige beperking aan het publiek beschikbaar gesteld. * Voor volledige instructies en schema's, bezoek: * https://newbiely.nl/tutorials/arduino/arduino-rotary-encoder */ #include <ezButton.h> // the library to use for SW pin #define CLK_PIN 2 #define DT_PIN 3 #define SW_PIN 4 #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 4 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_encoderChange() when CLK pin changes from LOW to HIGH attachInterrupt(digitalPinToInterrupt(CLK_PIN), ISR_encoderChange, RISING); } void loop() { button.loop(); // MUST call the loop() function first if (prev_counter != counter) { Serial.print("DIRECTION: "); if (direction == DIRECTION_CW) Serial.print("Clockwise"); else Serial.print("Counter-clockwise"); Serial.print(" | COUNTER: "); Serial.println(counter); prev_counter = counter; } if (button.isPressed()) { Serial.println("The button is pressed"); } // TO DO: your other work here } void ISR_encoderChange() { 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(); }

Als u nu aan de knop draait, ziet u vergelijkbare informatie verschijnen in de Serial Monitor als in de vorige code.

※ Notiz:

  • Als u interrupts gebruikt, moet u de CLK pin van de encoder aansluiten op een Arduino pin die interrupts ondersteunt. Niet alle Arduino pinnen kunnen dit. Bijvoorbeeld, op de Arduino Uno zijn alleen pin 2 en pin 3 geschikt voor interrupts.
  • U zult soms tutorials tegenkomen die twee interrupts gebruiken voor één encoder, maar dat is onnodig en verspilling. Eén interrupt is voldoende.
  • Het is belangrijk om de volatile keyword te gebruiken voor globale variabelen binnen de interruptroutine. Zonder dit kunnen onvoorziene problemen ontstaan.
  • Houd de code binnen de interruptroutine zo eenvoudig mogelijk. Vermijd het gebruik van Serial.print() of Serial.println() in de interrupt.

Arduino Rotary Encoder Toepassingen

Met een Rotary Encoder kunt u de volgende toepassingen (maar niet beperkt tot) realiseren:

  • Arduino - Rotary Encoder bestuurt positie van een servo motor
  • Arduino - Rotary Encoder bestuurt helderheid van een LED
  • Arduino - Rotary Encoder bestuurt snelheid van een stappenmotor

Video Tutorial

We overwegen het maken van videotutorials. Als u videotutorials belangrijk vindt, abonneer u dan op ons YouTube-kanaal om ons te motiveren de video's te maken.

Bekijk onze video-tutorial voor een visuele begeleiding bij dit project! De video biedt extra inzichten die de instructies aanvullen en verduidelijken.

Functiereferenties

※ ONZE BERICHTEN

  • U bent welkom om de link naar deze tutorial te delen. Gebruik onze inhoud echter niet op andere websites. We hebben veel moeite en tijd gestoken in het maken van de inhoud, respecteer alstublieft ons werk!