Nyomógomb figyelés

Tartalom:

  • Nyomógomb állapotának figyelése, megnyomás esetén különböző állapotok létrehozása, prellmentesítés
  • Nyomógomb állapotának prellmentes létrehozása változóban
  • Nyomógomb többszöri megnyomásakor be és kikapcsolt állapotok létrehozása változóban
  • Nyomógomb többszöri megnyomásakor változó értékének növelése, max. elérésekor nullázás
  • Nyomógomb megnyomásakor beállítható ideig nyomva tartott állapot előállítása változóban (késleltetett nyomógomb elengedés)
  • Mindezek loop() lényegi lassítása nélkül

———————————————————————————

A nyomógombok figyelésére létrehoztam egy általános függvényt, ami figyeli egy Arduino bemenet állapotát, feltételezve, hogy arra nyomógombot kötöttünk, és sokféle választ előállít a nyomógomb megnyomása hatására. Prellmentesít! Ez volt a függvény első funkciója. Aztán rá jöttem, hogy nem csak a prellmentesítésre használom gyakran, a nyomógombokat váltó kapcsolónak is szoktam használni. Megnyomom bekapcsol, megint megnyomom kikapcsol. Ez volt a második funkció. Egyszer olyan működés is kellett, hogy megnyomtam a gombot, és ha elengedtem, a program úgy csinált, mintha másodpercekig nyomva tartottam volna. Mivel alapvetően nagyon lusta vagyok, ez agyon tetszett nekem. Utoljára azt írtam bele, hogy minden gombnyomással növekedjen egy számláló (a függvény visszaadott) értéke. Ráadásul beállítható a megnyomásonkénti növekmény, és az is, mekkora maximális értéknél nullázódjon, azaz újra induljon a számlálás.

Próbáltam bőven ellátni kommentekkel, hogy érthető legyen. A függvénynek elég sok paramétere van, ezeknek a leírása is benne a forrásban. Azt is próbáltam kideríteni, hogy mennyire lassítja le a programot a használata. A folyamatosan ciklikusan futó loop-ból még így is több mint 30.000 fut végig másodpercenként, ami megnyugtató.

/**************************************************************************************************************
 * Ez a program gyakorlatban is felhasználható nyomógomb figyelő és művelet végző függvényt tartalmaz.        *
 * A programba beépített függvény sokféle paraméterrel hívható meg. Ha kell prellmentesít. Visszaadathatja    *
 * egy nyomógomb állapotát (prellmentesen), vagy akár visszaadott értéke válthatja is  állapotát              *
 * minden gombnyomáskor. A visszaadott érték állapotát automatikusan visszaejthetjük 0-ra a gombnyomást       *
 * követő megadott időn belül. A gombnyomások számát is visszaadhatjuk a függvény visszatérő értékeként. Ez a *
 * növelés akár többszörös is lehet, és beállíthatunk maximumot is.                                           *
 **************************************************************************************************************/

// a függvény használatához szükséges globális segéd változók
byte bemenet_allapot=0;        //bemenet pillanatnyi állapota (prellmenetes állapotban kerül beállításra)       
int kimenet_allapot;           //kimenet állapota, ez a függvény által visszaadott érték, ami 0,1,1-255 értékeket vehet fel
                               //0-kikapcsolt állapotot ad vissza, 1-bekapcsolt állapotot ad vissza, 
                               //1-255 amikor számlált állapotot ad vissza (setup=3)
byte bemenet_elozo_allapot=0;  //bemenet előző állapota segéd változó, amivel felderíthetjük a 
                               //fel vagy lefutó álét a prellmentes nyomógomb állapotváltozásnak
byte prell_tmp=0;              //bemenet prell figyeléshez segéd változó  
long prell_time=0;             //bemenet prellmentesítéshez az első kontaktus időpontja      
long kikapcs_ido_tmp=0;        //kimenet kikapcsolási időhöz segéd változó (setup=2 esetén)  

