Table of Contents

Digital Sand Timer

Nume: ANA Elena-Diana

Grupa: 331CB

Introducere

Digital Sand Timer (Clepsidra Digitala) - inovația care transformă jocurile de masă în experiențe mult mai fun! Cu un sunet distinct și lumini dinamice, Clepsidra Digitală adaugă un element palpitant, distractiv si interactiv partidelor de joc. Înlocuind clepsidra tradițională, acest companion digital asigură respectarea limitelor de timp în jocuri precum Activity, oferind o experiență de fair-play pentru toți jucătorii. Simplu de utilizat și elegant în design, Clepsidra Digitală este must-have-ul pentru o seara fun si fara certuri cu prietenii tai!

Descriere Generala

In proiectarea clepsidrei folosesc o placă Arduino Pro Mini ATmega328p ca unitate principală de control. Orientarea clepsidrei este detectată de un modul accelerometru și giroscop MPU6050, care permite detectarea direcției în care “nisipul se scurge”. Simulez acest proces de scurgere a nisipului cu ajutorul a două matrice LED de tip MAX7219, care vor aprinde si vor stinge anumite leduri. Buzzerul activ OKY0151 emite un sunet la expirarea timpului, butoanele permit reglarea timpului si senzorul tactil reprezinta un meniu de selectie a sunetului redat.

Inainte de a porni timerul, clepsidra afiseaza “grauntele” pe matricea de sus (detectată de MPU6050), adica are aprinse un numar de leduri proportional cu numarul minutelor masurate. Clepsidra va avea un sunet si o cuanta de timp predefinite, care vor fi folosite daca utilizatorul nu selecteaza nimic din butoane/meniu.

Utilizatorul poate modifica cuanta de timp folosind butoanele dedicate pentru a crește, respectiv scădea minutele. Alegerea sunetului redat de buzzer se realizează printr-un senzor tactil cu patru butoane - fiecare reprezentand o “melodie” ce poate fi redata pentru a semnala expirarea timpului.


Utilizatorul va putea vedea toate aceste modificari pe masura ce le savarseste - reglarea timpului va modifica numarul de “graunte” afisate in jumatatea de sus, iar alegerea unui sunet va reproduce acel sunet pentru a confirma ca a fost selectat.


Deoarece numarul de leduri care pot fi aprinse pe o matrice este limitat la 64, la un moment dat, cresterea/scaderea minutelor nu va mai putea fi observata pe matricea superioara; aceasta limita este de 5 minute.

În modul normal de funcționare, clepsidra simulează căderea grânelor de nisip de la o matrice LED la alta, în funcție de orientarea detectată de MPU6050. La expirarea timpului, buzzerul emite sunetul selectat anterior. Toate aceste funcționalități sunt integrate într-un design compact, iar piesele sunt interconectate prin intermediul unui breadboard.

Clepsidra porneste dintr-o stare default - in care afiseaza particule echivalente unui minut, in matricea detectata a fi 'top' de catre senzor si asteapta modificari (optionale) de la utilizator (ex: modificare cuanta timp). Dupa ce modificarile au fost sau nu facute, va fi necesar sa se apese butonul de start pentru a incepe masurarea timpului. Cand timpul s-a scurs, se va auzi sunetul selectat, iar apoi clepsidra se va reseta automat in starea default.

Hardware Design

Componentele hardware folosite in acest proiect sunt:

  • Arduino Pro Mini ATmega328p
  • accelerometru și giroscop MPU6050
  • 2x matrice LED MAX71219
  • buzzer activ OKY0151
  • butoane - reglaj timp
  • modul senzor tactil OKY3421 - alegere sunet produs
  • rezistenta 1kohm
  • adaptor FT232 OKY3410-1 - conectare laptop

Am conectat matricele de leduri, butoanele, buzzerul si modulul cu senzor tactil la pini digitali ai placutei Arduino.

Am folosit pinul 3 pentru conectarea buzzerului, astfel incat sa ii pot transmite un semnal de tip PWM - pulse witdh modulation - pentru a reda anumite frecvente ale sunetului emis; astfel am putut sa implementez redarea anumitor note muzicale pentru a “compune” muzicuta redata la expirarea timerului. Pentru a regla volumul sunetului emis, am adaugat o rezistenta de 1kohm in serie cu buzzerul.

Adaptorul pentru seriala este conectat cu pinii RXI, TXO, CTS, VCC si GND si asigura atat comunicarea cu laptopul cat si tensiunea de 5V necesara componentelor circuitului.

