Mnogo prekidača na malo pinova

Matrica prekidača na Arduinu: membranska tipkovnica 4 × 4 s vlastitim skeniranjem, nizovi i ugniježđene petlje, lažne tipke i diode koje ih uklanjaju

Arduino Elektronika
Mnogo prekidača na malo pinova

Na stolu našeg flipera bit će 15 senzora: mete, staze i rupa za kuglicu. Uz njih je i tipka Start, pa glavni Arduino mora čitati 16 prekidača. Arduino Uno ima 18 pinova koje možemo slobodno koristiti, a glavnom Arduinu trebaju i za tilt, za vezu s ostalim Unima i za druge poslove. Kada bi svaki prekidač imao svoj pin, pinova ne bi bilo dovoljno.

Zato prekidače slažemo u matricu: u redke i stupce, kao polja u tablici. Za 16 prekidača tada je dovoljno 8 pinova. Danas ćemo napisati program koji čita takvu matricu, upoznat ćemo njezinu najveću zamku, lažne tipke, i popraviti je diodama.

Što to znači za fliper?

Tlocrt flipera: plavi krug označava tri mete na lijevom zidu, a u velikom plavom krugu iste su mete uvećane, s ljubičastom lampicom ispred svake

Na tlocrtu našeg flipera plavim su krugom označene tri mete na lijevom zidu, a u velikom krugu iste su mete uvećane. Iza svake mete je mikroprekidač, a ispred nje lampica. Što znače ostali dijelovi crteža, piše na stranici o fliperu.

  • Glavni Arduino flipera čita 15 senzora i tipku Start kroz matricu 4 × 4, preko 8 pinova. Uz svaki prekidač bit će zalemljena dioda, kao u Vježbi 4, jer kuglica i igrač mogu istodobno pritisnuti više prekidača.
  • Cijelu matricu program skenira za manje od pola milisekunde. Udarac kuglice u mikroprekidač traje nekoliko milisekundi, pa ga program sigurno vidi. Izmjerit ćemo ga u sljedećoj lekciji. Zato ni ovdje loop() ne smije čekati.
  • Svaki prekidač u matrici ima svoje smirivanje koje reagira na prvi dodir, kao danas.
  • Matricu čitamo svojim kodom iz Vježbe 1, a ne bibliotekom Keypad iz Vježbe 3. Zašto, piše na kraju te vježbe.
  • Tilt i tipke palica nisu u matrici. Tilt ima svoj pin, a tipke palica spojene su na Arduino koji upravlja palicama, jer palica mora krenuti istog trenutka.

Kako radi matrica

Membranska tipkovnica 4 × 4 ima 16 tipki, a samo 8 nožica. Unutra su četiri vodiča u redcima (R1 do R4) i četiri u stupcima (C1 do C4). Svaka tipka stoji ondje gdje se jedan redak križa s jednim stupcem. Kada je pritisneš, spoji taj redak s tim stupcem.

Shema tipkovnice 4 puta 4: četiri vodoravna retka R1 do R4 na pinovima D12 do D9 i četiri okomita stupca C1 do C4 na pinovima D8 do D5. Na svakom križanju je jedna tipka, od 1, 2, 3 i A u prvom retku do zvjezdice, 0, ljestvi i D u zadnjem

Arduino tipkovnicu čita redak po redak:

  1. Jedan redak spoji s GND: pin tog retka je izlaz i šalje LOW. Ostali redci su isključeni.
  2. Pročita sva četiri stupca. Stupci imaju pull-up otpornik, kao tipkalo, pa čitaju HIGH. Stupac koji čita LOW spojen je s uključenim retkom preko pritisnute tipke.
  3. Isključi taj redak i prijeđe na sljedeći.
Jedna tipka izbliza: tipka 1 spaja stupac C1 na pinu D8, koji je ulaz (INPUT), s retkom R1 na pinu D12, koji je izlaz (OUTPUT). Unutar Arduina, u isprekidanom okviru, sivi pull-up otpornik od 20 do 50 kilooma spaja pin D8 s 5 V

Na slici je jedna tipka izbliza. Sivo je nacrtano ono što je unutar Arduina (isprekidani okvir): ugrađeni pull-up otpornik od 20 do 50 kΩ spaja pin stupca C1 s 5 V. Dok je tipka 1 otpuštena, kroz otpornik ne teče struja i stupac čita HIGH. Kada je pritisneš dok je redak R1 na LOW, tipka spoji stupac s retkom, pa stupac čita LOW.

Redak i stupac zajedno kažu koja je tipka pritisnuta: LOW na stupcu C2 dok je uključen redak R1 znači tipku 2. Ovako pročitati cijelu tipkovnicu zove se skeniranje. Arduino je skenira za manje od pola milisekunde, pa to ponavlja tisuće puta u sekundi.

PrekidačaSvaki na svom pinuU matrici
1616 pinova4 redka + 4 stupca = 8 pinova
6464 pina8 redaka + 8 stupaca = 16 pinova

Isključeni redak nije HIGH

Redak koji ne skeniramo program ne postavlja na HIGH, nego ga pretvori u ulaz (INPUT). Tada nije spojen ni s čim i kroz njega ne može teći struja.

Kada bi isključeni redak bio HIGH, dvije pritisnute tipke u istom stupcu spojile bi redak koji šalje HIGH s retkom koji šalje LOW. Bio bi to kratki spoj između dva pina, a on može oštetiti Arduino.

