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?

Kattints egy csillagra az értékeléshez!

Szövegesen is leírhatod véleményedet!