Rotacijski kodirnik (rotary encoder) is fantastična komponenta za krmiljenje projektov, kot so FM radijski sprejemniki, meniji na zaslonih ali nadzor glasnosti. Za razliko od navadnega potenciometra se lahko vrti v neskončnost, poleg tega pa ima vgrajen še gumb na pritisk.
Vendar pa se pri delu z njim hitro srečamo z realnostjo fizičnega sveta: mehanskim šumom stikov (t.i. bouncing). Ko zavrtiš gumb za een klik, mikrokontroler zaradi izjemne hitrosti zazna na desetine drobnih, lažnih vklopov in izklopov. Rezultat? Vrednosti na zaslonu skačejo divje gor in dol.
Kako deluje rotacijski kodirnik?
Kodirnik uporablja dva izhoda (običajno označena kot CLK in DT). Ko zavrtimo gumb, se na teh dveh izhodih sprožita dva kvadratna signala, ki sta med seboj zamaknjena za 90 stopinj (t.i. kvadratura). S spremljanjem, kateri signal se spremeni prvi, Arduino ugotovi smer vrtenja:
- Smer urinega kazalca: Signal CLK spremeni stanje pred signalom DT.
- Nasprotna smer urinega kazalca: Signal DT spremeni stanje pred signalom CLK.
Rešitev: Programski debouncing brez dodatnih komponent
Čeprav bi šum lahko reševali s spajkanjem kondenzatorjev (strojni debouncing), je veliko bolj elegantno težavo rešiti programsko. Z uporabo funkcije millis() v kodi določimo "čakalni čas" (npr. 5 milisekund). Če se signal spremeni hitreje kot v tem času, ga Arduino preprosto ignorira kot šum.
Za ta primer bomo uporabili Arduino Mega 2560, ki nam ponuja odlično stabilnost in dovolj procesorske moči za natančno spremljanje signalov.
Primer kode za Arduino Mega 2560
Spodaj je pripravljen delujoč program, ki ga lahko takoj naložiš na svoj Arduino. Koda uporablja programsko odpravljanje šuma za gladko zaznavanje vsakega premika:
// Definicija pinov na Arduino Mega
const int pinCLK = 3; // Pin za CLK signal
const int pinDT = 2; // Pin za DT signal
int zadnjeStanjeCLK;
int trenutnoStanjeCLK;
long polozaj = 0;
// Spremenljivke za odpravljanje šuma (debouncing)
unsigned long zadnjiCasSpremembe = 0;
const unsigned long zakasnitevDebounce = 5; // Čas v milisekundah
void setup() {
pinMode(pinCLK, INPUT);
pinMode(pinDT, INPUT);
Serial.begin(9600);
// Preberemo začetno stanje
zadnjeStanjeCLK = digitalRead(pinCLK);
}
void loop() {
trenutnoStanjeCLK = digitalRead(pinCLK);
// Reagiramo SAMO takrat, ko gre CLK iz HIGH v LOW stanje (padec signala)
if (trenutnoStanjeCLK != zadnjeStanjeCLK && trenutnoStanjeCLK == LOW) {
if ((millis() - zadnjiCasSpremembe) > zakasnitevDebounce) {
// Če je DT drugačen od CLK, se vrti v desno, sicer v levo
if (digitalRead(pinDT) != trenutnoStanjeCLK) {
polozaj++;
} else {
polozaj--;
}
Serial.print("Polozaj: ");
Serial.println(polozaj);
zadnjiCasSpremembe = millis();
}
}
zadnjeStanjeCLK = trenutnoStanjeCLK;
}
Navodila za hitro povezavo vezja
Da bo vse delovalo iz prve, poveži komponente po naslednjih korakih:
- Poveži GND pin kodirnika na GND pin na Arduino Mega.
- Poveži + (VCC) pin kodirnika na 5V pin na Arduinu.
- Poveži izhod CLK na digitalni pin 2 in izhod DT na digitalni pin 3.
- Odpri Serial Monitor (hitrost 9600) in začni vrteti gumb!