Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pm:prj2025:vstoica:teodora.voicu0210 [2025/05/29 20:42]
teodora.voicu0210
pm:prj2025:vstoica:teodora.voicu0210 [2025/05/29 21:57] (current)
teodora.voicu0210 [Bibliografie/Resurse]
Line 124: Line 124:
 ===== Software Design ===== ===== Software Design =====
  
 +<​code>​
 +/*
 + ​* ​ DIGITAL DICE  - Arduino UNO
 + ​* ​ — Shake → pornește DICE.WAV pe pin 9
 + ​* ​ — Stop Shake → afișează două numere pe OLED
 + *
 + ​* ​ HARDWARE:
 + ​* ​   LIS2DH12 (I²C) ​       | SDA/SCL = A4/A5
 + ​* ​   SSD1306 OLED 128×64 ​  | SDA/SCL = A4/A5
 + ​* ​   Micro-SD (SPI)        | CS = 10
 + ​* ​   Buzzer pasiv          | pin 9 (Timer1 PWM)
 + */
  
-<note tip+#​include ​<Wire.h// permite comunicarea I2C 
-Descrierea codului aplicaţiei (firmware): +#include "​SparkFun_LIS2DH12.h"​ // driverul pentru accelerometru 
-  * mediu de dezvoltare ​(if any) (e.g. AVR Studio, CodeVisionAVR+#include <​SPI.h>​ // pentru SD (comunicarea SPI
-  * librării şi surse 3rd-party (e.g. Procyon AVRlib) +#include <SD.h> // pt citire/​scrie fisiere pe cardul SD 
-  ​* algoritmi şi structuri ​pe care plănuiţi să le implementaţi +#include <​TMRpcm.h>​ //  redarea fisierelor WAV mono printr-un PWM pe buzzer 
-  * (etapa 3) surse şi funcţii implementate +#​include ​<U8g2lib.h// desene pe OLED
-</note>+
  
-===== Rezultate Obţinute =====+#define SD_CS_PIN ​       10 // chip select pt modulul SD 
 +#define SPEAKER_PIN ​      9 // buzzerul pasiv conectat pe pinul 9 (pwm timer)
  
-<note tip> +#define SHAKE_THRESHOLD 2000     // daca diferenta de citiri depaseste pragul e considerat shake 
-Care au fost rezultatele obţinute în urma realizării proiectului vostru. +#define SHAKE_TIMEOUT ​   300     // ms fără miscare = aruncare terminata 
-</note>+#define RESULT_HOLD ​    ​1500 ​    /ms pastram rez pe ecran inainte sa schimbam iar la Ready
  
-===== Concluzii =====+const char WAV_NAME[] ​"​DICE.WAV";​
  
-===== Download =====+SPARKFUN_LIS2DH12 accel; // cream accelerometrul 
 +TMRpcm ​            ​audio;​ // playerul care genereaza pwm ul pt a reda fisierul wav pe buzzer 
 +U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0,​ U8X8_PIN_NONE);​ // obiectul care controleaza ecranul
  
-<note warning>​ +enum class Stare uint8_t { GATASHAKINGREZULTAT }// logicile posibile 
-O arhivă (sau mai multe dacă este cazul) cu fişierele obţinute în urma realizării proiectuluisurseschemeetc. Un fişier README, un ChangeLog, un script de compilare şi copiere automată pe uC crează întotdeauna o impresie bună ;-).+Stare stareCurenta = Stare::​GATA;​ // starea de start
  
-Fişierele se încarcă pe wiki folosind facilitatea **Add Images or other files**. Namespace-ul în care se încarcă fişierele este de tipul **:​pm:​prj20??:​c?​** sau **:​pm:​prj20??:​c?:​nume_student** (dacă este cazul). **Exemplu:​** Dumitru Alin, 331CC -> **:​pm:​prj2009:​cc:​dumitru_alin**. +unsigned long tStartStare;​ // mom cand s-a schimbat ultima data starea 
-</note>+int16_t lastX, lastY, lastZ; ​// valorile de pe fiecare axa a accelerometrului
  
-===== Jurnal ===== 
  
