Az egyik korábbi blogbejegyzésünkben bemutattuk, milyen egyszerűen lehet csatlakoztatni egy szegmenses kijelzőt. A mai bejegyzésben egy egyszerű programot készítünk, amellyel a billentyűzeten megnyomott számokat jelenítjük meg a szegmenses kijelzőn. Egy 4×4-es, 16 gombos AVR billentyűzettel fogunk dolgozni, ahogy az az alábbi ábrán is látható:
Ebben a blogban megpróbáljuk elmagyarázni egy ilyen billentyűzet működési elvét. Ha Önnek csak a billentyűzet használata a fontos, és nem kíván belemerülni a működés elméletébe, ugorjon lejjebb a „Könyvtár használata” című részhez.
A billentyűzet működési elve
A billentyűzeten 16 gomb található, 4 sorba és 4 oszlopba rendezve. A billentyűzet belső kapcsolása a következőképpen néz ki:
Alaphelyzetben, amikor egyik gomb sincs lenyomva, a sorok és oszlopok elektromosan nincsenek összekapcsolva. Gombnyomáskor a megfelelő sor és oszlop vezető összekapcsolódik.
Annak meghatározásához, hogy melyik sorban történt a gombnyomás, a billentyűzet oszlopaihoz csatlakoztatott pineket kimeneti módba állítjuk és HIGH szintre húzzuk. A sorokhoz csatlakoztatott pineket bemenetként konfiguráljuk, és ellenőrizzük, hogy bármelyik soron megjelenik-e a HIGH szint. Ha igen, akkor tudjuk, hogy az adott sor valamelyik gombját megnyomták.
Ezt követően hasonló módon meghatározzuk, melyik oszlopban volt a gombnyomás. Az oszlopokat bemenetre állítjuk, a sorokat kimenetre és HIGH szintre kapcsoljuk. Leolvassuk, melyik oszloppinen jelenik meg HIGH, így megkapjuk a pontos oszlopot.
A sor és oszlop beolvasása a programban közvetlen egymás után történik, ez mikroszekundumos nagyságrendű, így pontosan detektálható, melyik gombot nyomták meg.
Ilyen módon az Arduino képes meghatározni a sor és oszlop koordinátákat, ahol a gombnyomás történt. Az alábbi táblázat mutatja, melyik sor és oszlop lesz HIGH állapotban az egyes gombok lenyomásakor, ha a bekötés az ábrán látható módon történt.
| Ha az oszlopot állítom be.. | és egyúttal megállapítom, hogy… | a lenyomott gomb… |
| Oszlop 0 = HIGH | Sor 0 = HIGH | 1 |
| Oszlop 1 = HIGH | Sor 0 = HIGH | 2 |
| Oszlop 2 = HIGH | Sor 0 = HIGH | 3 |
| Oszlop 0 = HIGH | Sor 1 = HIGH | 4 |
| Oszlop 1 = HIGH | Sor 1 = HIGH | 5 |
| Oszlop 2 = HIGH | Sor 1 = HIGH | 6 |
| Oszlop 0 = HIGH | Sor 2 = HIGH | 7 |
| Oszlop 1 = HIGH | Sor 2 = HIGH | 8 |
| Oszlop 2 = HIGH | Sor 2 = HIGH | 9 |
| Oszlop 1 = HIGH | Sor 3 = HIGH | 0 |
| Oszlop 0 = HIGH | Sor 3 = HIGH | * |
| Oszlop 2 = HIGH | Sor 3 = HIGH | # |
| Oszlop 3 = HIGH | Sor 0 = HIGH | A |
| Oszlop 3 = HIGH | Sor 1 = HIGH | B |
| Oszlop 3 = HIGH | Sor 2 = HIGH | C |
| Oszlop 3 = HIGH | Sor 3 = HIGH | D |
Ennél a felismerési módszernél előfordulhat, hogy problémák lépnek fel több gomb egyidejű lenyomásakor, illetve nagyon gyors gombnyomások esetén. Ezek kezelhetők összetettebb programozással vagy kiegészítő hardverrel.
-
Kábelek 65 db különböző mérecsap MM665Ft (ÁFA nélkül 524Ft ) -
4 × 4 AVR billentyűzet 16 billentyű315Ft (ÁFA nélkül 248Ft ) -
Nem forrasztási mező 830 pont665Ft (ÁFA nélkül 524Ft ) -
Arduino Uno R3 precíziós klón4 365Ft (ÁFA nélkül 3 437Ft )
Bekötés és program
Most bemutatjuk, hogyan kell bekötni a billentyűzetet és a 7 szegmenses kijelzőt, valamint hogyan lehet programot írni a megnyomott gombok megjelenítésére.
Az alábbi táblázat meghatározza, hogy a billentyűzet sorait (R1–R4) és oszlopait (C1–C4) mely Arduino pinekhez kell csatlakoztatni.
| Sor/oszlop | Leírás | Pin |
| R1 | Sor 1 (fel) | 9 |
| R2 | Sor 2 | 8 |
| R3 | Sor 3 | 7 |
| R4 | Sor 4 (le) | 6 |
| C1 | Oszlop 1 (bal) | 5 |
| C2 | Oszlop 2 | 4 |
| C3 | Oszlop 3 | 3 |
| C4 | Oszlop 4 (jobb) | 2 |
Az ábra segítségével láthatjuk, hogy az egyes számjegyek megjelenítéséhez mely szegmenseket kell felkapcsolni. Részletesebb információkért ajánljuk a korábbi blogbejegyzésünket a szegmenses kijelzőkről.
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);
}Könyvtár használata
Ebben a részben egy már elkészült, más által írt könyvtárat fogunk használni. Ajánlott könyvtár:
keypad.zip
A könyvtárat importálni kell, vagy ki kell csomagolni, majd bemásolni az Arduino IDE telepítési mappájába a következő útvonalra: Arduino/libraries
Kód a könyvtár használatával:
#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
}
}
A könyvtár funkciói:
void begin(makeKeymap(userKeymap)) – a billentyűzet inicializálása
char waitForKey() – várok a billentyű lenyomására; amikor ez megtörténik, visszakapjuk a lenyomott billentyű karakterét.
char getKey() – nem blokkoló függvény – nem vár a billentyű lenyomására, de ha gombnyomás történik, visszaadja a lenyomott billentyű karakterét.
KeyState getState() – visszaadja az aktuális billentyűállapotot: IDLE, PRESSED, RELEASED, HOLD
boolean keyStateChanged() – true/false értéket ad vissza annak alapján, történt-e állapotváltozás
setHoldTime(unsigned int time) – gombnyomás időtartamának beállítása (ms), amelyet tényleges lenyomásként kell érzékelni
setDebounceTime(unsigned int time) – gombnyomás „pergésének” (bounce) szűrési ideje (ms)
addEventListener(keypadEvent) – függvény csak akkor használható, ha a használt mikrokontroller támogatja a megszakításokat.
Javasoljuk, hogy próbálja ki a következő példakódot: Examples → Keypad → Examples → EventSerialKeypad
Felhasznált források és további olvasnivaló
https://www.hackster.io/
https://www.circuitbasics.com/
https://www.teachmemicro.com/
https://playground.arduino.cc/




