
Van az úgy, hogy egy egyszerű beállítást szeretnék megvalósítani: tekerővel választani menüpontot, nyomással megerősíteni. Nem akarok érintőkijelzőt, nem kell Bluetooth, csak valami fizikai, kézzel fogható. Egy olyan vezérlő, ami egyszerre intuitív, olcsó, és nem igényel bonyolult logikát. Egy hangerőszabályzó, amit nem csak szabályzónak lehet használni. Vagy épp egy beviteli eszköz egy projekt beállításához, ahol nincs hely három gombnak.
Ilyenkor jön képbe a rotary encoder, azon belül is a KY-040 modul. Nem új technológia, de még mindig megbízható. Épp azért szeretem, mert mechanikus, egyszerű, és kézzel programozható. Ha van egy Arduino UNO-m és egy laptopom, máris elindulhat a fejlesztés. A KY-040 nemcsak forgást érzékel, hanem a tengelye lenyomható is – így egyetlen alkatrésszel két bemenetet is kapok.
Ebben a cikkben azt mutatom be, hogyan tudom az Arduino-val kiolvasni a forgás irányát és a nyomógomb állapotát, majd ezeket soros porton közvetlenül megjeleníteni. Ez az első lépés az enkóderes projektek világába – innen már csak egy kis kreativitás, és kész is a saját menürendszerem vagy adatbevitel.
Hogyan működik a KY-040?
A KY-040 egy mechanikus rotary encoder, amely az egyik legegyszerűbb és legelterjedtebb eszköz, ha valamilyen elfordulást – például egy menü léptetését – szeretném érzékelni. A működése egy úgynevezett kvadratúra jelet állít elő: két digitális kimenete (CLK és DT) fáziseltéréssel kapcsolgat, attól függően, hogy merre forgatom a tengelyt. Ha a CLK vált előbb, akkor jobbra forgás történik, ha a DT vezet az állapotváltásban, akkor balra.

Ezek az impulzusok digitális jelek, így könnyedén olvashatók Arduino-val. Minden impulzus egy lépést jelent, amit például számlálni lehet. Ha például egy hangerőszabályzót építek, ezek a lépések jelenthetnek dB szintnövekedést vagy -csökkenést. A gyakorlatban persze ennél sokkal többet is kihozhatok belőle – de az alap mindig a két jel figyelése és az irány eldöntése:

A KY-040 egyik nagy előnye, hogy nemcsak forgatni lehet, hanem nyomni is: a tengely végén egy kis mikrokapcsoló található. Ez a kapcsoló külön lábon (SW) jön ki, és egy egyszerű nyomógombként használható. Ez teszi az eszközt igazán sokoldalúvá – egyetlen eszközzel lehetőségem van léptetni és választani is. A kapcsolóhoz beépített húzóellenállás is jár, az Arduino oldalán pedig INPUT_PULLUP módban máris stabilan kezelhető.
Persze nem minden rózsaszín: a mechanikus enkóderek tipikusan hajlamosak a kontaktusugrásra, azaz pattognak. Emiatt előfordulhat, hogy egyetlen kattintásnak több jelszintváltás is megfelel, amit az Arduino kétszeres vagy éppen semmilyen eseményként érzékel. Ezt hívják bouncing-nak – és ez ellen már az alap példában is védekezni kell.
A legegyszerűbb módszer az, ha egy kis időt várok a kapcsolás után – ez lehet egy delay(), vagy ha haladóbb vagyok, akkor millis()-alapú időzítéssel csak akkor reagálok, ha már elég idő telt el az előző esemény óta. Még jobb megoldás, ha egy kis kondenzátort (pl. 100nF) is elhelyezek a bemenet és a föld közé – ez hardveresen simítja ki a jelet.
Mindez nem bonyolult – csak tudni kell, hogy az enkóder nem egy szoftveres varázseszköz, hanem egy zajos, de kiszámítható viselkedésű modul. És ha tudom, hogyan olvassam ki, az Arduino már teszi a dolgát. Ebben a cikkben egy alap gyorsteszt kódot mutatok be, amellyel valós időben követhetem a forgás irányát és a nyomógomb állapotát a soros monitoron.
Bekötés és kapcsolási környezet
A KY-040 modul öt kivezetéssel rendelkezik: CLK, DT, SW, VCC és GND. Ezeket pontosan így csatlakoztatom az Arduino UNO-hoz:
- VCC a 5V tápra
- GND a földre
- CLK a digitális 3-as lábra (D3)
- DT a digitális 4-es lábra (D4)
- SW a digitális 2-es lábra (D2)
Ez a bekötés nem kötelező, de így jól átlátható, és könnyen használható az egyszerű tesztkódokban. A kapcsoló esetében INPUT_PULLUP módot használok, így nincs szükség külső ellenállásra.