Materijal

Svaki polaznik dobiva:

  • Arduino Uno i USB kabel
  • membransku tipkovnicu 4 × 4 i 8 spojnih žica s iglicama na oba kraja
  • veliki breadboard, četiri mala tipkala, četiri diode i spojne žice

Za pokaznu vježbu na kraju Vježbe 1 voditelj treba osciloskop s dva kanala i dvije sonde, mali breadboard i nekoliko spojnih žica.

Spoj iz prošle lekcije više nam ne treba: rastavi ga, a dijelove vrati u kutiju.

Pravila za spajanje

  1. Dok spajamo, Arduino je odspojen s USB kabela.
  2. Prvo učitaj program, a tek onda spoji tipkovnicu. Na Arduinu je možda još neki stari program u kojem su pinovi tipkovnice izlazi, na primjer program semafora. Kada bi takav program radio dok pritišćeš tipke, mogao bi spojiti dva izlaza. Program iz Vježbe 1 zato učitaj dok na Arduino još ništa nije spojeno.
  3. Prije uključivanja voditelj pregleda spoj.

Vježba 1: Skeniramo tipkovnicu

Program

Ovaj program čita tipkovnicu i u Serial Monitoru ispisuje znak svake tipke koju pritisneš. Isti program koristit ćemo i u Vježbama 2 i 4.

Planiraj prije nego što programiraš:
funkcija getKey:
za svaki redak:
uključi redak: izlaz, LOW
za svaki stupac:
pročitaj stupac
ako se tipka promijenila, a smirivanje je prošlo:
zapamti novo stanje i vrijeme
ako je tipka upravo pritisnuta:
isključi redak
vrati njezin znak
isključi redak
vrati NO_KEY: nijedna tipka nije upravo pritisnuta
ponavljaj zauvijek:
pitaj getKey je li neka tipka upravo pritisnuta
ako jest: ispiši njezin znak
// C++
const unsigned long SMIRIVANJE = 50;   // nakon promjene 50 ms ne gledamo tu tipku
const char NO_KEY = 0;                 // getKey() to vrati kada nijedna tipka nije upravo pritisnuta

const int redci[4] = {12, 11, 10, 9};  // nožice 1 do 4 tipkovnice: redci R1 do R4
const int stupci[4] = {8, 7, 6, 5};    // nožice 5 do 8 tipkovnice: stupci C1 do C4

// Znak svake tipke: prvi broj je redak, drugi stupac.
const char znakovi[4][4] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

bool bilaPritisnuta[4][4];             // kakva je svaka tipka bila zadnji put (na početku nijedna)
unsigned long zadnjaPromjena[4][4];    // kada se svaka tipka zadnji put promijenila

// Skenira tipkovnicu i vrati znak tipke koja je upravo pritisnuta, ili NO_KEY.
char getKey() {
  for (int r = 0; r < 4; r++) {        // redom svaki redak
    pinMode(redci[r], OUTPUT);         // uključi redak: izlaz...
    digitalWrite(redci[r], LOW);       // ...spojen s GND
    delayMicroseconds(10);             // pričekaj da se napon na stupcima ustali

    for (int s = 0; s < 4; s++) {      // redom svaki stupac
      bool pritisnuta = digitalRead(stupci[s]) == LOW;
      if (pritisnuta != bilaPritisnuta[r][s] && millis() - zadnjaPromjena[r][s] >= SMIRIVANJE) {
        bilaPritisnuta[r][s] = pritisnuta;
        zadnjaPromjena[r][s] = millis();
        if (pritisnuta) {              // tipka je upravo pritisnuta
          pinMode(redci[r], INPUT);    // isključi redak prije povratka
          return znakovi[r][s];        // vrati znak i izađi iz funkcije
        }
      }
    }

    pinMode(redci[r], INPUT);          // isključi redak prije sljedećeg
  }
  return NO_KEY;                       // nijedna tipka nije upravo pritisnuta
}

void setup() {
  for (int r = 0; r < 4; r++) {
    pinMode(redci[r], INPUT);          // redak je isključen
  }
  for (int s = 0; s < 4; s++) {
    pinMode(stupci[s], INPUT_PULLUP);  // stupac čitamo, kao tipkalo
  }
  Serial.begin(9600);
}

void loop() {
  char tipka = getKey();               // znak upravo pritisnute tipke ili NO_KEY
  if (tipka != NO_KEY) {
    Serial.println(tipka);
  }
}

Učitaj program dok na Arduino još ništa nije spojeno.

