28. septembra 2022

Návod: Zapojenie klávesnice + kód

V jednom z predchádzajúcich blogov sme si ukázali ako jednoducho zapojiť segmentový displej. V dnešnom blogu si ukážeme jednoduchý program, pomocou ktorého na segmentovom displeji vypíšeme čísla stlačené na klávesnici. Budeme pracovať s klávesnicou 4×4 AVR 16 klávesov ako je na obrázku nižšie:

V blogu sa pokúsime vysvetliť princíp fungovania takejto klávesnice. Ak potrebujete klávesnicu len použiť a nie je pre Vás dôležité zistiť princíp fungovania, odporúčame prejsť nižšie na časť “Použitie knižnice”.

Princíp fungovania klávesnice

Na klávesnici sa nachádza 16 tlačidiel, usporiadaných v 4 riadkoch a 4 stĺpcoch. Vnútorný obvod v klávesnici vyzerá nasledovne:

Všetky riadky aj stĺpce sú v počiatočnej polohe, kedy žiadne tlačidlo nie je stlačené, elektricky rozpojené. Stlačením tlačidla sa riadok a stĺpec elektricky prepojí.

Aby sme zistili, v ktorom riadku sa stlačené tlačidlo nachádza, všetky piny napojené na stĺpce nastavíme ako “výstupné” a nastavíme na hodnotu HIGH. Piny napojené na riadky nastavíme ako “vstupné” a kontrolujeme, či a na niektorom z riadkov je taktiež hodnota HIGH. Ak na niektorom z riadkov je HIGH, znamená to, že jedno z tlačidiel v danom riadku je stlačené.

Následne podobným spôsobom zistíme v ktorom stĺpci bolo tlačidlo stlačené. Nastavíme piny stĺpcov ako “vstupné”, piny riadkov ako “výstupné” a výstup na HIGH. Prečítame na ktorom stĺpcovom pine je HIGH a tak zistíme stĺpec.

Takéto čítanie vykonáme v kóde hneď po sebe, takže prebehne rádovo v mikrosekundách a stihneme zaregistrovať, ktoré presne tlačidlo bolo stlačené.

Takto dokáže Arduino zistiť riadok aj stĺpec, v ktorom sa nachádza stlačené tlačidlo. Tabuľka nižšie popisuje, ktorý riadok a ktorý stĺpec sú nastavené na HIGH pri stláčaní jednotlivých tlačidiel klávesnice ak sú riadky a stĺpce pripojené podľa obrázka vyššie.

Ak nastavím stĺpec..a súčasne zistím, že…stlačené tlačidlo je…
Stĺpec 0 = HIGHRiadok 0 = HIGH1
Stĺpec 1 = HIGHRiadok 0 = HIGH2
Stĺpec 2 = HIGHRiadok 0 = HIGH3
Stĺpec 0 = HIGHRiadok 1 = HIGH4
Stĺpec 1 = HIGHRiadok 1 = HIGH5
Stĺpec 2 = HIGHRiadok 1 = HIGH6
Stĺpec 0 = HIGHRiadok 2 = HIGH7
Stĺpec 1 = HIGHRiadok 2 = HIGH8
Stĺpec 2 = HIGHRiadok 2 = HIGH9
Stĺpec 1 = HIGHRiadok 3 = HIGH0
Stĺpec 0 = HIGHRiadok 3 = HIGH*
Stĺpec 2 = HIGHRiadok 3 = HIGH#
Stĺpec 3 = HIGHRiadok 0 = HIGHA
Stĺpec 3 = HIGHRiadok 1 = HIGHB
Stĺpec 3 = HIGHRiadok 2 = HIGHC
Stĺpec 3 = HIGHRiadok 3 = HIGHD

Pri takomto spôsobe rozpoznávania stlačeného tlačidla môže nastať problém, ak máme stlačených viacero tlačidiel naraz alebo stláčanie je rýchle. Tieto problémy by sa dali vyriešiť komplexnejším programom alebo použitím prídavného hardvéru.

Zapojenie a program

