Interakcija korisnika sa Arduino platformom Do sada nismo poklanjali naročitu pažnju jednoj važnoj oblasti koja se odnosi na procesiranje informacija unesenih od strane korisnika, pa ćemo situaciju pokušati da popravimo ovim pregledom. Tasteri i prekidači Svi znamo da se razne vrste tastera veoma često koriste u sklopu elektronskih uređaja. Iako vizuelno mogu mnogo da se razlikuju, princip rada im je jednostavan i sličan. Funkcija tastera je da na intervenciju korisnika o(ne)mogući protok struje iz jednog dela komponente u drugu, slično funkcionisanju visećeg mosta. Nije moguć prelazak sa jedne na drugu obalu reke, sve do momenta dok most nije spušten. Treba pomenuti da postoji i poseban (ređe korišćen) tip tastera koji radi suprotno, odnosno, na izvršeni pritisak zaustavlja protok struje, dok u standardnom stanju struja kontinuirano teče. Takvi tasteri se označavaju kao NC (normally closed), dok su standardni označeni kao NO (normally open). Osim tastera (push buttons), često se sreću i prekidači (switches), čija je funkcija da konstantno drže protok struje u uključenom ili isključenom stanju. Postoji i svojevrsna kombinacija klasičnog tastera push tipa sa prekidačem (na ilustraciji, sa plavom kapicom) koja konstantno propušta struju dok se komponenta nalazi u poziciji „uključeno”, odnosno, fiksirana u položaju prema dole. Tasteri se obično realizuju sa dva reda kontaktnih nožica. Razlog postojanja dva reda jeste u tome što veći broj nožica omogućuje bolju stabilnost komponente na štampanoj ploči. U radu sa Arduinom najčešće ćemo koristiti tastere push tipa sa po četiri pina koja smo na ilustraciji označili slovima AB (ulaz) i CD (izlaz). Dovoljno je dovesti napon na samo jedan od ta dva pina, pošto su oni međusobno povezani. Šta se dešava kada direktno povežemo taster na Arduino? Iako bismo očekivali da, u zavisnosti od toga da li je taster pritisnut ili ne, na ulazu mikrokontrolera imamo stanje logičke nule ili jedinice, dešava se da u stvari imamo nedefinisano stanje visoke impedanse kod koga se vrednost stalno nepredvidivo menja usled elektromagnetnog šuma. Tačnije, ovo stanje imamo samo kada taster nije pritisnut. Da bismo lakše shvatili o čemu se radi, pogledajmo sledeći primer: void setup() { pinMode(2, INPUT); //ovde prikljucujemo taster Serial.begin(9600); } void loop() { Serial.println(digitalRead(2)); delay(500); } Kôd čita ulaz na digitalnom pinu 2. Ukoliko pratimo pristigle podatke u prozoru terminala, videćemo da se oni sastoje od nasumičnih vrednosti nula i jedinica. Ako taster ili žicu koja vodi do pina mikrokontrolera, dodirnemo rukom ili ih izložimo nekom izvoru elektromagnetnog zračenja, videćemo da dolazi do promena u očitanim podacima. Da bi se ovo izbeglo, potrebno je dodati otpornik na jedan od sledećih načina: U pitanju je tehnika koja se vrlo često koristi u radu sa integrisanim kolima kada je potrebno da jasno postavimo pin u stanje inicijalne logičke nule ili jedinice. Gornji primer pokazuje vezu preko pull-up otpornika (povezuje se na Vcc liniju). Sve dok taster nije pritisnut, pin Arduina dobija napon koji odgovara vrednosti HIGH, dok nakon pritiska na taster dolazi do oticanja struje prema uzemljenju, a vrednost na posmatranom pinu pada na LOW. Dakle, kada imamo stanje LOW, to je znak da je taster pritisnut, dok HIGH znači da nije. Drugi primer je vrlo sličan, samo što sada pin dobija napon LOW dok taster nije pritisnut. Nakon pritiska dolazi do preusmeravanja struje od izvora 5V prema pinu Arduina i on dobija vrednost HIGH. Pull-down otpornici se uvek povezuju preko GND linije. Generalno, u praksi je moguće koristiti oba načina povezivanja, ali moramo obratiti pažnju na jedan važan detalj. Zbog uštede električne energije koristimo pull-up način ukoliko je taster retko u stanju kontakta (najčešći slučaj), dok se pull-down preferira tamo gde je taster/prekidač najveći deo vremena uključen. U radu sa naponom od 5V (Arduino Uno), najčešće vrednosti korišćenog otpornika su 4,7 i 10 kilooma. Moguće je izbeći korišćenje eksternih otpornika, aktiviranjem onih koji su ugrađeni u sam mikrokontroler. Naime, svi ulazni pinovi čipa Atmega328P u sebi sadrže sićušne otpornike veličine 20 kilooma, koje je moguće aktivirati na dva načina: pinMode(pin, INPUT); digitalWrite(pin, HIGH); ili pinMode(pin, INPUT_PULLUP); I ovde je moguće koristiti pristup sa korišćenjem biblioteke i bez nje. S obzirom na odlične praktično potvrđene rezultate rada, ovde pokazujemo primer pravilnog očitavanja tastera uz pomoć biblioteke Debounce2, koju preuzimamo sa goo.gl/7H99go, gde se nalazi i spisak podržanih funkcija. #include <Bounce2.h> Bounce d_taster = Bounce(); //Instanciranje objekta void setup() { pinMode(2,INPUT_PULLUP); //ukljucujemo ugradjeni otpornik pinMode(13,OUTPUT); //LED na pinu 13 d_taster.attach(2); //pratimo taster na portu 2 d_taster.interval(5); //interval (ms) } void loop() { d_taster.update(); //apdejtujemo stanje int stanje = d_taster.read(); //uzmi novu vrednost if ( stanje == LOW) { //taster pritisnut? digitalWrite(13, HIGH ); //upali LED } else { digitalWrite(13, LOW ); //LED ugasen } } Postoji mogućnost da istovremeno koristimo više tastera preko jednog analognog ulaza na Arduinu i to tako što svaki taster povežemo sa otpornikom iste vrednosti, a sve otpornike zatim međusobno povežemo serijski, dok sve izlaze šaljemo na analogni pin. U zavisnosti od toga koji taster je pritisnut, menja se i vrednost otpora koji će uzrokovati različit nivo napona na analognom pinu. Loša strana ovakvog vezivanja je to da istovremeno može biti očitan samo jedan taster. Ako želimo simultano očitavanje više njih, potrebno je da koristimo različite otpornike kojima je vrednost bar dvostruko veća od prethodnika u vezi. Zbog ograničenosti prostora, ovu temu ostavljamo za neki drugi put. Da bismo zaokružili priču o tasterima i prekidačima, pomenućemo i interesantnu varijantu ulaznih uređaja koji se nazivaju DIP (dual in-line package) prekidačima. Reč je, najčešće, o plastičnim kutijicama koje sa donje strane imaju pinove kojima se fiksiraju na štampanu ploču i na sebi sadrže veći broj malih prekidača, uglavnom od dva do deset. Njihova funkcija je jedino ograničena maštom kreatora, a najčešće se koriste kao džamperi za podešavanje uređaja. Sa cenom od 50 centi i malim dimenzijama, mogu odlično da posluže u mnogim projektima. Potenciometri Potenciometri su uređaji kojima se menja vrednost otpora pomeranjem pokretnog dela, koji je obično rotacionog tipa ili u obliku slajdera. Drugim rečima, u pitanju su promenjivi otpornici čija se vrednost definiše akcijom korisnika. Dva glavna tipa su: logaritamski (označeni slovom A ispred vrednosti) i linearni (slovo B). Uzmimo, na primer, potenciometar od deset kilooma. Kada se nalazi na minimumu, generiše otpor od nula oma, dok na maksimumu postiže svoju nominalnu vrednost od deset kilooma. Za očitavanje je potrebno da se potenciometar priključi na neki od analognih ulaza Arduina, gde će se promene otpora manifestovati promenom napona u analogno-digitalnom konverteru mikrokontrolera. Sve se to dešava u skladu sa Omovim zakonom, pa ćemo najveći napon imati kada je potenciometar na minimumu, a najmanji kada ga postavimo u krajnju poziciju. Arduino prepoznaje 1024 (210) stanja na A/D ulazu, što u prevodu znači da se prepoznaju promene napona u koracima od 0,00488V (5 mV). float alfa = 0.6; //koeficijent ublazavanja (0-1) int EMA = 0; //inicijalizacija EMA int stara = 0; //prethodna vrednost EMA void setup(){ Serial.begin(9600); EMA = analogRead(A3); //EMA pocetna vrednost } void loop(){ int vrednost = analogRead(A3); if (vrednost != stara){ //doslo do promene? EMA = (alfa*vrednost) + ((1-alfa)*EMA); Serial.println(EMA); stara = vrednost; //pamti promenu delay(20); } } Kod za demonstraciju korišćenja je bio veoma jednostavan, pa smo odlučili da ga malo zakomplikujemo uvođenjem mehanizma za filtriranje podataka, koji je zasnovan na korišćenju funkcije eksponencijalne pokretne prosečne vrednosti (Exponential Moving Average). Iako zvuči prilično „matematički”, stvar je sasvim prosta i cela logika je sadržana u sledećoj liniji koda: EMA = (alfa*vrednost) + ((1-alfa)*EMA); Što je ekvivalentno formuli: EMAt= a*pt + (1- a)*EMAt-1 Alfa je konstanta koja može imati vrednost od 0 do 1 i predstavlja intenzitet filtera, pt predstavlja trenutnu vrednost A/D konvertera, dok je EMAt-1 vrednost EMA za prethodni period merenja. Filtriranjem se umnogome otklanja šum koji se javlja u radu sa elektronskim komponentama. Postoji više načina za računanje pokretne srednje vrednosti, a EMA spada među one koji se najviše koriste. Karakteristika EMA je da nikada ne dobija vrednost nula i da daje prednost novijim rezultatima merenja u odnosu na one starije. Senzorska tastatura Princip rada je veoma jednostavan. Svi tasteri se nalaze na preseku po jednog reda i kolone. Naš zadatak je da ustanovimo koji od njih je pritisnut. To radimo tako što svaki red postavljamo u stanje logičke nule i zatim proveravamo stanje na kolonama. Pritisak tastera dovodi do prenosa logičke nule na kolonu sa pritisnutim tasterom, i kada očitamo da se na toj liniji pojavila logička nula, znamo da je taster pritisnut. Na primer, ukoliko je pritisnut taster 7, imaćemo na linijama 3 i 5 stanje logičke nule, što jasno identifikuje poziciju tastera. const char taster[4][4]{ {’1’, ’2’, ’3’, ’A’}, {’4’, ’5’, ’6’, ’B’}, {’7’, ’8’, ’9’, ’C’}, {’*’, ’0’, ’#’, ’D’} }; int red[4] {11, 10, 9, 8}; //linije 1,2,3,4 (izlaz) int kol[4] {7, 6, 5, 4}; //linije 5,6,7,8 (ulaz) void setup() { Serial.begin(9600); pinMode (11, OUTPUT); //red 1 (linija 1) pinMode (10, OUTPUT); pinMode (9, OUTPUT); pinMode (8, OUTPUT); //red 4 (linija 4) pinMode (7, INPUT); //kolona 1 (linija 5) pinMode (6, INPUT); pinMode (5, INPUT); pinMode (4, INPUT); //kolona 4 (linija 8) digitalWrite(7, HIGH); //input pinovi, digitalWrite(6, HIGH); //stanje logicko 1 digitalWrite(5, HIGH); digitalWrite(4, HIGH); } void loop() { for (int r = 0; r <= 3; r++) //4 reda { //saljemo LOW na red r digitalWrite(red[r], LOW); for (int k = 0; k <= 3; k++) //4 kolone { //proveri da li je ta kolona LOW? if (digitalRead(kol[k]) == LOW) { //jeste, ispisi pritisnuti taster Serial.print(taster[r][k]); Serial.print(" "); } } //taster nije pritisnut //vracamo red na logicku jedinicu digitalWrite(red[r], HIGH); } } Kao što to u Arduino svetu često biva, korisnicima na raspolaganju stoje biblioteke koje uveliko pojednostavljuju programiranje. U ovom slučaju to je biblioteka Keypad, koju je moguće učitati preko menadžera biblioteka Arduino IDE. #include <Keypad.h> Const char taster[4][4] = { {’1’,’2’,’3’,’A’}, {’4’,’5’,’6’,’B’}, {’7’,’8’,’9’,’C’}, {’*’,’0’,’#’,’D’} }; byte red[4] = {11, 10, 9, 8}; //linije 1,2,3,4 byte kol[4] = {7, 6, 5, 4}; //linije 5,6,7,8 Keypad senz = Keypad(makeKeymap(taster), red, kol, 4, 4); void setup(){ Serial.begin(9600); } void loop(){ char znak = senz.getKey(); if (znak){ Serial.print(znak); //salji na serijski port Serial.print(" "); } } Sledeće dve varijable red i kol definišu pinove Arduina koje ćemo koristiti za povezivanje sa redovima i kolonama tastature. U sledećem redu kreiramo konstruktor senz sa parametrima koji definišu pinove za redove i kolone, kao i dimenzije matrice. Kao parametar se prosleđuje i raspored tastera. Vrednost koja odgovara pritisnutom tasteru dobija se sa metodom getKey. U našem primeru samo ispisujemo taj znak, a moguće je uz pomoć petlje switch proveravati koji je taster pritisnut i na osnovu toga preduzimati željenu radnju. Neko se može zapitati, zašto da pišemo komplikovani program bez biblioteke, kada je sa bibliotekom sve moguće odraditi brže i elegantnije. Odgovor glasi: varijanta sa bibliotekom zauzima 900 bajtova memorije više, što je važan parametar kada se radi sa mikrokontrolerima. Inače, biblioteka Keypad ima dosta zanimljiv skup funkcija koje omogućavaju pisanje vrlo fleksibilnog koda, kao i mogućnost korišćenja više tastatura odjednom. Desktop tastatura Tastature sa PS/2 konektorom danas se retko koriste, ali se relativno lako mogu naći na starim računarima. Ono što je za nas veoma zanimljivo jeste činjenica da se takve tastature na vrlo jednostavan način mogu priključiti na Arduino i maksimalno olakšati unos podataka. Šestopinske konektore ženskog tipa moguće je naručiti preko interneta (oko 50 centi) ili ih možemo skinuti sa neke stare neispravne matične ploče. Moguće je kupiti gotove module za priključivanje PS/2 tastature po ceni od jedan do jedan i po evro, što smatramo sasvim prihvatljivim. Gledano sa prednje strane, konektori imaju sledeće kontakte za lemljenje na ploču: Kao što vidimo, od šest kontakata koristi se četiri, dva za napajanje (Vcc i GND), jedan za sinhronizaciju prenosa (CLK) i jedan za prenos podataka (DATA). Postoji nekoliko biblioteka koje podržavaju rad sa PS/2 tastaturom, ali je najpoznatija ona pod nazivom PS2Keyboard (goo.gl/MjsjD8). Tu je i zanimljiva varijacija na temu pod nazivom PS2KeyAdvanced (goo.gl/ZUAU6X) koja, osim manjeg zauzeća memorije, omogućava i pojednostavljen ispis na priključenom LCD ekranu. Obe varijante je moguće preuzeti preko ugrađenog menadžera biblioteka. U radu sa Arduinom UNO, na raspolaganju imamo samo dva pina sa mogućnošću generisanja spoljašnjeg hardverskog prekida (interrupt) i oni su smešteni na pozicijama D2 i D3 (digitalni pinovi 2 i 3). Drugi Arduino modeli imaju veći izbor, pa tako MEGA 2560 omogućava priključivanje na pinove 2, 3, 18, 19, 20 i 21. Obavezno je priključiti CLK signal na neki od tih pinova, pošto u suprotnom tastatura neće funkcionisati. Pin za prenos podataka (DATA) možemo izabrati proizvoljno. #include <PS2Keyboard.h> PS2Keyboard kb; //kb je instanca klase PS2Keyboard void setup() { kb.begin(4, 3); //DATA na pin 4, CLK na pin 3 Serial.begin(9600); } void loop() { if (kb.available()) { //otkucan novi znak? char znak = kb.read(); //da, citamo ga //provera dela specijalnih karaktera if (znak == PS2_ENTER) { Serial.println(); } else if (znak == PS2_DELETE) { Serial.print("[DEL]"); } else if (znak == PS2_LEFTARROW) { Serial.print("[<--]"); } else if (znak == PS2_RIGHTARROW) { Serial.print("[-->]"); } else { //znak je slovo, ispisi ga Serial.print(znak); } } } Kao što smo videli mnogo puta do sada, rad sa Arduinom je izuzetno jednostavan, što potvrđuje i ovaj skeč. Konstruktor klase u bloku setup() prima parametre koji ukazuju na pinove Arduina korišćene za povezivanje tastature. Sa programskom petljom loop() pratimo pojavljivanje novog karaktera u baferu tastature. Ukoliko on postoji, prvo proveravamo da li pripada grupi specijalnih karaktera. To su karakteri koji se na ekranu ne prikazuju kao tekst, već obavljaju neku funkciju. Recimo, Enter počinje sa ispisom u novom redu, Delete briše poslednji znak i tako dalje. U našem primeru ne postoji kod koji bi odgovarajuće reagovao na ponašanje tih kodova (osim za Enter), već jednostavno ispisuje tekst koji nam govori da su ti tasteri pritisnuti. Na završetku koda, ukoliko novi karakter ne spada u grupu specijalnih znakova, smatramo da je u pitanju alfanumerički karakter i ispisujemo ga. Igor S. RUŽIĆ |
| |||||||||||||||||||
Home / Novi broj | Arhiva • Opšte teme | Internet | Test drive | Test run | PD kutak | CeDeteka | WWW vodič • Svet igara Svet kompjutera Copyright © 1984-2018. Politika a.d. • Redakcija | Kontakt | Saradnja | Oglasi | Pretplata • Help • English | |
SKWeb 3.22 |