Što je novo u programu?

  • const int redci[4] = {12, 11, 10, 9}; – Niz: jedna varijabla s više vrijednosti, ovdje četiri broja pinova. Do svake vrijednosti dolazimo po rednom broju u uglatim zagradama, a brojimo od nule: redci[0] je 12, a redci[3] je 9.
  • const char znakovi[4][4] – Dvodimenzionalni niz: tablica s četiri retka i četiri stupca. znakovi[1][2] je znak u retku 1 i stupcu 2, dakle '6', jer i ovdje brojimo od nule. Tip char sprema jedan znak, napisan u jednostrukim navodnicima: '6', '#'.
  • bool bilaPritisnuta[4][4]; i unsigned long zadnjaPromjena[4][4]; – Svaka od 16 tipki pamti svoje stanje i vrijeme zadnje promjene, kao jedno tipkalo u lekciji o tipkalima. Nizovi napisani iznad setup() na početku su puni nula, pa nijedna tipka nije pritisnuta.
  • char getKey() – Vlastita funkcija koja vraća vrijednost, kao procitajBrojKoraka() u lekciji 2.1. char ispred imena kaže da funkcija vraća jedan znak. U funkciju smo premjestili cijelo skeniranje, pa je loop() kratak. Dali smo joj englesko ime getKey (dohvati tipku), jer se tako zove i funkcija biblioteke iz Vježbe 3. Zato loop() u obje vježbe izgleda gotovo jednako.
  • const char NO_KEY = 0; – Znak koji ne znači nijednu tipku. getKey() ga vrati kada nijedna tipka nije upravo pritisnuta, a loop() tada ništa ne ispiše.
  • for (int r = 0; r < 4; r++) i unutar njega for (int s = 0; s < 4; s++) – Petlja u petlji. Za svaki od četiri redka unutarnja petlja prođe kroz sva četiri stupca, pa se pri skeniranju cijele tipkovnice tijelo unutarnje petlje izvede 16 puta, jednom za svaku tipku.
  • return znakovi[r][s]; – return vrati znak i odmah izađe iz funkcije, iako su obje petlje još usred posla. Zato redak prije toga isključimo. Inače bi ostao uključen, pa bi program njegove tipke vidio i dok skenira druge redke.
  • Ako se u istom skeniranju pojave dvije nove tipke, getKey() vrati prvu. Stanje druge još nije zapamćeno, pa je funkcija u sljedećem prolazu kroz loop() opet vidi kao novu i vrati je tada. Tako program ne propusti nijednu tipku.
  • pinMode(redci[r], OUTPUT); … pinMode(redci[r], INPUT); – Pin retka mijenjamo između izlaza i ulaza dok program radi, a ne samo u setup(). Kao izlaz s LOW redak je uključen, a kao ulaz isključen.
  • delayMicroseconds(10); – Čeka 10 mikrosekundi, stotinku milisekunde, da se napon na stupcima ustali nakon uključivanja retka. Program zbog toga ne postaje primjetno sporiji.
  • Smirivanje svake tipke isto je kao u Vježbi 3 lekcije o tipkalima: prva promjena odmah vrijedi, a zatim 50 ms ne gledamo tu tipku.

Spajanje

Nožice tipkovnice gledamo s prednje strane, s tipkama okrenutim prema nama: nožice 1 do 4 su redci, a nožice 5 do 8 stupci. Spoji ih redom na pinove D12 do D5. U konektor tipkovnice utakni jedan kraj spojne žice, a drugi kraj izravno u pin Arduina. Breadboard nam za sada ne treba.

Nožica tipkovnice12345678
VodičR1R2R3R4C1C2C3C4
Arduino pinD12D11D10D9D8D7D6D5
Spajanje tipkovnice: nožice 1 do 4 tipkovnice, redci, idu na pinove D12 do D9, a nožice 5 do 8, stupci, na pinove D8 do D5

Većina membranskih tipkovnica 4 × 4 ima ovakav raspored nožica. Ako tvoja ima drukčiji, program će ispisivati krive znakove. Kako to popraviti, piše u odjeljku Ako nešto ne radi.

Spoji USB kabel, otvori Serial Monitor (9600 baud) i pritisni redom sve tipke. Ispisuje li program za svaku tipku njezin znak?

Pokazna vježba: osciloskop na stupcima

Ovu pokaznu vježbu radi voditelj, a svi gledaju. Osciloskop crta kako se napon na pinu mijenja kroz vrijeme. Za razliku od multimetra, vidi i promjene koje traju samo nekoliko mikrosekundi, pa njime možemo gledati skeniranje dok se događa. Naš osciloskop ima dva kanala, CH1 i CH2, pa istodobno crta dva pina: stupce C1 i C2. Dijelovi našeg osciloskopa i osnovne upute za rad opisani su na stranici Osciloskop.

Štipaljka za masu ide samo na GND

Svaka sonda ima vrh i malu krokodil štipaljku za masu. Mase obiju sondi u osciloskopu su međusobno spojene. Kada bi jedna štipaljka bila na GND, a druga na nekom drugom pinu, osciloskop bi taj pin spojio s GND. Bio bi to kratki spoj. Zato obje štipaljke idu na GND, a na pinove idu samo vrhovi sondi.

Priprema:

  1. Odspoji USB kabel. Žice stupaca C1 i C2 voditelj ne utakne izravno u Arduino, nego preko breadboarda: žica s tipkovnice ide u svoj redak breadboarda, a iz istog retka druga žica u pin D8 (odnosno D7). U svaki od ta dva retka utakne još jednu kratku žicu, na čiji slobodni kraj zakvači vrh sonde. Još jednom žicom spoji GND Arduina s trećim retkom breadboarda, za mase.
  2. Vrh sonde kanala CH1 zakvači na stupac C1, a vrh sonde kanala CH2 na stupac C2. Obje štipaljke za masu zakvači na redak s GND.
  3. Prekidač na sondi (1X ili 10X) i postavka sonde u izborniku osciloskopa moraju biti isti, za oba kanala. Obično je to 10X.
  4. Oba kanala postavi na 2 V po podjeljku. CH1 pomakni u gornju polovicu zaslona, a CH2 u donju, da se krivulje ne preklapaju.
  5. Vremensku bazu postavi na 50 µs po podjeljku.
  6. Okidanje (engleski trigger) kaže osciloskopu kada da počne crtati. Postavi izvor CH1, padajući brid i razinu oko 2,5 V: osciloskop crta od trenutka kada napon na CH1 padne ispod 2,5 V. Tipkom MODE odaberi način Auto, u kojem osciloskop crta i kada okidanja nema.
  7. Spoji USB kabel.