//a bemutató program működéséhez szükséges változók
byte szimulalt_nyomogomb;  //a függvény által szimulált prellmentes nyomógomb pillanatnyi állapota 
byte elozo_allapot;        //a függvény által visszaadott szimulált nyomógomb állapota az előző 
                           //ciklusban (segítségével csak akkor írjuk ki a visszaadott értéket, 
                           //ha változás van az állapotban)
long ciklus_szamlalo;      //minden loop() ciklusban növeljük az értékét, mert kíváncsiak vagyunk, hány ciklus zajlik le egy másodperc alatt
long ido;                  //ebben tároljuk az utolsó idő számláló kiírás időpontját, hogy 1000msec (1 sec) múlva újra kiírhassuk annak értékét
int szamlalo;
bool elozoallapot;

void setup() 
{
  pinMode(3,INPUT);      //nyomógomb bemenet
  digitalWrite(3,HIGH);  //felhúzó ellenállás bekapcsolva
  pinMode(11,OUTPUT);    //led kimenet, digitálisan és analóg is fogjuk vezérelni
  digitalWrite(11,LOW);  //led nem világít
  Serial.begin(9600);    //soros port bekapcsolása
}

void loop() 
{
  ciklus_szamlalo=ciklus_szamlalo+1;    //minden ciklusban növeljük az értékét, így ha 1 másodpercenként kiírjuk 
                                        //az értékét, megtudhatjuk hány ciklus zajlott le
  /*
   * Nyomógomb kezelő programrész, mely ellátja egy nyomógomb prellmentesítését, és a kimenet állapotaként
   * többféle állapotot képes visszaadni. Ezzel közvetlenül vezérelhető pl. egy kimenet
   * Bemeneő paraméterek sorrendben:
   * - válasz mód: a visszaadott érték lehetséges viselkedése
   *                  0-lemásolja a nyomógomb állapotát (prellmentesít)
   *                  1-váltó kapcsoló, minden nyomógomb lenyomáskor vált az értéke 0 és egy között. Felfutó
   *                    vagy lefutó élet külön be lehet állítani
   *                  2-minden nyomógomb lenyomást követően beállítható idő után "kikapcsol" a visszaadott érték.
   *                  3-minden gombnyomáskor növeli a kimenet értékét, megadható a növekedés nagysága, és egy 
   *                    maximum is, amit elérve nullázódik a visszaadott érték
   * - bemenet sorszáma: (Arduino bemenet sorszám, amire  nyomógombot kötöttük)
   * - bemenet prellmenetsítése: 0-nem prellmentesít, 1-prellmenetsít (50ms késés a kontaktus után)
   * - változást kiváltó esemény: 0-nyomógomb lenyomáskor változik a kimenet, 1-nyomógomb elengedéskor változik a kimenet
   * - setup=2 esetén időzítési idő msec-ben
   * - setup=3 esetén megnyomásonként növekedés (1-255-ig, mert byte változó)
   * - setup=3 esetén a maximális érték, ahol nullázódik a kimenet értéke
   */
  szimulalt_nyomogomb=multi_button(0,3,1,0,3000,70,255);  //meghívjuk a függvényt, és a visszaadott értéket a szimulalt_nyomogomb változóba töltjük
  if (elozo_allapot!=szimulalt_nyomogomb)                 //csak akkor írunk a soros portra, ha valami változik
  {
    Serial.println(szimulalt_nyomogomb);                  //kiírjuk a soros portra a visszaadott értéket, de csak akkor, ha változik
  }
  if (szimulalt_nyomogomb<2)
    {digitalWrite(11,szimulalt_nyomogomb);}               //a visszaadott érték megjelenítése a led-el, ha az érték 0 és 1 
  else {analogWrite(11,szimulalt_nyomogomb);}             //a visszaadott érték megjelenítése led-el, ha a visszaadott érték 2-255 között van
  elozo_allapot=szimulalt_nyomogomb;                      //ahhoz kell, hogy csak a visszaadott érték változásakor írjunk a soros portra, különben a soros port
                                                          //nagyon lelassítja a működést

  //az itt következő programrészek ahhoz kellenek, hogy megtudhassuk hány ciklust hajt végre a loop
  //vagyis mennyit lassít az a függvény (kb 80.000ciklust csinál egy Arduino UNO üresen
  //Ezt a programrészt csak a valasz_mod 0-ban lehet használni, mert a sima nyomógomb megnyomásokat számolja
  if (szimulalt_nyomogomb==0 and elozoallapot==1)   //azt érzékeljük, amikor az előző ciklusban még nem volt megnyomva 
                                        //a nyomógomb, most pedig igen. Ez a bemeneten egy "lefutó él" érzékelést jelent
  {
    szamlalo=szamlalo+1;                //növeljük a számláló értékét, mert a nyomógomb le lett nyomva
    Serial.println(szamlalo);           //kiírjuk a soros portra a számláló állapotát
  }
  elozoallapot=szimulalt_nyomogomb;                 //tároljuk a ciklus elején beolvasott bemeneti állapotot

  if (ido+1000<millis())                //ha 1 sec telt el az előző idő változóban tárolt időpont óta, akkor
  {
    Serial.println(ciklus_szamlalo);    //kiírjuk ciklus_szamlalo értékét a soros portra
    ciklus_szamlalo=0;                  //töröljük ciklus_szamlalo értékét, újra kezdjük a számlálást
    ido=millis();                       //tároljuk a millis() értékét, így az if-ben vizsgálhatjuk, hogy eltelt-e 1 másodperc
  }

}