A kapcsolási környezethez elegendő egy breadboard, néhány jumperkábel, és ha kéznél van: egy kis 100nF-os kondenzátor a CLK és DT lábakra – ez segít kisimítani a pellegő jeleket. A kapcsoló lábára is néha teszek 100 nF értékű kondenzátort (persze csak akkor, ha gyakran téves jelzést kapok (De legtöbbször ez már a kapcsoló végét jelenti – így a modulcsere célravezetőbb)).
Az áramkör egyszerű, nem igényel külön tápellátást – az Arduinoről való táplálása bőven elegendő. Érdemes a soros monitort is előkészíteni a teszteléshez: így azonnal látható, hogyan viselkedik a modul, és hogy jól kötöttem-e be minden vezetéket.
Alap működésteszthez szükséges kód
Az alábbi kód egy egyszerű számlálót valósít meg, amely figyeli a forgás irányát, és annak megfelelően növeli vagy csökkenti egy változó értékét, amely a soros monitoron azonnal visszajelzésre kerül. Ezáltal gyorsan ellenőrizhető, hogy az enkóder megfelelően működik. A kapcsoló lenyomására külön üzenet jelenik meg a soros monitoron, így ez az esemény is jól nyomon követhető, például kiválasztási vagy megerősítési célokra. A program nem használ külső könyvtárat, teljes egészében a szabványos Arduino parancsokra épül, így könnyen érthető és módosítható. Akár egy saját menürendszer első lépéseként is alkalmazható, hiszen az alaplogika már ebben a példában is megfigyelhető.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | /* Program neve: Enkóder (rotary encoder) – alap működés Verzió: 1.0 Dátum: 2025. augusztus 23. Szerző: Cseh Róbert Web: https://www.tavir.hu Leírás: A program egy egyszerű forgó enkóder működését demonstrálja. A CLK és DT jelekből meghatározza a forgás irányát és a számláló értékét növeli vagy csökkenti. A beépített nyomógombot is figyeli, és lenyomáskor kiírja az eseményt. Nincs külön zajszűrés, csak egy egyszerű delay alapú debounce a gombhoz. Bekötés: - Enkóder CLK (A) -> D2 - Enkóder DT (B) -> D3 - Enkóder SW (gomb) -> D4 - Enkóder GND -> GND - VCC -> 3.3–5 V */ #define CLK_PIN 2 #define DT_PIN 3 #define SW_PIN 4 int counter = 0; // forgatással változó számláló int lastCLK; // előző CLK érték eltárolása az élérzékeléshez void setup() { Serial.begin(9600); // Soros monitor indítása pinMode(CLK_PIN, INPUT); // CLK bemenet pinMode(DT_PIN, INPUT); // DT bemenet pinMode(SW_PIN, INPUT_PULLUP); // Gomb bemenet belső felhúzóval lastCLK = digitalRead(CLK_PIN); // Kezdeti CLK állapot elmentése } void loop() { int currentCLK = digitalRead(CLK_PIN); // aktuális CLK érték // Ha változott a CLK (fel- vagy lefutó él), akkor irányt nézünk if (currentCLK != lastCLK) { if (digitalRead(DT_PIN) != currentCLK) { counter++; // egyik irány Serial.print("Irany: jobbra | Pozicio: "); } else { counter--; // másik irány Serial.print("Irany: balra | Pozicio: "); } Serial.println(counter); } lastCLK = currentCLK; // új referencia érték // Ha a gomb lenyomódik (LOW, mert INPUT_PULLUP-ot használunk) if (digitalRead(SW_PIN) == LOW) { Serial.println("Kapcsolo lenyomva"); delay(200); // egyszerű, blokkoló debounce a gombhoz } } |
A tesztkód futtatása közben a soros monitor egyfajta ablakot nyit az Arduino működésébe: valós időben figyelhető meg, hogyan reagál a mikrokontroller a forgatásra és a gombnyomásra. Az enkóder jobbra vagy balra forgatásakor azonnal megjelenik a detektált irány és a pozíció számláló aktuális értéke. Ez nemcsak látványos, hanem hasznos is – különösen kezdő Arduino-használóknak –, mert minden mozdulat visszajelzésre kerül a képernyőn. Ha például az irány fordítva jelenik meg, ebből következtethető, hogy a CLK és DT vezetékek felcserélve lettek bekötve.

