Arduino – Ziua 5 – Să ne mai jucăm puţin cu ledul şi butonul… sau ce este un debounce…

Created at: martie 3, 2017; Last update: martie 3, 2017

Pornind de la tutorialul anterior, cum am putea face astfel încât la o apăsare şi eliberare a butonului, ledul să se aprindă şi să stea aprins până la următoarea apăsare/eliberare a butonului? Adică, dacă tot avem un microcontroller care face aprinderea/stingerea unui led, să ne bucurăm de acest microcontroller.

Ei bine, Ne vom folosi de o altă variabilă astfel încât, în momentul în care se dă drumul butonului, variabila respectivă să rămână cu valoarea dată în momentul apăsării butonului… Hai să vedem codul, pentru că aşa înţelegem mai bine. Şi să începem cu o greşeală…

Ai fi zis că acest cod ar trebui să fie ok. Dacă dai verify/compile şi faci upload, ar trebui să funcţioneze… Dar asta nu se întâmplă. Poţi să îmi spui de ce? Hai, gândeşte-te!

După ce te-ai gândit la răspuns putem trece mai departe…

Acum urmează răspunsul….

Ei bine, noi am definit stareLed ca fiind egal cu 0 în cadrul funcţiei loop(), care funcţie se repetă imediat ce s-a terminat. Ce înseamnă asta? Înseamnă că aproape mereu stareLed va reveni la 0. Hai să mutăm stareLed în afara loop()-ului.

 

Acum, dacă testăm apăsarea/eliberarea butonului ledul ar trebui să rămână aprins. Apoi, la repetarea secvenţei de apăsare/eliberare, ledul ar trebui să se stingă. Dacă faci asta de destule ori ar trebui să meargă. Dar… nu merge chiar de fiecare dată… De ce? Te poţi concentra din nou pentru a găsi singur răspunsul? Dacă nu, îl putem căuta împreună…

Ei bine, întâmplarea are legătură tot cu faptul că totul se întâmplă în loop(). Hai întâi să mai uşurăm codul şi apoi vom da răspunsul… Cine ştie? Poate pe parcurs îţi vei da seama şi de răspuns.

Secvenţa aceasta de cod:

…poate fi scrisă mai scurt aşa:

Pur şi simplu spunem variabilei stareLed să ia valoarea opusă celei pe care o are deja.

Acum hai ca în loc de numărul pinului să ne folosim de o denumire prin care să identificăm mai uşor ce pin aparţine cărui element. Aşadar, unde am definit stareLed, definim şi pinii cu denumiri mai uşor de înţeles

 

Acum hai să ne uităm aici:

Nu am putea scrie totul mai simplu? De ce nu am scrie pur şi simplu:

Şi cu ocazia aceasta, de ce nu am modifica şi partea aceasta de cod:

…cu…

Ok… Hai să ne mai uităm o dată la codul în totalitate, să îl compilăm şi să îl încărcăm pe microcontroller:

 

Mult mai aerisit… Acum să ne întoarcem la problema noastră. Se pare că nu de fiecare dată când apăsăm/eliberăm butonul ledul se aprinde/stinge. De ce oare? Se pare că oricât de rapidă ar fi apăsarea butonului, în interiorul lui au loc mai multe apăsări/eliberări ale voltajului. Aşadar, ce ne facem? Problema rezidă în faptul că noi nu avem o siguranţă şi rapiditate atât de mare în apăsare încât microcontrollerul să fie sigur asupra acţiunii noastre. Prin urmare, ar trebui să “obligăm” microcontrollerul să aştepte puţin după apăsarea noastră pentru a-şi da seama dacă totul este în regulă. Vom face asta în cadrul unei noi funcţii care va returna o valoare booleană:

 

Ce face funcţia aceasta? Funcţia primeşte ca variabilă o valoare care îi spune care a fost situatia butonului la momentul chemării funcţiei (dacă butonul a fost apăsat sau neapăsat). Apoi funcţia verifică dacă în prezent (ţine minte că intre “prezent” şi chemarea funcţiei au trecut deja câteva miimi de secundă în care butonul poate să fi avut deja cateva porniri/opriri care au “scăpat” degetului nostru). Dacă vede că cele două variabile sunt diferite, atunci pesemne că ceva nu este în regulă. Din această cauză, micro-controllerul este pus să aştepte 5 milisecunde şi apoi este pus din nou să citească valoarea pinului buton, valoare care este trimisă înapoi variabilei care a chemat funcţia. Dar ce variabilă cheamă funcţia? Hai să schimbăm din nou loop()-ul pentru a ne folosi de funcţia debounce():

Acum, pentru a ne folosi de variabilele currentButton şi lastButton trebuie să le definim undeva. Le vom defini printre celelalte variabile globale cu valoarea iniţială LOW. Hai să vedem din nou întreg sketch-ul:

 

Bun… Acum dacă reîncărcăm sketch-ul compilat pe micro-controller totul ar trebui să meargă cum trebuie. Şi aşa se va întâmpla.

Dar stai!!!

Delay-ul acela de 5 milisecunde este unul ales arbitrar. Adică de unde ştim noi că un delay de 5 milisecunde ar rezolva dilema noastră? Poate nu are nevoie de 5 milisecunde. Poate are nevoie de mai puţin. Sau poate are nevoie de mai mult?

Atunci hai să punem un delay de o milisecundă, după care să rechemăm funcţia debounce() înăuntrul funcţiei debounce (funcţie recursivă) pentru a verifica din nou că totul este ok:

Grozav. Hai să revedem codul final:

 

Asta-i tot!…

Oups… Îmi cer scuze… Nu vreau să se creadă că am un creier cât o baniţă. Nu… Ideea cu debounce()-ul nu este a mea. Am găsit-o în acest video pe care te invit să îl urmăreşti (este grozav!):

Lasă un răspuns

Your email address will not be published. Required fields are marked *

No spam? * Time limit is exhausted. Please reload CAPTCHA.