-<note tip+// primeste un sir si un font, si scrie acel text centrat orizontal la linia y pe ecran 
-Putețavea șo secțiune ​de jurnal ​în care să poată urmări asistentul ​de proiect progresul proiectului+void drawCentered(const char* text, uint8_t y, const uint8_t* font) { 
-</note>+  u8g2.setFont(font);​ // font select 
 +  int w = u8g2.getStrWidth(text);​ // latime txt 
 +  u8g2.firstPage(); ​ do { u8g2.drawStr((128 - w) / 2, y, text); } while (u8g2.nextPage());​ // plaseaza incep in centrul ecranului 
 +
 + 
 +void setup() { 
 +  // Serial.begin(9600);​ // pt debug 
 +  if (!accel.begin()) while (1);   // start accelerometru si se blocheaza daca lipseste 
 +  u8g2.begin();​ // initializeaza ecranul 
 +  drawCentered("​READY!",​ 32, u8g2_font_ncenB14_tr);​ // afis ready pt inceput 
 + 
 +  audio.speakerPin = SPEAKER_PIN;​ // spune playerului pe ce pin scoate semnal pwm catre buzzer 
 +  audio.CSPin ​     = SD_CS_PIN; // ce pin e chipselect pt sd 
 + 
 +  if (!SD.begin(SD_CS_PIN)) ​ while (1);    // stop dacă SD fail 
 +  if (!SD.exists(WAV_NAME)) ​ while (1);    // stop dacă lipseste DICE.wav 
 + 
 +  audio.setVolume(5); ​         // 0-6, 5 a fost optim 
 +  audio.quality(1); ​           // pt sunet mai clar 
 + 
 +  randomSeed(analogRead(A0));​ // foloseste zgomot de pe pinul A0 ca baza pt generarea numerelor aleatoare 
 +  lastX = accel.getRawX(); ​ lastY = accel.getRawY(); ​ lastZ = accel.getRawZ();​ // citeste si salveaza primele valori de la accelro 
 +
 + 
 +void loop() { 
 +  int16_t x = accel.getRawX(), ​ y = accel.getRawY(), ​ z = accel.getRawZ();​ // cit acceleratia pe fiec axa 
 +  int16_t dX = abs(x - lastX), ​ dY = abs(y - lastY), ​ dZ = abs(z - lastZ); // dif fata de ultima data 
 +  lastX = x;  lastY = y;  lastZ = z; // actualizare valori 
 + 
 +  switch (stareCurenta) { // algem ce stare urm in fct de starea curenta 
 + 
 +  case Stare::​GATA:​ 
 +    if (dX > SHAKE_THRESHOLD || dY > SHAKE_THRESHOLD || dZ > SHAKE_THRESHOLD) { // am detectat miscarea 
 +      stareCurenta = Stare::​SHAKING;​ // deci trecem in starea shaking 
 +      tStartStare ​ = millis(); 
 +      drawCentered("​Shake!",​ 32, u8g2_font_ncenB14_tr);​ // afisam shake 
 +      audio.play(WAV_NAME);​ // si redam sunetul DICE 
 +    } 
 +    break; 
 + 
 +  case Stare::​SHAKING:​ 
 +    if (dX > SHAKE_THRESHOLD || dY > SHAKE_THRESHOLD || dZ > SHAKE_THRESHOLD) { // daca ince se scturua accelreo 
 +      tStartStare = millis(); ​                // resetam timeoutul 
 +    } 
 +    if (millis() - tStartStare > SHAKE_TIMEOUT) {   // daca de la ultima miscare a trecut mai mult de shake timeout 
 +      audio.stopPlayback(); ​                  // oprim sunetul 
 +      uint8_t d1 = random(1,​7),​ d2 = random(1,​7);​ // afisam 2 nre random 
 +      char buf[6]; ​ snprintf(buf,​ sizeof(buf),​ "%d %d", d1, d2); 
 +      drawCentered(buf,​ 50, u8g2_font_logisoso32_tn);​ 
 + 
 +      stareCurenta = Stare::​REZULTAT;​ // trecem la starea de result 
 +      tStartStare ​ = millis(); 
 +    } 
 +    break; 
 + 
 +  case Stare::​REZULTAT:​ 
 +    if (millis() - tStartStare > RESULT_HOLD) { // daca a trecut timpul de cat tb tinut rez pe ecran 
 +      drawCentered("​READY!",​ 32, u8g2_font_ncenB14_tr);​ // afisam din nou starea de ready pt urmatoare miscare si 
 +      stareCurenta = Stare::​GATA;​ // actualizam si starea 
 +    } 
 +    break; 
 +  } 
 + 
 +  delay(5); ​                // pauza pt CPU 
 +
 +</code
 +==== Biblioteci externe utilizate ==== 
 + * ‘‘Wire.h’’ 
 + comunicare I²C cu accelerometrul şOLED 
 + * ‘‘SparkFun_LIS2DH12.h’’ 
 + driver pentru citirea acceleraţiilor de la senzorul ‘‘LIS2DH12’’ 
 + * ‘‘SPI.h’’ 
 + suport hardware ‘‘SPI’’ pentru modulul SD 
 + * ‘‘SD.h’’ 
 + acces la sistemul de fişiere ‘‘FAT’’ de pe cardul micro-SD 
 + * ‘‘TMRpcm.h’’ 
 + redare fişiere ‘‘WAV’’ mono prin ‘‘PWM’’ (Timer1) pe buzzerul pasiv 
 + * ‘‘U8g2lib.h’’ 
 + comandă şdesen pe ‘‘OLED SSD1306’’ 128×64 
 + 
 +==== Componente ale codului ==== 
 +Codul este împărţit în mai multe componente:​ 
 + * interfaţare cu hardware-ul,​ acoperind:​ 
 + iniţializare şi citire continuă a accelerometrului ‘‘LIS2DH12’’ 
 + * control ‘‘SPI/​SD’’ pentru verificarea şi deschiderea fişierului ‘‘DICE.WAV’’ 
 + * generare ‘‘PWM’’ audio pe pinul buzzer-ului 
 + * control ‘‘I²C’’ pentru desenul pe OLED 
 + * State machine, ce include: 
 + 
 + ‘‘GATA’’ – aşteaptă un shake şi afişează “READY!” 
 + ‘‘SHAKING’’ – redă sunetul şi afişează “Shake!” cât timp mişcarea continuă 
 + ‘‘REZULTAT’’ – generează două valori aleatorii, le afişează pe OLED, apoi revine la ‘‘GATA’’ 
 + 
 +        * funcţii auxiliare:​ 
 + 
 + ‘‘randomSeed(analogRead(A0))’’ pentru entropie la pornire 
 + ‘‘random(1,​7)’’ pentru fiecare zar 
 + ‘‘drawCentered(text,​ y, font)’’ – calculează lăţimea textului şi îl plasează centrat 
 + 
 +==== Fluxul aplicaţiei ==== 
 +-> La pornire, ‘‘setup()’’ iniţializează senzorul, OLED-ul, SD-ul, audio şi RNG-ul, apoi pe ecran apare “READY!”. 
 + 
 +-> În ‘‘loop()’’ se citesc acceleraţiile şi se calculează delta faţă ​de ultima citire. Dacă ‘‘delta > SHAKE_THRESHOLD’’,​ starea trece în ‘‘SHAKING’’. 
 + 
 +-> În ‘‘SHAKING’’ se porneşte ‘‘audio.play(“DICE.WAV”)’’ şi se afişează “Shake!”. La fiecare citire de mişcare, timer-ul este resetat. 
 + 
 +-> După ‘‘SHAKE_TIMEOUT’’ ms fără mişcare, ‘‘audio.stopPlayback()’’. Se generează două numere (1–6) şi se afişează cu font mare; starea devine ‘‘REZULTAT’’. 
 + 
 +-> După ‘‘RESULT_HOLD’’ ms, ecranul revine la “READY!” iar starea revine în ‘‘GATA’’,​ aşteptând un nou shake. 
 + 
 +==== Detalii de implementare ==== 
 +-> Praguri configurabile:​  
 +      * ‘‘SHAKE_THRESHOLD = 2000’’ – sensibilitate la mişcare  
 +      * ‘‘SHAKE_TIMEOUT = 300 ms’’ – interval fără mişcare înainte de oprire  
 +      * ‘‘RESULT_HOLD = 1500 ms’’ – cât timp rămâne afişat rezultatul 
 + 
 +-> Audio:  
 +      * ‘‘audio.setVolume(5)’’ – volum optim fără distorsiuni  
 +      * ‘‘audio.quality(1)’’ – oversampling 2× pentru claritate 
 + 
 +-> Desen pe OLED:  
 +      * re-desenările sunt minimizate – textul este redesenat doar la tranziţii de stare 
 + 
 +-> Random seed:  
 +      * folosirea unui pin analog “flotant” pentru a evita secvenţe pseudo-aleatoare repetitive 
 + 
 +==== Optimizări ==== 
 +      * Maşina ​de stări izolează logica de desen şi audio pe blocuri distincte, eliminând ‘‘redraw’’-uri inutile  
 +      * Actualizare ‘‘I²C’’ minimală – apeluri ‘‘drawCentered()’’ doar la tranziţii de stare  
 +      * Sincronizare audio–I²C – ‘‘audio.stopPlayback()’’ este apelat înainte de ‘‘drawCentered()’’ pentru a evita blocaje pe magistrala comună ​ 
 +      * Delay mic – ‘‘delay(5)’’ menţine CPU-ul liber pentru ISR-ul audio şi reduce consumul inutil 
 + 
 + 
 +===== Used labs ===== 
 + 
 +Lab0: GPIO 
 + * controlul pinilor digitali: 
 + * D9 – ieșire PWM către buzzer 
 + * D10 – Chip Select pentru modulul SD 
 + * LED-uri/Serial (opțional) pentru depanare 
 + 
 +Lab3: Timere & PWM 
 + * biblioteca TMRpcm folosește Timer1 în modul PWM pentru a genera semnalul audio necesar redării fișierului WAV pe buzzerul pasiv. 
 + 
 +Lab5: SPI 
 + * protocolul SPI asigură comunicația cu cardul micro-SD: 
 + * D11 → MOSI, D12 → MISO, D13 → SCK, D10 → CS 
 + * biblioteca SD.h gestionează sistemul de fișiere FAT și citirea fișierului DICE.WAV. 
 + 
 +Lab6: I²C (TWI) 
 + * magistrala I²C este partajată de: 
 + * LIS2DH12 – trimite datele brute de accelerație (detectarea shake-ului) 
 + * SSD1306 OLED – primește comenzile de desen (mesajele și rezultatul zarurilor) 
 + * linii comune: A4 → SDA, A5 → SCL. 
 + 
 +Lab1: USART  
 + * Serial.begin(9600) este prezent pentru diagnostic; când este decommentat,​ permite trimiterea de mesaje de debug în Serial Monitor. 
 + 
 + 
 +===== Rezultate Obţinute ===== 
 + 
 +[[https://​github.com/​teodora-voicu/​Digital_Dice|GitHub Repository]] 
 + 
 +[[https://​www.youtube.com/​watch?​v=ZkLngqv25lI|Demo Video]] 
 + 
 +{{:​pm:​prj2025:​vstoica:​IMG_1878.png?​300x|Shake}} 
 + 
 +{{:​pm:​prj2025:​vstoica:​IMG_1880.png?​300x|dice_res}} 
 +===== Concluzii ===== 
 + 
 +Acest proiect a reprezentat o ocazie excelentă de a vedea în practică conceptele teoretice şi de a le pune în aplicare pentru a crea ceva distractiv.
  
 ===== Bibliografie/​Resurse ===== ===== Bibliografie/​Resurse =====
  
-<​note>​ +[[https://​www.cirkitstudio.com/​|Cirkit Studio]] 
-Listă cu documente, datasheet-uri,​ resurse Internet folosite, eventual grupate pe **Resurse Software** şi **Resurse Hardware**+ 
-</note>+[[https://​www.arduino.cc/​|Pagina oficială Arduino]] 
 + 
 +[[https://​learn.adafruit.com/|Adafruit Learning System]]
  
 <​html><​a class="​media mediafile mf_pdf"​ href="?​do=export_pdf">​Export to PDF</​a></​html>​ <​html><​a class="​media mediafile mf_pdf"​ href="?​do=export_pdf">​Export to PDF</​a></​html>​
  
pm/prj2025/vstoica/teodora.voicu0210.1748540549.txt.gz · Last modified: 2025/05/29 20:42 by teodora.voicu0210
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0