Izvođenje:

  1. Nijedna tipka nije pritisnuta. Obje krivulje su ravne crte na 5 V.
  2. Polaznik drži tipku 1. Voditelj tipkom MODE odabere način Normal: osciloskop sada crta samo kada CH1 padne ispod 2,5 V, pa slika stoji mirno. Na CH1 vide se kratki padovi na 0 V, jedan za drugim. Razmak između dva pada je jedno skeniranje cijele tipkovnice. Je li kraći od pola milisekunde, odnosno od 10 podjeljaka?
  3. Polaznik drži tipke 1 i 2. Padovi na CH1 i CH2 su istodobni.
  4. Polaznik drži tipke 1 i 5. Pad na CH2 počinje otprilike kada pad na CH1 završi.
  5. Hvatamo pritisak. Polaznik pusti sve tipke, a voditelj tipkom MODE odabere način Single. Osciloskop čeka. Kada polaznik pritisne tipku 1, osciloskop nacrta trenutak pritiska i zaustavi se. Ako kontakti pri pritisku poskakuju, neki od prvih padova nedostaju ili su kraći od ostalih.

Kanal osciloskopa kaže stupac, a vrijeme pada kaže redak. Na isti način i program zna koja je tipka pritisnuta.

Koji znak je znakovi[2][1]?
'8'. Brojimo od nule, pa je [2] treći redak ('7', '8', '9', 'C'), a [1] drugi stupac u njemu.
Zašto su na osciloskopu oba stupca na 5 V dok nijedna tipka nije pritisnuta?
Stupci su ulazi s pull-up otpornikom (INPUT_PULLUP), a on ih drži na 5 V. Uključeni redak na LOW mogao bi stupac povući na 0 V samo preko pritisnute tipke.
Tipku 1 držiš cijelo vrijeme. Zašto je stupac C1 na 0 V samo u kratkim padovima?
Tipka 1 spaja stupac C1 s retkom R1, a R1 je na LOW samo dok ga program skenira. Ostatak vremena R1 je isključen (INPUT), pa pull-up drži C1 na 5 V. Svaki pad je trenutak u kojem program uključi redak R1, jednom u svakom skeniranju.
Zašto su padovi tipki 1 i 2 istodobni, a pad tipke 5 dolazi odmah iza pada tipke 1?
Tipke 1 i 2 su u istom retku, R1, pa im stupci padnu u istom trenutku: dok je uključen R1. Tipka 5 je u retku R2, a program ga uključi odmah nakon retka R1. Kanal osciloskopa kaže stupac tipke, a vrijeme pada kaže njezin redak.
Kako s osciloskopa pročitaš koliko traje jedno skeniranje tipkovnice?
Izmjeriš razmak između dva susjedna pada iste tipke: prebrojiš podjeljke i pomnožiš ih s vremenom po podjeljku. Na primjer, 4 podjeljka po 50 µs su 200 µs. Mnogi osciloskopi taj razmak izmjere i sami, kao period ili frekvenciju.
Što bi na stupcu C1 pokazao multimetar dok držiš tipku 1?
Nešto manje od 5 V. Padovi su prekratki da bi ih multimetar pratio, pa pokaže prosječni napon. Stupac je većinu vremena na 5 V, a samo kratko na 0 V, pa je prosjek bliže 5 V. Zato za brze promjene trebamo osciloskop.

Vježba 2: Lažne tipke

Program i spoj ostaju isti. Pritisni tipku 1 i drži je. Zatim pritisni i drži tipku 2, pa dok držiš obje, pritisni još i tipku 4. Što ispisuje program?

Osim 1, 2 i 4 program ispiše i 5, iako tipku 5 nitko nije dirao. To je lažna tipka (engleski ghost key).

Lijevo, bez dioda: dok je redak R2 uključen, struja iz stupca C2 prolazi kroz tipku 2 u redak R1, kroz tipku 1 natrag u stupac C1 i kroz tipku 4 u redak R2, pa stupac C2 čita LOW kao da je pritisnuta tipka 5. Desno, s diodama: dioda tipke 1 zaustavi struju i lažne tipke nema

Pogledaj lijevu stranu crteža. Program je uključio redak R2 i čita stupac C2. Tipka 5 nije pritisnuta, ali struja je pronašla zaobilazni put (crveno): iz stupca C2 kroz tipku 2 u redak R1, zatim kroz tipku 1 u stupac C1 i kroz tipku 4 u redak R2. Stupac C2 zato čita LOW i program misli da je pritisnuta tipka 5.

Desna strana crteža pokazuje kako se to popravlja: uz svaku tipku je dioda, koja struju propušta samo u jednom smjeru, od stupca prema retku. Struja iz stupca C2 i dalje stigne kroz tipku 2 u redak R1, ali zaobilazni put morao bi kroz tipku 1 proći unatrag, od retka R1 prema stupcu C1. Dioda tipke 1 to ne dopušta (zelena kvačica), pa stupac C2 ostaje na 5 V i lažne tipke nema. Diode ćemo dodati u Vježbi 4.

