Tartalom:
- Rotary kapcsoló működési elve
- Használatát bemutató példa program
- Prelles rotary típus használata, prellmentesítés dalay() nélkül
————————————————————————————
A rotary kapcsoló egy igen hasznos adatbeviteli eszköz. Egy forgatógomb, amivel fényerőt (hangerőt) szabályozhatunk, de más hasznos dolgokra is használhatjuk. Én pl. elsőként az ABC betűinek bevitelére használtam. Gyorsabb a forgatógombot tekergetni, mint két különálló gombot nyomogatni. Így néz ki egy rotary gomb:
A tengely forgatás közben érezhetően kis pici pozíciókban áll meg. Az általam használt kapcsoló 30 ilyen pozícióval rendelkezik.
A jeladó belsejében két kapcsoló van (és egy ezektől független harmadik, ami akkor kapcsol, amikor megnyomjuk a tengelyt). Amikor a kapcsoló egy rögzített helyzetben megáll, mindkét kapcsoló nyitott állapotba kerül. Ha valamelyik irányba forgatjuk, akkor az egyik kapcsoló előbb kapcsol, mint a másik. Innen kideríthető a kapcsolás iránya:
Az alábbi ábra szemlélteti a kapcsoló kialakításának módját.
Amint látható, az A és B kontaktus szöghelyzete olyan, hogy:
- A tengely óramutató járásával megegyező irányú elforgatásával az A és C kivezetések kapcsolnak először.
- A tengely óramutató járásával ellentétes irányú forgatásakor a B és C kivezetések kapcsolnak először.
Ezt a működést az alábbi ábra szemlélteti:
Lényegében azt kell egy programmal észrevennünk, hogy, hogy melyik kapcsoló vált állapotban először, és ez meghatározza a forgásirányt. Ha A változik először, a kapcsoló az óramutató járásával megegyező irányba forog. Ha B változik először, akkor a kapcsoló az óramutató járásával ellentétes irányban forog.
A rotary kapcsoló kivezetései:
A modul úgy lett kialakítva, hogy alacsony a kimenet, amikor a kapcsolók zárt állapotban vannak és magasak, amikor a kapcsolók nyitottak. A zárt állapot a megfelelő kivezetést földre húzza le, míg nyitott állapotban a kivezetést egy felhúzó ellenállás a tápfeszültségre húzza fel. Az általam használt rotary nem prelles. Az alább található példaprogram szépen egyenként számol fel és lefelé a forgásiránytól függően. Minden bizonnyal nem véletlen, hogy 5V-ra és GND-re is szüksége van. Esetleg valamilyen optikai érzékelő lehet benne!
Korábban említettem, hogy van egy harmadik kapcsoló is. Ez akkor záródik, ha a tengelyt megnyomjuk. Így a forgatást követően azonnal jelzést adhatunk a programnak, ha a forgatással kiválasztottuk a megfelelő menüpontot, betűt stb.
Itt egy példaprogram a használatra. A program egy számláló értékét változtatja a rotary tengelyének tekergetésével, fel és le számlál a tekergetés iránya szerint :
int szamlalo = 0; //szamlalja a pozició váéltások számát //előjelesen (előre +, hátra -) int rotary_CLK_elozo; //Utolsó állapota az a kivezetésnek int rotary_CLK; //A kivezetés aktuális állapota int rotary_DT; //B kivezetés aktuális állapota int rotary_PUSSH; //nyomógomb kivezetés állapota void setup() { pinMode (3,INPUT); //rotary CLK kivezetés pinMode (4,INPUT); //rotary DT kivezetés pinMode (5,INPUT); //rotary nyomógomb kivezetés digitalWrite(5,HIGH); //felhúzó ellenállás bekapcsolása pinMode (8,OUTPUT); //rotary CLK állapotának megjelenítéséhez pinMode (9,OUTPUT); //rotary DT állapotának megjelenítéséhez pinMode (10,OUTPUT); //rotary DT állapotának megjelenítéséhez rotary_CLK_elozo = digitalRead(3); Serial.begin (9600); } void loop() { rotary_CLK = digitalRead(3); rotary_DT = digitalRead(4); rotary_PUSSH = digitalRead(5); digitalWrite(8,rotary_CLK); digitalWrite(9,rotary_DT); digitalWrite(10,rotary_PUSSH); if (rotary_CLK and !rotary_CLK_elozo){ //csak a CLK kivezetés //felfutó élét figyeljük, //mert nyugalmi helyzetben // CLK=1 felfutó él csak // tekergetés közben fordul elő if (rotary_DT) { // DT kivezetés 1 - Óramutató járásával //megegyezõ irányban forgatunk szamlalo--; } else { // DT kivezetés 0, óramutató játrásával //ellentétesen forgalunk szamlalo++; } Serial.println(szamlalo); } rotary_CLK_elozo = rotary_CLK; }
A fentiekben leírtak igazak és nagyon jól működik az a rotary kapcsoló, amit szállítási költséggel együtt egy magyar elektronikai alkatrész áruházból rendeltem. Mivel nem akartam újra 1500Ft-ot költeni egy rotary kapcsolóra, a silány kínai termékre vetemedtem, mert az Aliexpress-en 5db-ot kaptam 600Ft-ért szállítással együtt! Igaz, ez még az ÁFA fizetés és Posta díjszabás előtt volt. Így néz ki:
Ezen a képen nem CLK-nak és DT-nek nevezték el a kivezetéseket, hanem A-nak és B-nek. Jogos, mert mindegy, hogy melyiket tekintjük CLK-nak. Ha egy programot megírtunk és azt akarjuk, hogy ellentétesen működjön, elég a két kivezetést felcserélni, és pont fordítva fog számolni a program (a kis demó programomra gondolok, amit alább találsz meg).
Meglepetés is ért. Más kinézetű rotary kapcsolót kaptam, ami feltehetőleg gyengébb kivitelű. +5V már nem is kell neki, csak kontaktus jeleket ad, és prelles. Tekergetés közben a remek kis programom nem egyértelműen működik, néha (igazán csak néha) visszafele is számol, nem a tekergetés irányába. Mondjuk minden 50. katt esetén téveszt. Ennek oka, hogy a kontaktus jelet egy tárcsa állítja elő, amin az érintkezők pattognak egymáson, és ha nem várom meg, míg beáll a stabil kontaktus állapot, akkor téveszt a program. Nincs mit tenni, át kell alakítani a programot. Pofon egyszerű lenne betenni valahol a programban a felfutóél érzékelésekor egy kis késleltetést delay()-el, de nekem olyan környezetben kell a rotary kapcsoló, amiben a loop() erőteljesen dolgozik egy csomó feladattal, nem lehet delay()-el késlekedni. Ezért átalakítottam a programot. Az átalakítás lényege, hogy amikor egy felfutó élet érzékelek (a CLK kivezetés 0-ra húzza a bemenetet), akkor megjegyzem a millis() pillanatnyi értékét, és 1 millisec múlva nézem meg a másik rotary kivezetés állapotát. Fontos tudnivaló, hogy a rotary kapcsolóban a CLK kivezetés kontaktusát nagyon gyorsan követi a DT kivezetés kontaktusa, illetve nagyon rövid idővel előzi meg. A prell miatti kényszer várakozási idő 1msec, ennél nem kell hosszabb. Ezt kísérletezgetéssel állapítottam meg. Kipróbáltam 10msec-el, akkor már csak visszafelé számolt a program. Ha még az 1 millisec is hosszú lenne, akkor a micros() függvényt kellene használni, ami mikrosec-ben adja meg a bekapcsolás óta eltelt időt. De úgy tűnik, az én rotary kapcsolómmal és tekergetési képességeimmel elég az 1 millisec. A demó programból kihagytam minden felesleges részt, csak a rotary két kivezetésével foglalkoztam:
int szamlalo = 0; //számlálja a pozíció váltások számát //előjelesen (előre (óramutató járása) +, hátra -) long ciklus_szamlalo=0; //csak annak bizonyítására, hogy a loop zavartalanul fut tovább int rotary_CLK_elozo; //Utolsó állapota az a kivezetésnek int rotary_CLK; //CLK kivezetés aktuális állapota (bármelyik kivezetés lehet CLK) int rotary_DT; //DT kivezetés aktuális állapota long rotary_start; //felfutó élet találtunk a CLK kivezetésen, akkor bool rotary_ertekel=0; //az időzítés letelte után ennek az 1 értéke indítja a kiértékelést void setup() { pinMode (A0,INPUT); //rotary CLK kivezetés pinMode (A1,INPUT); //rotary DT kivezetés digitalWrite(A0,HIGH); //felhúzó ellenállás bekapcsolása digitalWrite(A1,HIGH); //felhúzó ellenállás bekapcsolása rotary_CLK_elozo = digitalRead(A0); //ez azért kell, hogy csak akkor történjen valami, ha tényleg forgatjuk a rotary kapcsolót Serial.begin (115200); } void loop() { rotary_CLK = digitalRead(A0); //kontaktus pillanatnyi állapota rotary_DT = digitalRead(A1); //kontaktus pillanatnyi állapota if (!rotary_CLK and rotary_CLK_elozo and !rotary_ertekel){ //a CLK kivezetés felfutó élét detektáltuk, és még nem történt kiértékelés rotary_start=millis(); //megjegyezzük a pillanatnyi időt ahhoz, hogy 1msec múlva ránézhessünk a kontaktusokra rotary_ertekel=1; //kiértékelés fog következni, ha letelt a várakozási idő } if (rotary_start+1<millis() and rotary_ertekel) { //ha eltelt 1msec és kiértékelést állítottunk be egy felfutó él után if (rotary_DT) {szamlalo--;} // DT kivezetés 1 - Óramutató járásával ellentétes irányban forgatunk else {szamlalo++;} // DT kivezetés 0, óramutató járásával megegyező irányba forgatunk rotary_ertekel=0; Serial.print(szamlalo); Serial.print(" ("); Serial.print(ciklus_szamlalo); Serial.println(")"); } rotary_CLK_elozo = rotary_CLK; //felfutóél kereséséhez ciklus_szamlalo++; }
Bekerült azonban egy változó annak bizonyítására, hogy valóban teker a loop, és csinálna valamit, ha kellene. Ez a számláló nagyokat halad előre, két rotary kattanás között.
Íme a futási eredmény a sorosporton:
06:52:56.821 -> 1 (82900)
06:52:57.408 -> 2 (128354)
06:52:57.826 -> 3 (164116)
06:52:58.228 -> 4 (194597)
06:52:58.482 -> 5 (213741)
06:52:58.730 -> 6 (235083)
06:52:59.031 -> 7 (258136)
06:52:59.185 -> 8 (267898)
06:53:00.089 -> 7 (341357)
06:53:00.190 -> 6 (348858)
06:53:00.337 -> 5 (360001)
06:53:00.491 -> 4 (372778)
06:53:00.591 -> 3 (380758)
06:53:00.739 -> 2 (393452)