Rotary kapcsoló

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)

Mennyire volt hasznos amit olvastál? Értékelés után szövegesen is leírhatod megjegyzéseidet és véleményedet!

Kattints egy csillagra az értékeléshez!

Szövegesen is leírhatod véleményedet! Ha kérdésed van, ne felejtsd el megadni az email címedet!