Modulul accelerometru si giroscop comunica cu placuta prin intermediul protocolului I2C; asadar am conectat pinii SDA si SCL ai senzorului cu pinii analogici A4 respectiv A5 ai placutei, pini dedicati protocolului mentionat.

Pentru restul componentelor am folosit pini digitali disponibili, fara a urma vreo regula.

Legaturile intre componente si pinii folositi sunt redate in detaliu in schema:

Am montat senzorul MPU6050 cu axa OX perpendiculara pe plan - voi folosi acceleratia de pe aceasta axa pentru a determina orientarea clepsidrei.

Software Design

  • Am folosit Arduino IDE 2.3.2 pentru a scrie programul
  • Am utilizat bibliotecile: LedControl si MPU6050 pentru a putea comunica cu matricele de leduri, respectiv cu accelerometrul
  • Am folosit biblioteca Delay din care am luat un non-blocking delay pe care il folosesc pentru a calcula cat timp trece la fiecare particula care “cade”

Am folosit biblioteca LedControl pentru a putea avea acces la fiecare led individual din matricele de leduri; folosesc functii precum:

Pe langa aceste functii, am mai implementat cateva pentru a-mi usura lucrul cu stucturi de date de tip 'coord' - pentru ca am folosit astfel de structuri cand determinam coordonatele rezultate in urma unei mutari stanga/dreapta/jos a “particulelor”

Am folosit biblioteca MPU6050 pentru a folosi senzorul. Acesta foloseste protocolul I2C pentru a comunica cu placuta Arduino; am initializat un obiect al clasei: 'MPU6050 mpu6050()' si am folosit un obiect de tip Wire care asigura comunicarea; in setup am apelat Wire.begin() pentru a-l initializa. Pentru a calibra aparatul apelez: 'mpu6050.initialize()' si avertizez utilizatorul sa il tina nemiscat pentru ca acesta sa-si poata lua ca referinta starea initiala. Apoi apelez: 'getAccelerationX()' pentru a citi acceleratia obiectului pe axa OX si de aici deduc “gravitatia” pe care “particulele” mele de nisip trebuie sa o respecte (adica matricea top va fi A cand acceleratia e negativa si B cand e pozitiva).

Ca logica principala, clepsidra mea are 3 stari de functioare - reset, settings si running/hourglass mode. In functia setup(), dupa ce initializez pinii pentru butoane, buzzer etc, voi trece in modul 'RESET'; de asemenea, dupa terminarea timpului, tot in acest mod se va trece.

Se va apela functia 'resetMatrices' care reinitializeaza variabilele globale cu valorile lor default, apoi calculeaza orientarea matricelor (determina care e top, care e bottom) si apeleaza 'fillMatrices' - functie care goleste matricea de bottom si “umple” matricea de top cu un anumit numar de “particule”/leduri aprinse. Din modul reset se va trece automat in modul 'SETTINGS', unde utilizatorul poate modifica valorile default.

In acest mod se vor citi (in loop) starile tuturor butoanelor si ale touchpadului si in functie de acestea se pot intampla urmatoarele lucruri:

  1. cand se apasa pe butonul 'ADD': se mareste cuanta de timp cu un minut - si se vor afisa mai multe particule pe ecran
  2. cand se apasa pe butonul 'DEC': scade cuanta de timp cu un minut - se vor afisa mai putine particule
  3. cand se apasa pe butonul 'START': porneste clepsidra - se iese din modul settings, se intra automat in modul 'HOURGLASS' si incepe cronometrul
  4. cand se apasa pe tasta 1/2/3/4 a touchpadului: se alege sunetul 1/2/3/4 - se va reda sunetul 1/2/3/4 pentru a se confirma ca a fost selectat

Logica de cronometrare se bazeaza pe un non-blocking delay pe care il initializez cu 'particle_seconds' secunde si verific daca timpul din delay a trecut de fiecare data cand ma uit daca o particula poate trece din top in bottom. In momentul in care timpul a trecut, las particula sa treaca si reinitializez delay-ul.


In ceea ce priveste logica de afisare a particulelor, avand in vedere ca o matrice are 64 de leduri, nu voi putea sa redau vizual incrementarea minutelor dupa o anumita limita. Asadar, m-am gandit ca fiecare led sa reprezinte un numar de secunde - by default 5 - salvat in 'particle_seconds' si sa se poata afisa maxim 60 de particule - adica echivalentul a 5 minute; dupa aceasta limita, voi schimba valoarea variabilei 'particle_seconds' (deoarece aceasta logica ma va ajuta sa-mi dau seama cat timp trebuie sa treaca intre “scurgerea” a 2 particule consecutive), dar nu voi mai schimba numarul de particule afisate (acest numar este salvat in 'particles').

