EC11 – Rotary encoder

Ze noemen het ook wel een digitale volumeregelaar, maar daar doe je de encoder tekort mee. Inmiddels wordt het component o.a. toegepast als thermostaatknop, als selectiewiel op een smartwatch of op een oven, of in de auto en ja, ook op moderne audio-installaties waarbij volume en toon digitaal geregeld worden. De meeste encoders zijn voorzien van een drukknop waarmee de ingestelde waarde geselecteerd kan worden.

In deze uitgebreide tutorial leg ik uit wat een roterende encoder is en laat ik zien hoe je een roterende encoder op de Raspberry Pi aansluit.

Daar gaan we…

Basisprincipe
Een roterende encoder is een elektronisch component dat de rotatie en richting van de draaiende knop detecteert en pulsen genereert als de as verdraait. Het werkt door twee interne contacten die een circuit maken en verbreken als er aan de knop wordt gedraaid. Terwijl je aan de knop draait, voel je hem “klikken”, wat aangeeft dat er minimaal één positie is gedraaid.

Als de interne contacten oorspronkelijk HOOG waren (circuit maakten) na een enkele klik, zouden ze nu allebei LAAG zijn (circuit verbreken). Met een simpel stukje logica kun je de richting van de rotatie bepalen. Daar kom ik later op terug.

Het principe en daarmee de voorkomende modellen roterende encoders zijn beperkt. Voor deze uitleg zal ik mij beperken tot het meest voorkomende roterende basismodel met draai-as, de roterende encoder type EC11.

De EC11 rotary encoder

Hoe roterende encoders werken?
Binnenin de encoder bevindt zich een schijf met open sleuven die is verbonden met pin C, de (gemeenschappelijke) ground. Het heeft ook twee contactpinnen A en B, zoals hieronder weergegeven.

Wanneer je aan de knop draait, maken A en B contact in een specifieke volgorde met de ground (pin C), afhankelijk van de richting waarin je de knop draait.

Wanneer de contactpinnen contact maken met de ground, worden er twee (logische) signalen gegenereerd. Deze signalen zijn 90° uit fase omdat de ene pin eerder contact maakt met de ground dan de andere. Dit wordt kwadratuurcodering genoemd .

Signalen A en B zijn 90° uit fase

Draairichting bepalen
Wanneer de knop met de klok mee wordt gedraaid, wordt pin A vóór pin B met ground verbonden. Wanneer de knop tegen de klok in wordt gedraaid, wordt pin B vóór pin A met ground verbonden.

Door te monitoren wanneer elke pin verbinding maakt of loskoppelt van de ground, kunnen we bepalen in welke richting de knop wordt gedraaid. Dit kan worden bereikt door simpelweg de toestand van B te observeren wanneer de toestand van A verandert.

Wanneer A van status verandert:

  • als B != A, dan wordt de knop met de klok mee gedraaid:
  • als B = A, wordt de knop tegen de klok in gedraaid:

De pinnen van een roterende encoder
Er zijn verschillende uitvoeringen van de encodermodule met nagenoeg dezelfde aansluitingen. Mogelijk dat de signalen net even anders genoemd worden. Mijn module ziet er als volgt uit:

  • CLK is de primaire uitgangspuls die gebruikt wordt om de hoeveelheid rotatie te bepalen. Elke keer als de knop met slechts één klik in een van beide richtingen wordt gedraaid, doorloopt de ‘CLK’-uitvoer één cyclus van HOOG en vervolgens LAAG.
  • DT is vergelijkbaar met CLK-uitvoer, maar blijft achter op CLK met een faseverschuiving van 90°. Deze uitgang wordt gebruikt om de draairichting te bepalen.
  • SW is de uitgang van de drukknopschakelaar (actief laag). Wanneer de knop wordt ingedrukt, wordt de spanning LAAG.
  • Vcc is de positieve voedingsspanning, die ligt doorgaans tussen 3,3 en 5 volt.
  • GND is de ground.
Schema van de rotary encoder module

De encoder aansluiten
Nu we begrijpen hoe de roterende encoder werkt, is het tijd om hem in gebruik te nemen! Laten we de encoder aansluiten op de Raspberry Pi. De verbindingen zijn vrij eenvoudig.

  • Sluit de CLK-pin van de module aan op pin 11 (GPIO17) van de Pi
  • Sluit nu de DT-pin van de module aan op pin 12 (GPIO18) van de Pi
  • De SW-pin van de module wordt in deze tutorial niet gebruikt!
  • En de GND-pin van de module op een willekeurige GND-pin (zoals pin 14) van de Pi
  • Sluit de +pin van de module aan op de 3.3V-uitgang van de Pi