Lažna tipka pojavi se kada su pritisnute tri tipke u tri kuta pravokutnika u matrici. Četvrti kut je tada lažna tipka.

Držiš tipke 5, 6 i 8. Koja će se lažna tipka pojaviti?
Tipka 9. Tipke 5 i 6 su u retku R2, tipke 5 i 8 u stupcu C2. Četvrti kut tog pravokutnika je redak R3 i stupac C3, a to je tipka 9. Isprobaj!

Lažne tipke na računalu

I tipkovnica računala je matrica. Jeftine tipkovnice nemaju diode, pa neke kombinacije triju ili više tipki ne rade dobro: računalo ili vidi tipku koju nisi pritisnuo, ili ne vidi tipku koju jesi. Tipkovnice za igrice zato često imaju diodu uz svaku tipku, pa računalo ispravno vidi bilo koju kombinaciju tipki.

Vježba 3: Tipkovnica s bibliotekom Keypad (neobavezna)

Ovu vježbu radi ako ti ostane vremena. Tipkovnice su toliko česte da za njih postoji gotova biblioteka, kao Bounce2 za tipkalo u lekciji o tipkalima. Zove se Keypad. Napisat ćemo program koji radi isto što i program iz Vježbe 1, ali skeniranje i smirivanje prepustit ćemo biblioteci. Zatim ćemo vidjeti što biblioteka radi s lažnim tipkama.

Spoj ostaje isti, pa tipkovnicu ne moraš odspajati. I biblioteka u svakom trenutku ima samo jedan pin kao izlaz, pa ne može spojiti dva izlaza.

Instaliranje biblioteke

  1. U Arduino IDE-u otvori Library Manager: ikona s knjigama na lijevoj strani ili izbornik Sketch ⇒ Include Library ⇒ Manage Libraries…
  2. U tražilicu upiši Keypad.
  3. Instaliraj biblioteku koja se zove samo Keypad, autora Mark Stanley i Alexander Brevig. Tražilica pokaže i mnogo drugih biblioteka s riječju Keypad u imenu, ali njih ne trebamo.

Za instaliranje treba internet. Ako ga u radionici nema, voditelj biblioteku unaprijed instalira na svako računalo.

Planiraj prije nego što programiraš:
ponavljaj zauvijek:
pitaj biblioteku je li neka tipka upravo pritisnuta
ako jest: ispiši njezin znak

Drugi dio plana isti je kao u Vježbi 1, samo pitamo biblioteku umjesto naše funkcije. Prvi dio plana, funkciju getKey, sada ima biblioteka.

Program s bibliotekom

// C++
#include <Keypad.h>                    // biblioteka za tipkovnice

byte redci[4] = {12, 11, 10, 9};       // isti pinovi kao u Vježbi 1
byte stupci[4] = {8, 7, 6, 5};

char znakovi[4][4] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

Keypad tipkovnica(makeKeymap(znakovi), redci, stupci, 4, 4);

void setup() {
  Serial.begin(9600);
}

void loop() {
  char tipka = tipkovnica.getKey();    // znak upravo pritisnute tipke ili NO_KEY
  if (tipka != NO_KEY) {
    Serial.println(tipka);
  }
}

Učitaj program, otvori Serial Monitor i pritisni redom sve tipke. Program mora ispisivati iste znakove kao program iz Vježbe 1.

Što je novo u programu?

  • #include <Keypad.h> – Uključuje biblioteku u program. Ako biblioteka nije instalirana, prevođenje javi grešku Keypad.h: No such file or directory.
  • byte redci[4] = {12, 11, 10, 9}; – Tip byte sprema cijeli broj od 0 do 255, a to je dovoljno za broj pina. Biblioteka traži pinove baš u nizu tipa byte, i to bez const, pa ovdje ne možemo napisati const int kao u Vježbi 1.
  • Keypad tipkovnica(makeKeymap(znakovi), redci, stupci, 4, 4); – tipkovnica je objekt, kao start u lekciji o tipkalima. Biblioteci kažemo znakove tipki, pinove redaka, pinove stupaca te koliko je redaka i stupaca. makeKeymap() pretvara našu tablicu znakova u oblik koji biblioteka traži.
  • setup() ima samo Serial.begin(9600); – Pinove postavlja biblioteka, pa pinMode() ne pišemo.
  • char tipka = tipkovnica.getKey(); – Funkcija getKey() biblioteke radi isto što i naša iz Vježbe 1: skenira tipkovnicu i vrati znak tipke koja je upravo pritisnuta, a ako takve tipke nema, vrati NO_KEY. Ispred nje pišemo tipkovnica., jer je to funkcija objekta. Osim toga, loop() je isti kao u Vježbi 1.
  • Nema naše funkcije getKey(), konstante NO_KEY ni nizova bilaPritisnuta i zadnjaPromjena. Sve to ima biblioteka.

Prednosti biblioteke:

  • Program je mnogo kraći i lakše se čita. Od Vježbe 1 ostali su samo pinovi, tablica znakova i loop().
  • Smirivanje je već ugrađeno, pa ga ne moramo pisati.
  • Biblioteka zna više od pritiska: za svaku tipku zna je li upravo pritisnuta, drži li je netko dulje od pola sekunde ili je upravo otpuštena. To dobro dođe za bravu sa šifrom ili izbornik.
  • Tipkovnica druge veličine, na primjer telefonska 4 × 3, traži samo druge brojeve i drugu tablicu znakova.
  • Biblioteku koriste mnogi ljudi, pa su njezine greške većinom već pronađene i popravljene. U izborniku File ⇒ Examples ⇒ Keypad ima gotove primjere.