A nyomógomb működése is hasonlóképp megfigyelhető: minden lenyomás külön soros üzenetet generál, amivel azonnal ellenőrizhető a kapcsoló működése. Ez ideális menük vezérlésére, beállítások jóváhagyására, vagy egyszerű visszajelzésre a felhasználói interakcióról.
Az egész mechanizmus jól bemutatja, mennyi információ nyerhető ki egyetlen kis eszközből – forgásirány, lépésszám és gombállapot. Ezek mindegyike megjeleníthető és kiértékelhető a soros monitor segítségével. Így nemcsak működéstesztként, hanem tanulási céllal is jól alkalmazható.
Mégis, milyen problémák lehetnek mégis az enkóderrel?
A KY-040 encoder működése első ránézésre nem tűnik bonyolultnak – elfordítod, vagy megnyomod a gombot, és az Arduino érzékeli a változást. Ez a működés nagyon látványos lehet, különösen akkor, ha most ismerkedsz a mikrokontrollerek világával. Azonban amikor élesben próbálod használni, például egy menürendszer irányításához, hangerő szabályzáshoz vagy egyéb felhasználói vezérléshez, hamar előjöhetnek kisebb, de bosszantó hibák. Az egyik leggyakoribb ilyen jelenség az úgynevezett bouncing, ami magyarul prellegés: azt jelenti, hogy a gomb vagy az enkóder nem ad tiszta, egyértelmű jelet az Arduino felé. Ennek oka a mechanikus érintkezők bizonytalansága: egyetlen nyomás vagy elfordítás nemcsak egy, hanem több nagyon rövid idejű jelszint-változást okozhat. Ezért a mikrokontroller gyakran többször is érzékeli ugyanazt az eseményt – még akkor is, ha te csak egyszer nyomtad meg vagy fordítottál a tekerőjén.
A legegyszerűbb és leggyorsabb megoldás erre egy rövid időzítés (delay(50)), amit a programkódban lehet elhelyezni minden bemenetvizsgálat után. Ez arra jó, hogy az Arduino kivárjon egy kicsit, és ne reagáljon azonnal minden apró ugrásra. Ez a módszer azonban leállítja a program többi részét is – vagyis amíg az Arduino várakozik, addig más művelet nem történik. Ez nem ideális akkor, ha több érzékelőt vagy eszközt is kezelni kell egyszerre. Éppen ezért egy fejlettebb módszer a millis()-alapú debounce. Ez nem állítja le a programot, hanem folyamatosan figyeli, hogy mennyi idő telt el az előző változás óta. Csak akkor engedi a következő eseményt, ha már elég idő eltelt – így hatékonyabban és gördülékenyebben működik.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | /* Program neve: Enkóder (rotary encoder) – kvadratúra olvasás és gombkezelés Verzió: 1.1 Dátum: 2025. augusztus 20. Szerző: Cseh Róbert Web: https://www.tavir.hu Leírás: A program egy mechanikus, nyomógombos forgó enkóder jelének stabil olvasását mutatja be. A két kvadratúra csatorna (CLK/A és DT/B) alapján meghatározzuk az elfordulás irányát, egy számlálót (counter) növelünk/csökkentünk, a gombnyomást pedig külön kezeljük. A bemenetekhez a belső felhúzó ellenállások (INPUT_PULLUP) vannak használva, ezért az enkóder közös lábát (COM) GND-re kell kötni. Egyszerű millis()-alapú zajszűrés/„debounce” működik mind a lépésekre, mind a gombra. A soros monitorra kiírjuk az irányt és a pozíciót. Bekötés (ehhez a sketch-hez): - Enkóder CLK (A) -> D2 - Enkóder DT (B) -> D3 - Enkóder SW (gomb) -> D4 - Enkóder COM -> GND - VCC -> 3.3–5 V (ha modul/megvilágítás szükséges) */ // -------------------- Beállítások -------------------- #define CLK_PIN 2 // Enkóder A/CLK jel #define DT_PIN 3 // Enkóder B/DT jel (FONTOS: külön láb a CLK-tól!) #define SW_PIN 4 // Enkóder nyomógomb // Állapotváltozók int counter = 0; // Számláló (pozíció) int lastCLK; // Előző CLK szint a változásérzékeléshez // Egyszerű zajszűrés/debouncing időzítők unsigned long lastStepMs = 0; // utolsó érvényes lépés ideje const unsigned long stepDebounce = 2; // ms — kvadratúra él zajszűrés (kicsi érték elég) unsigned long lastBtnMs = 0; // utolsó gombkezelés ideje const unsigned long btnDebounce = 200; // ms — gomb lenyomás szűrése void setup() { Serial.begin(9600); // Soros monitor indítása // Belső felhúzók: stabil bemeneti szintek, az enkóder COM a GND-re megy. pinMode(CLK_PIN, INPUT_PULLUP); pinMode(DT_PIN, INPUT_PULLUP); pinMode(SW_PIN, INPUT_PULLUP); // Gombnál LOW = lenyomva // Kezdeti állapot mentése a változásfigyeléshez lastCLK = digitalRead(CLK_PIN); Serial.println(F("Enkoder teszt indul. Forgasd az enkodert, nyomd meg a gombot!")); } void loop() { // ---- Enkóder lépések olvasása ---- int currentCLK = digitalRead(CLK_PIN); // Élérzékelés: csak akkor dolgozunk, ha változott a CLK (fel- vagy lefutó él) if (currentCLK != lastCLK) { unsigned long now = millis(); // Gyors zajszűrés: figyelmen kívül hagyjuk a nagyon sűrű történéseket if (now - lastStepMs >= stepDebounce) { // Kvadratúra logika: // Ha a DT eltér az új CLK szinttől → egyik irány (pl. jobbra), különben a másik (balra). if (digitalRead(DT_PIN) != currentCLK) { counter++; Serial.print(F("Irany: jobbra | Pozicio: ")); } else { counter--; Serial.print(F("Irany: balra | Pozicio: ")); } Serial.println(counter); lastStepMs = now; } // Frissítjük a referenciát a következő élhez lastCLK = currentCLK; } // ---- Gomb olvasása (nyomásérzékelés) ---- // INPUT_PULLUP mellett a gomb lenyomása LOW szintet ad. if (digitalRead(SW_PIN) == LOW) { unsigned long now = millis(); if (now - lastBtnMs >= btnDebounce) { Serial.println(F("Kapcsolo lenyomva")); lastBtnMs = now; // Ha szeretnéd, itt nullázhatod a számlálót: // counter = 0; // Serial.println(F("Szamlalo nullazva")); } } // A loop gyors, nincs szükség extra delay-re. } |
További, kissé összetettebb problémák is felmerülhetnek a KY-040 encoder használata közben, különösen akkor, ha már nem csak egyszerű tesztelésről, hanem valós alkalmazásról van szó. Ilyen gond lehet például, ha gyorsan forgatjuk az enkódert, és az Arduino nem érzékeli minden lépést, vagy esetleg rossz irányt érzékel. Ezt nevezzük jelkimaradásnak vagy hibás irányérzékelésnek, és gyakran előfordul, ha az enkóder nem ipari minőségű, mint például a KY-040.
Ezek a hibák már túlmutatnak az alapok szintjén, és olyan mélyebb elektronikai és programozási ismereteket igényelnek, amelyekre egy egyszerű tesztprogram már nem ad teljes választ. Itt jönnek képbe az olyan haladó megoldások, mint az interruptra épülő megszakításkezelés, ahol az Arduino azonnal reagál minden bemeneti változásra, vagy az állapotgép (state machine), amely lépésről lépésre követi a jelek változását, és így pontosabban tudja értelmezni, mi történik. A fizikai zajszűrés, például kis kondenzátorokkal a bemeneteken, szintén sokat segíthet a hibák csökkentésében.
Ezek már az enkóder használat mélységei, amelyekről részletesen a TavIR Tudástárban a Mélyvíz sorozatban lehet olvasni. Itt konkrét példák, részletes magyarázatok és működő megoldások várnak, ha szeretnéd még jobban megérteni és irányításod alá vonni az enkóder működését. →Mélyvíz – gyors forgatás és bouncing kezelése KY-040-nel.
De mégis mire jó?
A KY-040 forgó enkóderrel való első találkozás pont olyan volt, mint egy véletlenül nyitva hagyott ajtó: egyszerűségében rejlett az ereje. Egy apró alkatrész, amely nem csak forog, hanem kattintható is – és mindezt az Arduino azonnal érzékeli. Amikor először próbára lett kötve, világossá vált, mennyi minden vezérelhető egyetlen tekerőgombbal. Innen indult a mélyebb felfedezés: irányérzékelés, pozíciókövetés, és akár komplett menürendszerek építése. A gyorsteszt nemcsak azt mutatta meg, hogy működik – hanem azt is, mire képes.
Gyakran ismételt kérdések
Kérdés: Mire használható a KY-040 rotary encoder Arduino projekteknél, és miben különbözik egy hagyományos potmétertől?
Válasz: A KY-040 rotary encoder elsősorban forgásérzékelésre szolgál – digitális jelekkel dolgozik, nem analóg feszültséggel, mint a potméter. Ez azt jelenti, hogy léptetve érzékeli az elfordulás irányát és számát, így tökéletes választás menük léptetésére, értékek változtatására vagy akár felhasználói visszajelzésre (pl. beállítási mód kiválasztása, megerősítés). Mivel a tengelye lenyomható, egyetlen modul képes helyettesíteni akár három gombot (fel, le, OK), ami helyszűkésnél vagy egyszerűsített vezérlésnél ideális.
Kérdés: Hogyan működik a kvadratúra jel, és mi alapján állapítja meg az Arduino a forgás irányát?
Válasz: A KY-040 két digitális kimenetet generál (CLK és DT), amelyek kvadratúra (négyfázisú) impulzusokat bocsátanak ki – vagyis nem egyszerre váltanak állapotot, hanem fáziseltolással. Az Arduino ezek időbeli sorrendje alapján határozza meg a forgás irányát. Ha például a CLK jel változik előbb, és a DT más állapotban van, az egy irányt (pl. jobbra) jelent, ha fordítva, akkor a másikat (pl. balra). Ez a megoldás nemcsak irányt, hanem sebességet is mérhetővé tesz, ha gyors impulzuselemzés történik.
Kérdés: Mi az a bouncing, és miért jelent problémát az enkóder használata közben?
Válasz: A bouncing (más néven prellegés) mechanikus kapcsolók tipikus jelensége, amikor egyetlen kapcsolási művelet (pl. gombnyomás vagy tekerés) nem egyetlen tiszta jelváltozást, hanem több rövid impulzust generál. Ez a KY-040 esetén hibás értelmezést okozhat az Arduino oldalán, például többszörösen számolt lépéseket, vagy téves gombérzékelést. A leggyakoribb szoftveres megoldás a késleltetés beiktatása (delay(50)), illetve egy fejlettebb, nem blokkoló megközelítés a millis() alapú időzítés. Hardveres megoldásként kis értékű kondenzátorokat (pl. 100nF) alkalmazhatunk a bemeneti lábak és a GND közé, amivel a fizikai zaj jelentős része kiszűrhető.
Kérdés: Milyen tesztkódot és bekötést használjak, ha most kezdem a KY-040 modul használatát Arduino-val?
Válasz: A kezdéshez érdemes egy alap tesztkódot futtatni, amely számlálja a lépéseket és kiírja a forgásirányt, valamint figyeli a gomb lenyomását. A cikk két verziót is bemutat: egy egyszerű delay-es debounce változatot, valamint egy fejlettebb, millis()-alapú verziót, amely már stabilabb működést biztosít. A bekötésnél fontos, hogy a CLK, DT és SW jelek digitális bemenetekre kerüljenek, és a belső INPUT_PULLUP mód legyen használva. A modul GND és VCC lábait megfelelően kell csatlakoztatni (5V vagy 3.3V, típustól függően). A soros monitoron így azonnal nyomon követhetjük a forgás és gombnyomás eseményeket.
Kérdés: Milyen gyakori hibák fordulhatnak elő a KY-040 használata során, és hogyan lehet ezeket elkerülni?
Válasz: A leggyakoribb hibák közé tartozik a hibás forgásirány-érzékelés (gyakran a CLK és DT vezetékek felcseréléséből ered), a jelkimaradások gyors forgatásnál, illetve a kapcsoló hibás működése – amely legtöbbször elhasználódásra vagy bounce-ra vezethető vissza. Ezen hibák megelőzhetők pontos bekötéssel, zajszűrés beépítésével és szoftveres időzítéssel. Haladó esetekben érdemes megszakítás-alapú (interrupt) megoldásokat alkalmazni, vagy állapotgépes logikát építeni, amely pontosabban követi a jelek változását és kiküszöböli az átmeneti hibákat.
Kérdés: Hol találok további útmutatókat a rotary encoder használatáról Arduino-val?
Válasz: A TavIR Tudástárban több részletes cikk és projektleírás is foglalkozik a témával. Érdemes elindulni a gyűjtőoldalon, ami az enkóderekkel kapcsolatos: →KY-040 és egyéb enkóderek. Ezek lépésről lépésre mutatják be az elméletet, a bekötést, valamint a működő kódokat és komplett alkamazásokat.
Források
– Rotary encoder a TavIR WebShopban [TavIR WebShop]
– Rotary Encoders – Alapozó [Arduino.cc]