Aansluittabel

Andere vormfactor, andere pinaanduiding
Ik heb nog een tweede rotary encoder module die op een ronde print gemonteerd is. Bij deze is de pinaanduiding weliswaar anders, maar de signalen zijn hetzelfde als degene die hierboven besproken is. Het voordeel van deze ronde EC11 is dat er een debounce (anti-stuiter) circuit is aangebracht. Mocht je een encoder willen aanschaffen, raad ik aan deze aan. Het kan behoorlijk frustreren als je circuit ‘stuitert’ en meer pulsen afgeeft dan wenselijk is.

Roterende encoder module met debounce circuit

De volgende afbeelding toont de bedrading.

Dat is het voor zover het de bedrading betreft. Je hoeft je geen zorgen te maken over weerstanden of andere componenten, aangezien de encoder ingebouwde weerstanden van 10k Ohm heeft, waardoor de stroom tot een minimum (0,33mA) wordt beperkt!


Python
Je kunt de voorbeeldcode hier downloaden of de code hieronder kopiëren en in de nano editor plakken.

De voorbeeldcode is een eenvoudige teller. Als je de encoder met de klok meedraait, wordt het getal bij elke “klik” met 1 verhoogd en als je het tegen de klok in draait, neemt het bij elke “klik” met 1 af. Ook wordt de draairichting getoond.

import RPi.GPIO as GPIO
from time import sleep

counter = 10

CLK = 18
DT  = 17

def init():
    print ("\033[1;1;1m,\033c")
    print ("Rotary Encoder Test Programma\n")
    GPIO.setwarnings(True)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(CLK, GPIO.IN)
    GPIO.setup(DT, GPIO.IN)
    GPIO.add_event_detect(CLK, GPIO.RISING, callback=rotation_decode, bouncetime=10)
    return

def rotation_decode(CLK):
    global counter
    sleep(0.002)
    Switch_A = GPIO.input(CLK)
    Switch_B = GPIO.input(DT)

    if (Switch_A == 1) and (Switch_B == 0):
        counter += 1
        print ("Draairichting -> ", counter)
        while Switch_B == 0:
            Switch_B = GPIO.input(DT)
        while Switch_B == 1:
            Switch_B = GPIO.input(DT)
        return

    elif (Switch_A == 1) and (Switch_B == 1):
        counter -= 1
        print ("Draairichting <- ", counter)
        while Switch_A == 1:
            Switch_A = GPIO.input(CLK)
        return
    else:
        return

def main():
    try:
        init()
        while True :
            sleep(1)

    except KeyboardInterrupt:
        GPIO.cleanup()

if __name__ == '__main__':
    main()

Tip: Wist je dat je met de toetscombinatie [Alt]-[Shift]-3 regelnummers in nano laat zien?

De logica voor het bepalen van de draairichting is heel eenvoudig te coderen, maar niet zo gemakkelijk te begrijpen. Daarom hier nog even de stappen van de signaalwijzigingen bij de rotatie/’klik’:

Voor een rotatie met de klok mee:

  1. CLK en DT zijn beide HOOG
  2. CLK wordt LAAG, DT blijft HOOG -> clkLastState was HOOG, clkState is LAAG (clkState != clkLastState ) dus nu kunnen we de richting bepalen -> dtState is HOOG, clkState LOW, dtState != clkState, +1
  3. DT wordt LAAG, CLK blijft LAAG -> clkLastState was LAAG, clkState is LAAG -> Er gebeurt niets

Voor een rotatie tegen de klok in:

  1. CLK en DT zijn beide HOOG
  2. DT wordt LAAG, CLK blijft HOOG -> clkLastState was HOOG, clkState is HOOG -> Er gebeurt niets
  3. CLK wordt LAAG, DT blijft LAAG -> clkLastState was HOOG, clkState is LAAG (clkState != clkLastState ) dus nu kunnen we de richting bepalen -> dtState is LOW, clkState LOW, dtState == clkState, -1

Huiswerk
Om de functionaliteit van de encoder te oefenen is altijd goed om zelf iets te ontwikkelen. Zo zou je een roterend cijferslot kunnen maken dat na 5 goed ingevoerde getallen een rode led groen laat oplichten. Je gebruikt de drukknop functie van de module om de cijfers te op te slaan. Laat me weten als het gelukt is!

Have A Nice Day!

Geef als eerste een reactie

Laat een reactie achter

Het e-mailadres wordt niet gepubliceerd.


*