Teraz si ukážeme ako zapojiť klávesnicu a 7-segmentový displej a ako napísať program, aby sa na displeji zobrazovali stlačené tlačidlá. 

Tabuľka nižšie popisuje, ktorý riadok/stĺpec zapojíme do ktorého pinu na Arduino doske. Označenie riadkov použijeme R1 až R4 a označenie stĺpcov C1 až C4.

Riadok/stĺpecPopisPin
R1Riadok 1 (hore)9
R2Riadok 28
R3Riadok 37
R4Riadok 4 (dole)6
C1Stĺpec 1 (vľavo)5
C2Stĺpec 24
C3Stĺpec 33
C4Stĺpec 4 (vpravo)2

Pomocou obrázku nižšie vieme určiť ktoré segmenty je potrebné rozsvietiť na zobrazenie jednotlivých číslic. Pre viac informácií odporúčame preštudovať náš predchádzajúci blog o segmentovkách.

Program:

//definujeme do ktorých pinov zapojíme jednotlivé segmenty 7-segmentoveho displeja
#define segA 11
#define segB 10
#define segDP A0
#define segC A1
#define segD A2
#define segE A3
#define segF 12
#define segG 13


//zapojenie riadkov a stĺpcov klávesnice do pinov
int R1 = 9;
int R2 = 8;
int R3 = 7;
int R4 = 6;
int C1 = 5;
int C2 = 4;
int C3 = 3;
int C4 = 2;

//piny, do ktorých je zapojený 7-segmentový displej, nastavíme na hodnotu OUTPUT
void setup() {
  for(int i = 0 ; i < 14; i++) {
    pinMode(i, OUTPUT);
  }

  pinMode(A0, OUTPUT); //desatinná bodka, pre náš účel nie je tento pin potrebný
  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
}

//podľa toho, ktorým riadkom a stĺpcom preteká prúd vypíšeme čísla na displeji. 
//ak nestlačíme žiadne tlačidlo, na displeji nebude svietiť žiadny segment
void loop() {
   int stlpec = zisti_ktory_stlpec(); //==2
   int riadok = zisti_ktory_riadok(); //==2  

   if(riadok == 1 && stlpec == 1 ) {
     vypis_jednotku();
   }
   if(riadok == 1 && stlpec == 2 ) {
     vypis_dvojku();
   }
   if(riadok == 1 && stlpec == 3 ) {
     vypis_trojku();
   } //podobnym spôsobom by sme vedeli vypísať aj ďalšie čísla
   else {
     vynuluj_segmentovku();
   }
}


int zisti_ktory_riadok() { 
  pinMode(C1, OUTPUT);
  pinMode(C2, OUTPUT);
  pinMode(C3, OUTPUT);
  pinMode(C4, OUTPUT);

  digitalWrite(C1,LOW);
  digitalWrite(C2,LOW);
  digitalWrite(C3,LOW);
  digitalWrite(C4,LOW);

  pinMode(R1, INPUT_PULLUP);
  pinMode(R2, INPUT_PULLUP);
  pinMode(R3, INPUT_PULLUP);
  pinMode(R4, INPUT_PULLUP);

  if(digitalRead(R1) == LOW) {
    return 1;
  }
  if(digitalRead(R2) == LOW) {
    return 2;
  }
    if(digitalRead(R3) == LOW) {
    return 3;
  }
  if(digitalRead(R4) == LOW) {
    return 4;
  }
  return 0;
}

int zisti_ktory_stlpec() { 
  pinMode(R1, OUTPUT);
  pinMode(R2, OUTPUT);
  pinMode(R3, OUTPUT);
  pinMode(R4, OUTPUT);

  digitalWrite(R1, LOW);
  digitalWrite(R2, LOW);
  digitalWrite(R3, LOW);
  digitalWrite(R4, LOW);

  pinMode(C1, INPUT_PULLUP);
  pinMode(C2, INPUT_PULLUP);
  pinMode(C3, INPUT_PULLUP);
  pinMode(C4, INPUT_PULLUP);

  if(digitalRead(C1) == LOW) {
     return 1;
  }
  if(digitalRead(C2) == LOW) {
     return 2;
  }
  if(digitalRead(C3) == LOW) {
     return 3;
  }
  if(digitalRead(C4) == LOW) {
     return 4;
  }  
  return 0;
}