byte multi_button(byte valasz_mod,byte bemenet,byte prellmentesit,byte felfutoel,int  aut_kikapcs_ido, byte novekedes, byte max_ertek) 
/****************************************************************************************************************************
 * Bemenő paraméterek sorrendben:                                                                                           *
 * valasz mod: ezzel állítjuk be, hogy milyen eseményt eredményez a nyomógomb lenyomása                                     *
 * bemenet: Az arduino bemenet száma, amire a nyomógombot kötöttük                                                          *
 * prellmentesit: Ha 1, akkor prellmentesítést végez, 0 esetén nem prellmentesít, csak másolja a nyomógomb állapotát        *
 * felfutoel: A kimenet változása a nyomógomb megnyomásakor (0-felfutó él), vagy elengedésekor következzen be (1-lefutó él)  *
 * aut_kikapcs_ido: valasz_mod=2 esetén a visszaadott értéket 0-ra állítja a megadott időn belül (msec)                      *
 * novekedes: valasz_mod=3 esetén a gombnyomásonként ennyivel növeli a visszaadott értéket                                  *
 * max_ertek: valasz_mod=3 esetén ennél az értéknél nullázza a visszaadott értéket                                            *
 *                                                                                                                          *
 * Visszaadott érték lehetséges állapotai:                                                                                  *
 * valasz_mod=0 esetén: 0-nincs lenyomva a nyomógomb, 1-le van nyomva a nyomógomb                                           *
 * valasz_mod=1 esetén: 0,1 minden lenyomáskor változik                                                                     *
 * valasz_mod=2 esetén: 0,1 gomb lenyomásakor 1, és ezt követően aut_kikapcs_ido érteke után automatikusan visszaesik 0-ra  *
 * valasz_mod=3 esetén: 0-255 gombnyomásonként felfelé számol, novekedes változóban beállított érték a növekmény, max_ertek *
 *                      változóban beállított érték elérésekor visszaesik a kimenet értéke 0-ra.                            *
 ****************************************************************************************************************************/
{ 
  //bemenet lekövetése a paraméterek alapján
  if (prellmentesit==1) {
    if (felfutoel==0)  //felfutó élre fognak bekövetkezni a visszaadott érték változásai
      {
      if (bemenet_allapot==0 and digitalRead(bemenet)==LOW and prell_tmp==0)                             //első lenyomás érzékelése
        {prell_tmp=1;prell_time=millis();} 
      if (bemenet_allapot==0 and digitalRead(bemenet)==LOW and prell_tmp==1 and millis()>prell_time+50)  // már 50msecv óta nyomva van, most már biztos, hogy lenyomták és nem prellezik
        {bemenet_allapot=1;prell_tmp=0;} 
      if (bemenet_allapot==1 and digitalRead(bemenet)==HIGH and prell_tmp==0) //első elengedés érzékelése
        {prell_tmp=1;prell_time=millis();} 
      if (bemenet_allapot==1 and digitalRead(bemenet)==HIGH and prell_tmp==1 and millis()>prell_time+50) // már 50msecv óta elengedve, most már biztos, hogy elengedték és nem prellezik
        {bemenet_allapot=0;prell_tmp=0;} 
      }
    else   //lelfutó élre fognak bekövetkezni a visszaadott érték változásai
    {
      if (bemenet_allapot==0 and digitalRead(bemenet)==HIGH and prell_tmp==0)  //első elengedés érzékelése
        {prell_tmp=1;prell_time=millis();} 
      if (bemenet_allapot==0 and digitalRead(bemenet)==HIGH and prell_tmp==1 and millis()>prell_time+50) // már 50msecv óta elengedve, most már biztos, hogy elengedték és nem prellezik
        {bemenet_allapot=1;prell_tmp=0;} 
      if (bemenet_allapot==1 and digitalRead(bemenet)==LOW and prell_tmp==0)  //első lenyomás érzékelése
        {prell_tmp=1;prell_time=millis();} 
      if (bemenet_allapot==1 and digitalRead(bemenet)==LOW and prell_tmp==1 and millis()>prell_time+50) // már 50msecv óta lenyomták, most már biztos, hogy elengedték és nem prellezik
        {bemenet_allapot=0;prell_tmp=0;} 
    }
  }
  else  //nem kell prellmentesíteni, csak másoljuk a nyomógombot
  {
    if (digitalRead(bemenet)==0) {if (felfutoel==0) {bemenet_allapot=0;} else {bemenet_allapot=1;}}
    else {if (felfutoel==0) {bemenet_allapot=1;} else {bemenet_allapot=0;}}
  }
  switch (valasz_mod) {   //kimenet vezérlése a paraméterek alapján
    case 0: 
      kimenet_allapot=bemenet_allapot;break;
    case 1:
      if (bemenet_allapot==1 and bemenet_elozo_allapot==0) 
        {if (kimenet_allapot==0) {kimenet_allapot=1;} else {kimenet_allapot=0;}}
      bemenet_elozo_allapot=bemenet_allapot;
      break;
    case 2:
      if (bemenet_allapot==1 and bemenet_elozo_allapot==0){
        if (kimenet_allapot==0) {kimenet_allapot=1;kikapcs_ido_tmp=millis();} 
        else {kimenet_allapot=0;kikapcs_ido_tmp=millis();}
      }
      if (millis()>kikapcs_ido_tmp+aut_kikapcs_ido) {
        kimenet_allapot=0; 
      }
      bemenet_elozo_allapot=bemenet_allapot;
      break;
    case 3:
      if (novekedes==0) {novekedes=1;}
      if (bemenet_allapot==1 and bemenet_elozo_allapot==0){
         kimenet_allapot=kimenet_allapot+novekedes;
         if (kimenet_allapot>max_ertek) {kimenet_allapot=0;}
      }
      bemenet_elozo_allapot=bemenet_allapot;
      break;
    } 
  return kimenet_allapot;
}


/*********************************
Futási eredmény a sorosporton:
32113
32104
1
31833
0
1
31811
32072
1
31768
0
2
31850
32104
1
31793
0
3
31863
32072
32105
32104
32105
32104
*************************************/

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!