Mane su iste kao kod biblioteke Bounce2: treba je instalirati na svako računalo, ne vidimo kako radi i zauzima više memorije. Ovaj program je oko 830 bajtova veći od programa iz Vježbe 1.

Lažne tipke s bibliotekom

Ponovi pokus iz Vježbe 2: pritisni i drži tipku 1, zatim tipku 2, pa dok držiš obje, pritisni još i tipku 4. Što sada ispisuje program?

Program ispiše samo 1. Lažne tipke 5 nema, ali nema ni tipki 2 i 4, koje si stvarno pritisnuo/la.

Biblioteka lažne tipke ne uklanja. I ona skenira tipkovnicu bez dioda, pa i ona za tipku 5 pročita LOW, kao naš program u Vježbi 2. Iz napona na pinovima ne može se znati je li tipka 5 stvarno pritisnuta ili je struja našla zaobilazni put. To ne može nijedan program.

Lažnu tipku ne vidimo zbog načina na koji radi getKey() biblioteke. Biblioteka pritisnute tipke pamti u popisu, a getKey() javlja samo novu tipku na prvom mjestu popisa. Dok držiš tipku 1, ona je prva, pa getKey() ne javi ni 2, ni 4, ni lažnu 5. Funkcija getKeys() iz iste biblioteke javlja sve pritisnute tipke, pa bi uz 1, 2 i 4 javila i lažnu tipku 5.

Program bi mogao najviše primijetiti da su pritisnute tri tipke u kutovima pravokutnika i ne vjerovati četvrtoj, kao neke jeftine tipkovnice računala, koje tada radije ne vide jednu tipku. Biblioteka Keypad ni to ne radi. Lažne tipke stvarno uklanjaju tek diode, a njih ćemo dodati u Vježbi 4.

Je li biblioteka Keypad uklonila lažnu tipku?
Nije. I ona za tipku 5 pročita LOW. Lažnu tipku ne ispiše samo zato što getKey() dok držiš tipku 1 ne javlja nijednu drugu tipku, pa ne javi ni prave tipke 2 i 4. S funkcijom getKeys() lažna tipka 5 bi se pojavila.

Zašto je u fliperu ne koristimo

Za tipkovnicu koju pritišće čovjek biblioteka Keypad dobar je izbor. Glavni Arduino flipera ipak će matricu čitati našim kodom iz Vježbe 1, jer biblioteka radi tri stvari koje fliperu smetaju:

  • Skenira tipkovnicu najviše jednom u 10 ms. Ako od zadnjeg skeniranja nije prošlo 10 ms, getKey() odmah vrati NO_KEY, a da tipkovnicu nije ni pogledao. Tako biblioteka smiruje tipke. Prst tipku drži mnogo dulje, pa to ne smeta. Udarac kuglice u mikroprekidač traje samo nekoliko milisekundi i može cijeli proći između dva skeniranja. Program ga tada uopće ne vidi. Naš program skenira cijelu matricu u svakom prolazu kroz loop().
  • getKey() biblioteke javlja samo jednu tipku. Dok držiš tipku 1, bibliotečna getKey() ne javi druge tipke, kao što si vidio/la u pokusu s lažnim tipkama. Naša getKey() iz Vježbe 1 javi ih. U fliperu kuglica i igrač često istodobno pritisnu više prekidača. Biblioteka ima i funkciju getKeys() za više tipki, ali s njom program više nije kratak.
  • Skenira obrnutim smjerom. Naš program uključuje redke i čita stupce, pa struja kroz pritisnutu tipku teče od stupca prema retku. Biblioteka uključuje stupce (LOW) i čita redke (pull-up), pa struja teče od retka prema stupcu. U Vježbi 4 dodat ćemo diode koje struju propuštaju samo od stupca prema retku. S njima biblioteka ne bi vidjela nijednu tipku dok joj u programu ne zamijenimo redke i stupce.
Zašto biblioteka Keypad u fliperu može propustiti udarac kuglice?
Biblioteka skenira matricu najviše jednom u 10 ms. Udarac kuglice traje samo nekoliko milisekundi, pa može početi i završiti između dva skeniranja. Nijedno skeniranje tada ne vidi pritisnut mikroprekidač. Naš program cijelu matricu skenira za manje od pola milisekunde, pa vidi svaki udarac koji traje dulje od toga.

Vježba 4: Diode protiv lažnih tipki

Dioda je jednosmjerni ventil za struju: propušta je samo u jednom smjeru, od anode prema katodi. Jednu diodu već dobro poznaješ: LED-ica je dioda koja pritom svijetli. Na običnoj diodi katoda je označena prugom.

U našoj matrici struja kroz pritisnutu tipku teče od stupca, koji pull-up otpornik drži na 5 V, prema uključenom retku na LOW. Zato uz svaku tipku stavimo diodu: anoda je prema tipki, a katoda prema retku. Kroz pritisnutu tipku struja tada teče kao i prije. Ali zaobilazni put mora kroz tipku 1 proći unatrag, od retka prema stupcu, a to dioda ne dopušta. Pogledaj desnu stranu crteža iz Vježbe 2, koji je ponovljen ovdje:

Lijevo, bez dioda: dok je redak R2 uključen, struja iz stupca C2 prolazi kroz tipku 2 u redak R1, kroz tipku 1 natrag u stupac C1 i kroz tipku 4 u redak R2, pa stupac C2 čita LOW kao da je pritisnuta tipka 5. Desno, s diodama: dioda tipke 1 zaustavi struju i lažne tipke nema

Tipkovnici ne možemo dodati diode, pa ćemo na breadboardu složiti malu matricu 2 × 2, s četiri tipkala i četiri diode.

Spajanje

Program je onaj iz Vježbe 1. Ako si radio/la Vježbu 3, prvo ponovo učitaj program iz Vježbe 1, jer biblioteka skenira obrnutim smjerom i s ovim diodama ne bi vidjela nijednu tipku. Zatim odspoji USB kabel i izvuci žice iz tipkovnice. Naša mala matrica spojena je na prva dva retka i prva dva stupca, pa su njezina tipkala za program tipke 1, 2, 4 i 5. Ostali pinovi ostaju nespojeni i program na njima ne vidi nijednu tipku.

DioArduino pinNa breadboardu
Tipkalo 1–preko središnjeg utora, u e3, e5, f3, f5
Tipkalo 2–preko središnjeg utora, u e9, e11, f9, f11
Tipkalo 4–preko središnjeg utora, u e15, e17, f15, f17
Tipkalo 5–preko središnjeg utora, u e21, e23, f21, f23
Diode–h5–h8, h11–h14, h17–h20 i h23–h26; pruga (katoda) prema dolje, u retke 8, 14, 20 i 26
Stupac C1D8žica s D8 u a3, žica od b3 do b15
Stupac C2D7žica s D7 u a9, žica od c9 do c21
Redak R1D12žica s D12 u f8, žica od i8 do i14
Redak R2D11žica s D11 u f20, žica od i20 do i26
Shema matrice 2 puta 2: tipkala SW1 do SW4 su tipke 1, 2, 4 i 5. Svako tipkalo spaja svoj stupac, C1 na D8 ili C2 na D7, preko svoje diode D1 do D4 sa svojim retkom, R1 na D12 ili R2 na D11. Katode dioda su prema redcima
Spajanje matrice 2 puta 2 na breadboardu: četiri tipkala preko središnjeg utora u retcima 3 i 5, 9 i 11, 15 i 17 te 21 i 23, diode od h5 do h8, h11 do h14, h17 do h20 i h23 do h26, stupci D8 u a3 i D7 u a9 sa žicama b3 do b15 i c9 do c21, redci D12 u f8 i D11 u f20 sa žicama i8 do i14 i i20 do i26
  • Svako tipkalo spaja svoja dva retka breadboarda, na primjer tipkalo 1 retke 3 i 5. Redak 3 vodi do stupca, a redak 5 preko diode do retka matrice.
  • Matrici ne treba GND na breadboardu. Uključeni redak matrice, pin s LOW, za tipke je isto što i GND.
  • Dioda na sebi zadrži oko pola volta, pa stupac pritisnute tipke ne pada sasvim na 0 V. To je i dalje mnogo ispod 1,5 V, pa Arduino sigurno čita LOW.

Spoji USB kabel i otvori Serial Monitor. Pritisni svako tipkalo: ispisuju se 1, 2, 4 i 5? Zatim pritisni i drži tipkala 1, 2 i 4. Ispisuje li program još i 5?

Eksperimenti

1. Dioda je zaštita. Odspoji USB kabel, izvadi diodu tipkala 1 i na njezino mjesto stavi žicu od h5 do h8. Spoji USB kabel i ponovo drži tipkala 1, 2 i 4. Što se dogodi? Vrati diodu na mjesto.

2. Okrenuta dioda. Okreni diodu tipkala 2, tako da je pruga gore, u h11. Radi li tipkalo 2? Okreni je natrag.

Zašto je u eksperimentu 1 važna baš dioda tipkala 1?
Zaobilazni put kroz tipku 1 prolazi unatrag, od retka R1 prema stupcu C1. Upravo dioda tipkala 1 zato zaustavlja struju i nema lažne tipke. Kroz diode tipkala 2 i 4 struja na tom putu teče u smjeru u kojem je propuštaju. Bez diode tipkala 1 zaobilazni put je otvoren, pa se lažna tipka 5 opet pojavi.
Zašto okrenuta dioda tipkala 2 ne radi?
Okrenuta dioda propušta struju samo od retka prema stupcu. Pritisnuto tipkalo trebalo bi propustiti struju od stupca prema retku, a to okrenuta dioda ne dopušta. Stupac zato ostaje na HIGH i program tipku ne vidi.