//funkcia zabezpečujúca aby segmenty displeja boli zhasnuté
void vynuluj_segmentovku () { 
  for (int i = 10; i < 14; i++) {
    digitalWrite(i, LOW);
  }

  digitalWrite(A0, LOW);
  digitalWrite(A1, LOW);
  digitalWrite(A2, LOW);
  digitalWrite(A3, LOW);
}

//nižšie sú definované funkcie na rozsvietenie jednotlivých segmentov podľa toho akú číslicu chceme mať na displeji práve zobrazenú
//zastavíme sa pri číslici 3, aby kód nebol príliš dlhý no podobne by sa dalo pokračovať aj na ďalšie číslice

void vypis_jednotku () {
  digitalWrite(segB, HIGH);
  digitalWrite(segC, HIGH);
}

void vypis_dvojku () {
  digitalWrite(segA, HIGH);
  digitalWrite(segB, HIGH);
  digitalWrite(segG, HIGH);
  digitalWrite(segE, HIGH);
  digitalWrite(segD, HIGH);
}

void vypis_trojku () {
  digitalWrite(segA, HIGH);
  digitalWrite(segB, HIGH);
  digitalWrite(segG, HIGH);
  digitalWrite(segC, HIGH);
  digitalWrite(segD, HIGH);
}

Použitie knižnice

V tejto časti blogu použijeme už vytvorenú knižnicu, ktorú pred nami napísal niekto iný. Odporúčame použiť:
keypad.zip
Knižnicu je nutné naimportovať alebo rozbaliť a prekopírovať do priečinku kde je nainštalované IDE na cestu Arduino/libraries

Kód s použitím knižnice:

#include <Keypad.h>

const byte rows = 4; //počet riadkov
const byte cols = 4; //počet stĺpcov
char keys[rows][cols] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[rows] = {9, 8, 7, 6}; //piny pre pripojenie riadkov
byte colPins[cols] = {5, 4, 3, 2}; //piny pre pripojenie stĺpcov

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, rows, cols );

void setup(){
  Serial.begin(9600);  //nadviažeme komunikáciu s PC
}

void loop(){
  char key = keypad.getKey(); //použijeme vstavanú funkciu

  if (key != NO_KEY){
    Serial.println(key);  //ak sme niečo stlačili, vypíšeme to v počítači
  }
}

Knižnica má niekoľko funkcií:
void begin(makeKeymap(userKeymap)) – inicializácia klávesnice
char waitForKey() – čakám na stlačenie klávesy, keď nastane, naspäť dostaneme znak stlačenia
char getKey() – neblokujúca funkcia, na stlačenie sa nečaká, ale keď nastane, dostaneme naspäť znak stlačenia
KeyState getState() – naspäť získame stav stlačenia, môžu byť nasledovné: IDLE, PRESSED, RELEASED and HOLD
boolean keyStateChanged() – naspäť dostaneme hodnotu “true” alebo “false” podľa toho, či nastala zmena stavu stlačenia
setHoldTime(unsigned int time) – funkcia pre nastavenie doby stlačenia tlačidla, aby bolo rátané ako stlačené (v milisekudnách)
setDebounceTime(unsigned int time) – čas pre filtrovanie kmitania pri stlačení tlačidla (v milisekundách)
addEventListener(keypadEvent) – funkciu môžeme použiť iba v prípade, ak mikrokontrolér ktorý používame umožňuje prerušenia. Odporúčame vyskúšať kód z príkladov: Examples -> Keypad -> Examples -> EventSerialKeypad

Použité zdroje a ďalšie čítanie

https://www.hackster.io/
https://www.circuitbasics.com/
https://www.teachmemicro.com/
https://playground.arduino.cc/

Pridaj komentár

Vaša e-mailová adresa nebude zverejnená.