In acest mod, atat cuanta de timp cat si sunetul sunt setate si incepe cronometrul propriu-zis. Se apeleaza functia 'updateMatrix' in loop si se adauga un delay dupa fiecare apel pentru a se putea observa “scurgerea” particulelor. Oprirea cronometrului este detectata la trecerea ultimei particule din matricea top in matricea bottom; in acest moment se va porni un non-blocking delay care va astepta 'particle_seconds' si apoi va opri clepsidra prin redarea sunetului si modificarea variabilei 'mode' in 'RESET' mode.

Particulele se “misca” pe diagonala fie din 0.0 in 7.7, fie invers (in functie de care matrice e top - matricea A ⇒ prima varianta, matricea B ⇒ a 2-a varianta). Se apeleaza 'dropParticle' pentru a verifica daca o particula a ajuns in punctul de trecere dintre top si bottom matrices (de ex, cand A e top matrix, acest punct este (MATRIX_A, 0, 0), (MATRIX_B, 7, 7), unde ledul din A este aprins si ledul din B este stins). Parcurge ledurile aprinse si incearca sa le mute intr-una din directiile - stanga, dreapta, jos - prin apelul 'moveParticle' pe ambele matrice.

Verifica printr-un non-blocking delay daca au trecut 'particle_seconds' secunde de la ultima particula care a trecut din top in bottom. Daca timpul a trecut, verific orientarea clepsidrei si inversez valorile ledurilor din punctele/colturile de trecere top-bottom ale matricelor.

Verifica pentru fiecare particula daca are un loc disponibil - in stanga, dreapta sau jos, unde se poate deplasa. Disponibilitatea inseamna ca acel led este stins in acel moment. Se va prioritiza mutarea in jos, iar daca aceasta nu se poate face, se va alege stanga/dreapta random.

Arhiva cu codul sursa: clepsidra_digitala.rar

Rezultate

Am reusit sa implementez tot ce mi-am propus pentru acest proiect.

Concluzii

Momentele in care am intampinat dificultati cu proiectul meu au fost legate de conectarea senzorului MPU6050 si implementarea logicii de “scurgere” a particulelor, precum si asigurarea acuratetii cu care clepsidra masoara timpul.

Neavand pini pentru A4 si A5 pe arduino mini, am incercat sa conectez senzorul la alti pini si sa folosesc biblioteci de genul 'Software wire' pentru a asigura comunicarea I2C intre placuta si senzor. Desi am reusit conectarea, nu am reusit sa citesc corect datele de pe MPU6050 (nu erau compatibile cu biblioteca dispozitivului); asadar mi-am cumparat pini pentru A4, A5 si i-am lipit, iar mai apoi, folosind biblioteca MPU6050 a fost destul de simplu sa folosesc senzorul.

In implementarea logicii de miscare a particulelor a trebuit sa tin mereu cont de care matrice este 'top' si sa calculez mutarile in functie de asta (deoarece intr-un caz mut din coltul 0.0 in 7.7 si in celalalt caz, invers). De asemenea, a trebuit sa ma gandesc cum corelez trecerea particulelor cu trecerea reala a timpului.

Un alt aspect a fost faptul ca trebuia sa reglez delay-urile din functia loop astfel incat sa nu interfereze cu non-blocking delay-ul care semnala cand sa se miste urmatoarea particula; de asemenea a trebuit sa ma asigur ca nici functiile de miscare a particulelor nu rulau intr-un timp prea mare. Mi s-a intamplat sa am delay-uri prea mari in loop si sa se intarzie verificarea timeout-ului, astfel clepsidra ramanea in urma fata de timpul real; am reusit sa rezolv aceasta problema optimizand functiie si reducand timpul din delay-uri, astfel incat sa se poata observa stingerea si aprinderea ledurilor - care dau efectul de “curgere”, pastrand totodata acuraterea clepsidrei.

Dupa ce am trecut de aceste momente si am inteles mai bine cum trebuie sa programez, pot spune ca a fost chiar interesant si placut sa scriu cod si sa pot vedea cum sunt influentate in realitate niste dispozitive.

Demo

https://drive.google.com/file/d/1nWGXsg7cGIAmB01IPp6FXS4MtSJnHUi5/view?usp=drive_link

Resurse - hardware

Resurse - software

Jurnal