Ako nešto ne radi

  • Program ništa ne ispisuje ⇒ Odaberi 9600 baud. Jesu li sve žice u konektoru tipkovnice? Idu li redom s nožica 1 do 8 na D12 do D5?
  • Program ispisuje krive znakove, na primjer 4 kada pritisneš 2 ⇒ Kod tvoje tipkovnice redci i stupci su zamijenjeni. U programu zamijeni brojeve u nizovima: redci neka bude {8, 7, 6, 5}, a stupci {12, 11, 10, 9}.
  • Program ispisuje znakove obrnutim redom, na primjer D kada pritisneš 1 ⇒ Žice su u konektoru okrenute. Spoji nožicu 1 na D12, a nožicu 8 na D5.
  • Ne radi cijeli redak ili cijeli stupac tipki ⇒ Jedna žica nije dobro utaknuta. Iz tablice pročitaj koja i provjeri je.
  • U Vježbi 4 jedno tipkalo ne radi ⇒ Je li njegova dioda okrenuta? Pruga mora biti dolje, u retku 8, 14, 20 ili 26. Je li tipkalo preko središnjeg utora?
  • U Vježbi 4 i dalje se pojavljuje lažna tipka ⇒ Neka dioda nedostaje ili je premoštena žicom. Provjeri da su sve četiri diode na mjestu.
  • Program se ne može učitati ⇒ Provjeri jesu li u Arduino IDE-u odabrani ploča Arduino Uno i pravi port.

Dodatni izazovi

  1. Brava sa šifrom. Neka program pamti posljednje četiri pritisnute tipke. Kada pritisneš #, neka ispiše Otvoreno ako su to bile 1, 9, 7 i 0, a inače Krivo. Savjet: četiri znaka spremi u niz char sifra[4];.
  2. Koliko tipki odjednom? Neka program svakih pola sekunde ispiše koliko je tipki sada pritisnuto. Na tipkovnici bez dioda pokušaj pronaći četiri tipke koje možeš pritisnuti odjednom, a da se ne pojavi lažna tipka.
  3. Koliko traje skeniranje? micros() radi kao millis(), ali vraća mikrosekunde. S njom izmjeri koliko traje jedno skeniranje cijele tipkovnice. Je li kraće od udarca kuglice, koji traje nekoliko milisekundi?

Što smo naučili?

  • U matrici prekidači su u redcima i stupcima. 16 prekidača u matrici 4 × 4 treba samo 8 pinova.
  • Arduino matricu skenira: uključi jedan redak (LOW), pročita sve stupce (INPUT_PULLUP), isključi redak i prijeđe na sljedeći.
  • Na osciloskopu stupac pritisnute tipke kratko padne na 0 V jednom u svakom skeniranju, dok je uključen redak te tipke.
  • Isključeni redak je ulaz (INPUT), a ne HIGH. Inače bi dvije tipke u istom stupcu spojile dva izlaza.
  • Niz je varijabla s više vrijednosti. Do vrijednosti dolazimo po rednom broju, a brojimo od nule: redci[0].
  • Dvodimenzionalni niz je tablica: znakovi[redak][stupac]. Tip char sprema jedan znak.
  • Petlja u petlji prođe kroz sve redke i u svakom kroz sve stupce.
  • Tri pritisnute tipke u tri kuta pravokutnika daju lažnu tipku u četvrtom kutu, jer struja nađe zaobilazni put.
  • Biblioteka Keypad skenira tipkovnicu umjesto nas, pa je program mnogo kraći, ali lažne tipke ne uklanja. U fliperu je ne koristimo, jer skenira najviše jednom u 10 ms i može propustiti kratak udarac kuglice.
  • Dioda propušta struju samo od anode prema katodi. Pruga na diodi je katoda.
  • Dioda uz svaku tipku zaustavi zaobilazni put, pa lažnih tipki nema.

Mali kviz

1. Koliko pinova treba matrica s 8 redaka i 8 stupaca, i koliko prekidača može imati?
8 + 8 = 16 pinova, a prekidača može biti 8 × 8 = 64.
2. Kako program zna koja je tipka pritisnuta?
Program uključuje redak po redak i u svakom čita sve stupce. Ako stupac čita LOW dok je uključen neki redak, pritisnuta je tipka u kojoj se križaju taj redak i taj stupac.
3. Zašto isključeni redak nije HIGH, nego INPUT?
Dvije pritisnute tipke u istom stupcu spojile bi redak na HIGH s retkom na LOW. To je kratki spoj između dva pina. Ulaz nije spojen ni s čim, pa kroz njega struja ne teče.
4. Zašto prvo učitavamo program, a tek onda spajamo tipkovnicu?
Stari program na Arduinu možda koristi iste pinove kao izlaze, na primjer program semafora. Ako bi on radio dok pritišćemo tipke, mogao bi spojiti izlaz na HIGH s izlazom na LOW. Naš program redke drži kao ulaze dok ih ne skenira, pa je siguran.
5. Što je redci[0] u programu iz Vježbe 1?
  1. Brojimo od nule, pa je redci[0] prva vrijednost u nizu {12, 11, 10, 9}: pin retka R1.
6. Koliko puta se izvede tijelo unutarnje petlje kada getKey() skenira cijelu tipkovnicu?
16 puta. Vanjska petlja prođe kroz 4 retka, a unutarnja za svaki redak kroz 4 stupca: 4 × 4 = 16, jednom za svaku tipku.
7. Kada se pojavi lažna tipka?
Kada su pritisnute tri tipke u tri kuta pravokutnika u matrici. Struja tada nađe zaobilazni put kroz te tri tipke, pa stupac četvrtog kuta čita LOW, kao da je pritisnuta i četvrta tipka.
8. Na koju stranu okrećemo diodu uz tipku i zašto?
Anoda je prema tipki i stupcu, a katoda, s prugom, prema retku. Tako dioda propušta struju od stupca prema uključenom retku, kako teče kroz pritisnutu tipku, a zaustavlja struju koja bi zaobilaznim putem išla unatrag.