Differences

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

Link to this comparison view

pm:prj2026:alexandru.jipa2803:valentina.ceban [2026/05/24 18:38]
valentina.ceban
pm:prj2026:alexandru.jipa2803:valentina.ceban [2026/05/24 20:26] (current)
valentina.ceban [Concluzii]
Line 1: Line 1:
-====== Simon Says - Joc de memorie cu LEDs, LCD si buzzer ​======+====== Simon Says - Joc de memorie cu LEDs, LCD si Buzzer ​======
  
 ===== Introducere ===== ===== Introducere =====
  
-Proiectul reprezinta o implementare a jocului clasic **Simon Says** pe placa **ATmega328P Xplained Mini**.+Proiectul reprezinta o implementare ​extinsa ​a jocului clasic **Simon Says** pe placa **ATmega328P Xplained Mini**.
 Jocul afiseaza secvente de lumini prin 4 LED-uri colorate, iar jucatorul trebuie sa reproduca Jocul afiseaza secvente de lumini prin 4 LED-uri colorate, iar jucatorul trebuie sa reproduca
 secventa in ordinea corecta, apasand butoanele corespunzatoare. Cu fiecare nivel reusit, secventa secventa in ordinea corecta, apasand butoanele corespunzatoare. Cu fiecare nivel reusit, secventa
Line 9: Line 9:
  
 Proiectul integreaza: Proiectul integreaza:
-  * **LCD 16x2 cu modul I2C** pentru afisarea scorului, nivelului, ​vitezei ​si mesajelor de stare+  * **LCD 16x2 cu modul I2C** pentru afisarea scorului, nivelului, ​countdown-ului ​si mesajelor de stare 
 +  * **Animatii LCD** cu 8 caractere custom (inima, skull, trofeu, note muzicale, progress bar) 
 +  * **Selectare dificultate** la start — Easy / Medium / Hard, cu viteze si timpi diferiti 
 +  * **Dificultate adaptiva bidiectionala** — viteza creste la succese si scade la greseli 
 +  * **Countdown vizibil** pe LCD in timpul in care jucatorul replica secventa 
 +  * **Feedback sonor** prin buzzer activ, cu note diferite per culoare 
 +  * **Melodie "We Are the Champions"​** la baterea recordului, cu LED-uri sincronizate 
 +  * **Celebrare record in timp real** — fara sa intrerupa jocul
   * **EEPROM persistent** pentru salvarea celui mai bun scor intre resetari   * **EEPROM persistent** pentru salvarea celui mai bun scor intre resetari
-  * **Dificultate adaptiva** — viteza creste la succese si scade la greseli 
-  * **Feedback sonor** prin buzzer pasiv, cu note diferite per culoare 
-  * **Animatii** la pornire, victorie si game over 
  
 **Schema bloc:** **Schema bloc:**
  
 +{{pm:​prj2026:​alexandru.jipa2803:​schema_electrica_valentinaceban.png?​300}}
  
  
Line 23: Line 28:
 ==== Logica jocului ==== ==== Logica jocului ====
  
-  - La pornire, LCD afiseaza ​"SIMON SAYS" ​si cel mai bun scor din EEPROM +  - La pornire, LCD afiseaza ​animatie de intro cu scroll ​si cel mai bun scor din EEPROM 
-  - LED-urile executa o animatie de bun-venit (se aprind pe rand)+  - LED-urile executa o animatie de bun-venit (wave in ambele directii) 
 +  - Jucatorul selecteaza dificultatea:​ **Easy** (B1), **Medium** (B2), **Hard** (B3)
   - La apasarea oricarui buton, jocul incepe   - La apasarea oricarui buton, jocul incepe
-  - Microcontrolerul genereaza ​un element aleator (0-3) si il adauga la secventa +  - Microcontrolerul genereaza ​o secventa aleatoare ​si o afiseaza prin LED-uri cu sunet specific fiecarei culori 
-  - LED-urile se aprind **pe rand**, in ordinea secventei, ​cu sunet specific fiecarei culori +  - Jucatorul reproduce secventa; pe LCD se afiseaza countdown-ul de timp ramas 
-  - Jucatorul reproduce secventa ​apasand butoanele in ordinea corecta +  - La nivel corect: animatie ​inima care batescor actualizatdificultate ​crescuta 
-  - La raspuns ​corect: animatie ​de victorienivel urmatorviteza ​crescuta +  - Daca scorul depaseste recordul: celebrare imediata cu trofeu pe LCD si melodie, jocul **continua** 
-  - La raspuns gresit: ​sunet de eroaretoate LED-urile clipescdificultatea scade usor (dificultate ​adaptiva) +  - La raspuns gresit ​sau timeoutskull animatGame Over, scor afisatselectie ​dificultate ​din nou 
-  - Scorul cel mai bun este salvat ​in EEPROM ​si persista ​intre resetari+  - Recordul persista ​in EEPROM intre resetari ​si deconectari
  
 ==== Masina de stari ==== ==== Masina de stari ====
  
 <​code>​ <​code>​
-IDLE (ecran ​start+IDLE (ecran ​intro + animatie
-    │ apasare buton+    │ apasare ​orice buton
     ▼     ▼
-SHOW_SEQUENCE (afisare secventa LED-uri)+SELECT_DIFFICULTY (Easy / Medium / Hard) 
 +    │ apasare B1 / B2 / B3 
 +    ▼ 
 +SHOW_SEQUENCE (afisare secventa LED-uri ​cu sunet)
     │ secventa terminata     │ secventa terminata
     ▼     ▼
-WAIT_INPUT (asteapta input jucator) +WAIT_INPUT (asteapta input jucator, countdown vizibil pe LCD
-    ├─ corect → CORRECT (animatie ​+ nivel urmator) → SHOW_SEQUENCE +    ├─ corect, scor > record → RECORD (trofeu + melodie) → SHOW_SEQUENCE 
-    └─ gresit → GAME_OVER (animatie ​+ salvare scor) → IDLE+    ├─ corect, scor <= record ​→ CORRECT (animatie ​inima) → SHOW_SEQUENCE 
 +    └─ gresit ​/ timeout ​→ GAME_OVER (skull animat ​+ salvare scor) → SELECT_DIFFICULTY
 </​code>​ </​code>​
 +
  
 ===== Hardware Design ===== ===== Hardware Design =====
Line 53: Line 64:
 ^ Componenta ^ Model/​Valoare ^ Cantitate ^ Rol in proiect ^ ^ Componenta ^ Model/​Valoare ^ Cantitate ^ Rol in proiect ^
 | Microcontroller | ATmega328P Xplained Mini | 1 | Unitate centrala de control | | Microcontroller | ATmega328P Xplained Mini | 1 | Unitate centrala de control |
-| Display LCD | 16x2 cu modul I2C (PCF8574) | 1 | Afisare scor, nivel, ​mesaje ​|+| Display LCD | 16x2 cu modul I2C (PCF8574) | 1 | Afisare scor, nivel, ​countdown, animatii ​|
 | LED rosu | 5mm, 2V, 20mA | 1 | Culoarea 1 a jocului | | LED rosu | 5mm, 2V, 20mA | 1 | Culoarea 1 a jocului |
-| LED albastru ​| 5mm, 3.2V, 20mA | 1 | Culoarea 2 a jocului | +| LED verde | 5mm, 2.1V, 20mA | 1 | Culoarea 2 a jocului | 
-| LED verde | 5mm, 2.1V, 20mA | 1 | Culoarea 3 a jocului | +| LED galben ​| 5mm, 2V, 20mA | 1 | Culoarea 3 a jocului | 
-| LED galben ​| 5mm, 2V, 20mA | 1 | Culoarea 4 a jocului | +| LED albastru ​| 5mm, 3.2V, 20mA | 1 | Culoarea 4 a jocului | 
-| Rezistenta | 220Ω | 4 | Protectie LED-uri | +| Rezistenta | 220Ω | 4 | Protectie LED-uri ​(limiteaza curentul la ~15mA) ​
-| Butoane tactile | 6x6mm | 4 | Input jucator | +| Butoane tactile | 6x6mm, 4 pini | 4 | Input jucator | 
-| Buzzer ​pasiv | 5V | 1 | Feedback sonor | +| Buzzer ​activ | 5V | 1 | Feedback sonor, note diferite per culoare ​
-| Breadboard | 830 puncte | 1 | Prototipare | +| Breadboard | 830 puncte | 1 | Prototipare ​circuit ​
-| Fire jumper | M-M | ~25 | Conexiuni |+| Fire jumper | M-M | ~25 | Conexiuni ​intre componente ​|
  
 ==== Pinii folositi ==== ==== Pinii folositi ====
  
 ^ Componenta ^ Pin ATmega ^ Pin Arduino ^ Motivatie alegere ^ ^ Componenta ^ Pin ATmega ^ Pin Arduino ^ Motivatie alegere ^
-| LED rosu | PD4 | D4 | GPIO simplu, fara functii speciale |+| LED rosu | PD2 | D2 | GPIO simplu, fara functii speciale | 
 +| LED verde | PD3 | D3 | GPIO simplu, fara functii speciale | 
 +| LED galben ​| PD4 | D4 | GPIO simplu, fara functii speciale |
 | LED albastru | PD5 | D5 | GPIO simplu, fara functii speciale | | LED albastru | PD5 | D5 | GPIO simplu, fara functii speciale |
-LED verde | PD6 | D6 | GPIO simplu, fara functii speciale ​+Buton rosu | PD6 | D6 | GPIO cu pull-up intern disponibil ​
-LED galben ​| PD7 | D7 | GPIO simplu, fara functii speciale ​+Buton verde | PD7 | D7 | GPIO cu pull-up intern disponibil ​
-| Buton rosu | PB0 | D8 | GPIO cu pull-up intern disponibil |+| Buton galben ​| PB0 | D8 | GPIO cu pull-up intern disponibil |
 | Buton albastru | PB1 | D9 | GPIO cu pull-up intern disponibil | | Buton albastru | PB1 | D9 | GPIO cu pull-up intern disponibil |
-Buton verde | PB2 | D10 | GPIO cu pull-up intern disponibil | +Buzzer activ | PB2 | D10 | Compatibil cu functia tone() | 
-| Buton galben | PB3 | D11 | GPIO cu pull-up intern disponibil | +| LCD SDA | PC4 | A4 | Pin hardware TWI/I2C al ATmega328P ​
-| Buzzer | PB4 | D12 | Compatibil cu functia tone() | +| LCD SCL | PC5 | A5 | Pin hardware TWI/I2C al ATmega328P ​|
-| LCD SDA | PC4 | A4 | Pin hardware TWI/I2C al ATmega ​+
-| LCD SCL | PC5 | A5 | Pin hardware TWI/I2C al ATmega ​|+
  
 **Motivatia alegerii pinilor:** **Motivatia alegerii pinilor:**
-  * PD0/PD1 au fost evitati — sunt RX/TX, folositi de comunicatia seriala USB cu mEDBG +  ​* **PD0/PD1 au fost evitati** — sunt RX/TX, folositi de comunicatia seriala USB cu mEDBG; conectarea LED-urilor pe acesti pini blocheaza upload-ul de cod 
-  * PC4/PC5 sunt pinii hardware TWI (I2C) ai ATmega328P, oferind comunicatie stabila cu LCD-ul +  ​* **PC4/PC5** sunt pinii hardware TWI (I2C) ai ATmega328P, oferind comunicatie stabila cu LCD-ul ​prin protocol hardware, nu software bitbang 
-  * PB4 (D12) este compatibil cu timer-ul folosit ​intern ​de functia tone() pentru generarea de frecvente audio +  * **Butoanele folosesc INPUT_PULLUP ​intern** — elimina necesitatea rezistentelor externe de pull-down, simplificand circuitul si reducand numarul de componente
-  ​LED-urile pe PD4-PD7 permit setarea simultana prin operatii pe registrul PORTD+
  
 ==== Schema electrica ==== ==== Schema electrica ====
Line 89: Line 99:
 **LED-uri (x4, conectare identica):​** **LED-uri (x4, conectare identica):​**
 <​code>​ <​code>​
-Pin GPIO (PD4-PD7) ──────── Anod LED (+, picior lung) +Pin GPIO (D2-D5) ── ​Rezistenta 220Ω ── Anod LED (+, picior lung) 
-                             ​Catod LED (-, picior scurt) ​── Rezistenta 220Ω ── GND+                                        Catod LED (-, picior scurt) ── GND
 </​code>​ </​code>​
  
-**Butoane (x4, cu pull-up intern):**+**Butoane (x4, cu pull-up intern, fara rezistente externe):**
 <​code>​ <​code>​
-Pin GPIO (PB0-PB3──────── Pin 1 buton +Pin GPIO (D6-D9) ── Pin 1 buton (o latura) 
-GND ─────────────────────── Pin 2 buton (opus+GND ─────────────── Pin 2 buton (latura opusa, de cealalta parte a canalului central
-Pull-up intern activat ​in cod prin INPUT_PULLUP +Pull-up intern activat prin INPUT_PULLUP ​→ citeste LOW la apasare, HIGH in repaus
-Butonul ​citeste LOW cand e apasat, HIGH cand e liber+
 </​code>​ </​code>​
  
-**Buzzer ​pasiv:**+**Buzzer ​activ:**
 <​code>​ <​code>​
-PB4 (D12) ──────────────── Pin + buzzer +D10 ── Pin + buzzer ​(marcat cu +) 
-GND ─────────────────────── Pin - buzzer+GND ── Pin - buzzer ​(marcat cu -)
 </​code>​ </​code>​
  
 **LCD I2C:** **LCD I2C:**
 <​code>​ <​code>​
-PC4 (A4/SDA) ───────────── SDA modul I2C +A4 (SDA/PC4) ── SDA modul I2C 
-PC5 (A5/SCL───────────── SCL modul I2C +A5 (SCL/PC5) ── SCL modul I2C 
-5V ──────────────────────── VCC modul I2C +5V ──────────── VCC modul I2C 
-GND ─────────────────────── GND modul I2C+GND ─────────── GND modul I2C
 Potentiometru albastru pe modul = reglaj contrast Potentiometru albastru pe modul = reglaj contrast
 </​code>​ </​code>​
  
-**Alimentare breadboard:** +{{pm:prj2026:​alexandru.jipa2803:​5211176995717324748.jpg?​300}}
-<​code>​ +
-5V placa  ──── linia rosie (+) breadboard +
-GND placa ──── linia albastra (-) breadboard +
-</​code>​+
  
-{{pm:​prj2026:​alexandru.jipa2803:​5211176995717324748.jpg?​300}} 
  
 ===== Software Design ===== ===== Software Design =====
Line 128: Line 132:
 ==== Mediu de dezvoltare ==== ==== Mediu de dezvoltare ====
  
-  * **PlatformIO** + **framework Arduino** (MiniCore pentru ATmega328P) +  * **Arduino IDE** cu framework Arduino
-  * **Arduino IDE** (alternativ,​ pentru upload rapid)+
   * Limbaj: **C++** cu API Arduino   * Limbaj: **C++** cu API Arduino
 +  * Upload prin USB (mEDBG integrat pe placa Xplained Mini)
 +  * **Serial Monitor** la 9600 baud pentru debugging si logging
  
 ==== Biblioteci folosite ==== ==== Biblioteci folosite ====
  
 ^ Biblioteca ^ Sursa ^ Motivatie ^ ^ Biblioteca ^ Sursa ^ Motivatie ^
-| Wire.h | Built-in Arduino | Comunicatie I2C hardware cu LCD — nu necesita instalare externa ​+| Wire.h | Built-in Arduino | Comunicatie I2C hardware cu LCD 
-| EEPROM.h | Built-in Arduino | Acces la memoria EEPROM ​a ATmega328P ​pentru persistenta high score | +| LiquidCrystal_I2C.h | Frank de Brabander | Abstractizare comenzi LCD: initializare,​ cursor, print, caractere custom ​
-| Arduino.h | Built-in | API de baza: pinMode, digitalWrite,​ tone, delay | +| EEPROM.h | Built-in Arduino | Acces la memoria EEPROM pentru persistenta high score |
- +
-**Motivatia alegerii Wire.h in loc de LiquidCrystal_I2C:​** +
-Libraria LiquidCrystal_I2C a prezentat probleme de compatibilitate cu toolchain-ul MiniCore +
-pentru ATmega328P Xplained Mini. Solutia adoptata a fost implementarea directa a protocolului +
-I2C pentru LCD folosind Wire.h (built-in), scriind manual functiile de initializare,​ trimitere +
-nibble/​byte,​ setare cursor si print. Aceasta abordare ofera control complet si elimina +
-dependentele externe.+
  
 ==== Elementul de noutate ==== ==== Elementul de noutate ====
  
-  * **Dificultate adaptiva bidiectionala**:​ viteza creste la succese si scade la greseli, mentinand jocul accesibil indiferent de nivelul jucatorului +  ​* **Selectare dificultate la start**: jucatorul alege Easy / Medium / Hard inainte de fiecare joc, cu viteze si timpi de replica diferiti; selectia reapare dupa fiecare Game Over 
-  * **Sistem de bonus**: 3 raspunsuri consecutive corecte declanseaza o crestere suplimentara a vitezei +  ​* **Dificultate adaptiva bidiectionala**:​ viteza creste la succese ​(−20ms/​nivel) ​si scade la greseli ​(+30ms), cu limite 150ms–600ms, mentinand jocul accesibil indiferent de nivel 
-  * **Persistenta high score in EEPROM**: scorul maxim supravietuieste resetarilor si deconectarii de la alimentare +  * **Celebrare record in timp real**: daca scorul depaseste recordul in timpul jocului (nu doar la Game Over), se afiseaza trofeu pe LCD, se canta melodia si se salveaza in EEPROM — jocul **continua** fara intrerupere 
-  * **Animatii procedurale**: secventele de LED-uri la pornirevictorie si eroare sunt generate programaticfara timere hardware blocante+  * **Animatii LCD cu caractere custom**: 8 simboluri definite ca matrici 5x8 pixeli (inima, skull, trofeu, note muzicale, sageata, progress bar) folosite in animatii procedurale 
 +  * **Melodie la record**: primele 15 note din "We Are the Champions"​ cantate pe buzzer, cu LED-urile clipind sincronizat cu fiecare nota 
 +  * **Countdown vizibil**: in timpul replicii jucatoruluiLCD afiseaza secundele ramaseactualizate in timp real
  
 ==== Functionalitati din laborator utilizate ==== ==== Functionalitati din laborator utilizate ====
  
 ^ Functionalitate ^ Utilizare in proiect ^ ^ Functionalitate ^ Utilizare in proiect ^
-| GPIO output | Control LED-uri: PORTD pentru afisarea secventei | +| GPIO output | Control LED-uri ​pe D2-D5 pentru afisarea secventei ​si animatii ​
-| GPIO input cu pull-up | Citire butoane fara rezistente externe: INPUT_PULLUP pe PB0-PB3 +| GPIO input cu pull-up | Citire butoane fara rezistente externe: INPUT_PULLUP pe D6-D9 
-| Timer (tone()) | Generare frecvente audio pentru buzzer ​pasiv — intern foloseste Timer2 |+| Timer (tone()) | Generare frecvente audio pentru buzzer — intern foloseste Timer2 |
 | TWI/I2C (Wire.h) | Comunicatie cu modulul LCD prin 2 fire (SDA/SCL) | | TWI/I2C (Wire.h) | Comunicatie cu modulul LCD prin 2 fire (SDA/SCL) |
-| EEPROM | Stocare persistenta a high score-ului la adresa 0 | +| EEPROM | Stocare persistenta a high score-ului la adresa 0 cu EEPROM.put/​get ​
-Intreruperi soft (debounce) ​| Eliminarea ​zgomotului ​mecanic ​al butoanelor prin delay 50ms + asteptare release |+Debounce software ​| Eliminarea ​bouncing-ului ​mecanicasteptare release ​+ delay 50ms |
  
-==== Scheletul proiectului ====+==== Scheletul proiectului ​si portiuni de cod relevante ​==== 
 + 
 +=== Selectare dificultate === 
 + 
 +La pornire si dupa fiecare Game Over, jucatorul selecteaza dificultatea prin primele 3 butoane. 
 +LED-urile se aprind ca indicatori vizuali in timp ce asteapta selectia: 
 + 
 +^ Dificultate ^ Buton ^ Viteza initiala ^ Timp replica ^ 
 +| Easy | B1 (rosu) | 600ms per LED | 12 secunde | 
 +| Medium | B2 (verde) | 500ms per LED | 10 secunde | 
 +| Hard | B3 (galben) | 300ms per LED | 7 secunde |
  
 <code cpp> <code cpp>
-// Masina de stari implementata prin apeluri recursive de functii:+void selecteazaDificultate() { 
 +  lcd.write(CHAR_NOTE); ​   lcd.print("​E ​ "​); ​  // Easy 
 +  lcd.write(CHAR_SAGEATA);​ lcd.print("​M ​ "​); ​  // Medium 
 +  lcd.write(CHAR_SKULL); ​  ​lcd.print("​H"​); ​    // Hard
  
-asteaptaStart() +  // Aprinde LED-urile ca indicatori vizuali 
-  ​└─> animatieStart(afisare LCD "SIMON SAYS Best Score"​ +  ​for (int i = 0; i < 3; i++) digitalWrite(ledPins[i], HIGH);
-  └─> asteapta apasare buton → incepeJoc()+
  
-incepeJoc() +  while (!ales{ 
-  ​└─>​ reseteaza lungime=1, viteza=600ms, scor=0 +    if (digitalRead(btnPins[0]) ​== LOW) { viteza=600; timpReplica=12000; ales=true; } 
-  ​└─>​ genereazaSecventa() → arataSiAsteapta()+    ​if ​(digitalRead(btnPins[1]== LOW) { viteza=500; timpReplica=10000;​ ales=true; } 
 +    if (digitalRead(btnPins[2]== LOW) { viteza=300; timpReplica=7000; ​ ales=true; } 
 +  } 
 +
 +</​code>​
  
-arataSiAsteapta() +=== Dificultate ​adaptiva ​bidiectionala ===
-  └─> afiseaza nivel + viteza pe LCD +
-  └─> aprinde LED-urile pe rand cu sunet (secventa) +
-  └─> pentru fiecare element din secventa: +
-        asteaptaButon() +
-          └─> corect: feedback LED+sunet, continua +
-          └─> gresit: gameOver() +
-  └─> dupa secventa completa: animatieVictorie() +
-  └─> dificultate ​adaptiva: scade viteza (creste dificultatea) +
-  └─> bonus daca 3 consecutive corecte +
-  └─> genereazaSecventa() + arataSiAsteapta() (nivel urmator)+
  
-gameOver() +Dupa fiecare nivel, viteza si timpul de replica se ajusteaza automat. 
-  ​└─dificultate adaptivacreste viteza ​(scade dificultatea+Limitele explicite previn ca jocul sa devina imposibil sau prea lent: 
-  ​└─verifica si salveaza high score in EEPROM + 
-  ​└─afisare ​LCD "Game Over + Scor Best+<code cpp> 
-  ​└─asteaptaStart()+void ajusteazaDificultate(bool corect{ 
 +  ​if (corect) { 
 +    viteza ​     = max(150, viteza - 20);       // LED-urile se aprind mai repede 
 +    timpReplica = max(5000, timpReplica - 300); // mai putin timp de replica 
 +  } else { 
 +    viteza ​     = min(600, viteza + 30);        // LED-urile se aprind mai lent 
 +    timpReplica = min(12000, timpReplica + 500);// mai mult timp de replica 
 +  } 
 +
 +</code> 
 + 
 +=== Countdown vizibil pe LCD === 
 + 
 +In bucla de asteptare a butoanelor, LCD-ul este actualizat continuu cu secundele ramase. 
 +Functia returneaza −1 la timeout, tratata ca greseala: 
 + 
 +<code cpp> 
 +int waitForButton() { 
 +  ​unsigned long start = millis(); 
 +  while (millis() - start < (unsigned long)timpReplica) { 
 +    int secRamase = (timpReplica - (millis() - start)) / 1000; 
 +    lcd.setCursor(9,​ 1); 
 +    lcd.print("​T:"​);​ lcd.print(secRamase);​ lcd.print("​s ​ "); 
 + 
 +    for (int i = 0; i < 4; i++) { 
 +      if (digitalRead(btnPins[i]) == LOW) { 
 +        lightUp(i, 300); 
 +        while (digitalRead(btnPins[i]) == LOW); // asteapta release 
 +        delay(50); ​                              // debounce 
 +        return i; 
 +      } 
 +    } 
 +  } 
 +  return -1; // timeout 
 +
 +</code> 
 + 
 +=== Animatii LCD cu caractere custom === 
 + 
 +LCD-ul 16x2 suporta pana la 8 caractere custom definite ca matrici de pixeli 5x8. 
 +Proiectul defineste 8 simboluri inregistrate la initializare cu ''​lcd.createChar()'':​ 
 + 
 +^ Index ^ Simbol ^ Utilizat ​in 
 +| 0 | Inima plina | Nivel corect, record | 
 +| 1 | Inima goala | Animatie batai inima | 
 +| 2 | Skull | Game Over | 
 +| 3 | Note muzicale | Intro, selectie Easy | 
 +| 4 | Sageata | Nivel curent, selectie Medium | 
 +| 5 | Trofeu | Record, castig | 
 +| 6 | Progres plin | Progress bar | 
 +| 7 | Progres gol | Progress bar | 
 + 
 +Exemplu definitie si animatie inima care bate: 
 + 
 +<code cpp> 
 +byte inima[] ​     = {0b00000,​0b01010,​0b11111,​0b11111,​0b11111,​0b01110,​0b00100,​0b00000};​ 
 +byte inimaGoala[] = {0b00000,​0b01010,​0b10101,​0b10001,​0b10001,​0b01010,​0b00100,​0b00000};​ 
 + 
 +void animatieInima() { 
 +  ​for (int i = 0; i < 3; i++) {   // 3 batai 
 +    lcd.setCursor(15,​ 0); 
 +    lcd.write(CHAR_INIMA); ​         // inima plina 
 +    tone(buzzer,​ 800); delay(80); noTone(buzzer);​ 
 +    delay(100);​ 
 +    lcd.setCursor(15,​ 0); 
 +    lcd.write(CHAR_INIMA_GOALA); ​   // inima goala 
 +    delay(200);​ 
 +  } 
 +  lcd.setCursor(15,​ 0); 
 +  lcd.write(CHAR_INIMA);​ 
 +
 +</code> 
 + 
 +Progress bar pe randul 2 al LCD-ului, care arata progresul prin cele 20 de nivele: 
 + 
 +<code cpp> 
 +void afiseazaProgressBar() { 
 +  lcd.setCursor(0,​ 1); 
 +  int pasi = map(level, 1, MAXLEVEL, 0, 16); // 1-20 nivele → 0-16 caractere 
 +  for (int i = 0; i < 16; i++) { 
 +    if (i < pasi) lcd.write(CHAR_PROG_FULL);​ 
 +    else          lcd.write(CHAR_PROG_EMPTY);​ 
 +  } 
 +
 +</​code>​ 
 + 
 +=== Celebrare record in timp real === 
 + 
 +Spre deosebire de implementarile clasice (care verifica recordul doar la Game Over), 
 +aceasta implementare verifica dupa fiecare nivel corect. La depasirea recordului,​ 
 +se afiseaza trofeu, se salveaza in EEPROM si se canta melodia — apoi jocul **continua**:​ 
 + 
 +<code cpp> 
 +// In loop(), dupa completarea unui nivel: 
 +scor += level * 10; 
 +ajusteazaDificultate(true);​ 
 + 
 +if (scor > highScore) { 
 +  celebreazaRecord(); ​  // trofeu ​melodie + salveaza EEPROM 
 +} else { 
 +  animatieInima(); ​     // animatie normala nivel corect 
 +
 + 
 +level++; 
 +if (level > MAXLEVEL) win(); 
 +else playSequence(); ​   // jocul continua normal 
 + 
 +void celebreazaRecord() { 
 +  lcd.write(CHAR_TROPHY);​ lcd.print(" ​NOU RECORD! "); lcd.write(CHAR_TROPHY);​ 
 +  ​highScore = scor; 
 +  EEPROM.put(0,​ highScore); ​ // persistenta intre resetari 
 +  cantaMelodie(); ​            // We Are the Champions 
 +
 +</code> 
 + 
 +=== Melodie la record === 
 + 
 +La baterea recordului, buzzerul canta primele 15 note din "We Are the Champions"​. 
 +LED-urile clipesc sincronizat cu melodia ​(cate un LED diferit per nota, in cicluri de 4)
 + 
 +<code cpp> 
 +const int melodieNote[] ​  = { 392,​392,​349,​392,​0,​523,​494,​440,​392,​ 
 +                               ​659,​659,​659,​587,​523,​392 }; 
 +const int melodieDurata[] = { 200,​200,​200,​400,​200,​400,​200,​200,​600,​ 
 +                               ​200,​200,​200,​200,​200,​600 }; 
 + 
 +void cantaMelodie() { 
 +  for (int i = 0; i < melodieLen; i++) { 
 +    if (melodieNote[i] == 0) { noTone(buzzer);​ }   // pauza intre note 
 +    else { 
 +      tone(buzzer,​ melodieNote[i]);​ 
 +      digitalWrite(ledPins[i % 4], HIGH); ​          // LED sincronizat cu nota 
 +    } 
 +    delay(melodieDurata[i]);​ 
 +    noTone(buzzer);​ 
 +    digitalWrite(ledPins[i % 4], LOW); 
 +    delay(30);​ 
 +  } 
 +
 +</​code>​ 
 + 
 +=== Persistenta EEPROM === 
 + 
 +Scorul maxim este salvat la adresa 0 din EEPROM. Validarea la citire protejeaza 
 +impotriva datelor corupte sau a primei porniri (cand EEPROM contine valori nedefinite):​ 
 + 
 +<code cpp> 
 +// La pornire — citire cu validare: 
 +EEPROM.get(0,​ highScore);​ 
 +if (highScore < 0 || highScore > 9999) highScore = 0; 
 + 
 +// La baterea recordului — scriere imediata: 
 +EEPROM.put(0,​ highScore);​ 
 +</​code>​ 
 + 
 +=== Debounce butoane === 
 + 
 +Butoanele mecanice genereaza bouncing la apasare si eliberare. 
 +Debounce-ul software combina doua tehnici complementare:​ 
 + 
 +<code cpp> 
 +if (digitalRead(btnPins[i]) == LOW) { 
 +  lightUp(i, 300);                          // feedback vizual imediat 
 +  while (digitalRead(btnPins[i]) == LOW);   // asteapta release complet 
 +  delay(50); ​                               // elimina bouncing la eliberare 
 +  return i; 
 +}
 </​code>​ </​code>​
  
Line 201: Line 373:
 **1. Testare LED-uri individual:​** **1. Testare LED-uri individual:​**
 <code cpp> <code cpp>
-// Cod de test: fiecare ​buton aprinde ​LED-ul corespunzator +// Aprinde ​fiecare LED pe rand cu delay, verifica orientarea si conexiunile 
-if (digitalRead(butoane[i]) == LOW) digitalWrite(leduri[i], HIGH);+void loop() { 
 +  for (int i = 0; i < 4; i++) { 
 +    digitalWrite(ledPins[i], HIGH); delay(500)
 +    ​digitalWrite(ledPins[i], LOW);  ​delay(200);​ 
 +  } 
 +}
 </​code>​ </​code>​
  
-**2. Validare prin Serial Monitor:​** +**2. Testare butoane cu Serial Monitor:​** 
-La fiecare eveniment ​(nivel, apasare buton, corect/​gresit) ​se afiseaza mesaje ​pe Serial Monitor ​la 9600 baud:+<code cpp> 
 +// Afiseaza butonul apasat — a identificat problema de inversare GND/​semnal 
 +void loop() { 
 +  for (int i = 0; i < 4; i++) { 
 +    if (digitalRead(btnPins[i]) == LOW) { 
 +      Serial.print("​Buton "); Serial.print(i+1);​ Serial.println("​ apasat!"​);​ 
 +      delay(300);​ 
 +    } 
 +  } 
 +
 +</​code>​ 
 + 
 +**3. Validare prin Serial Monitor ​in joc:** 
 +La fiecare eveniment se afiseaza mesaje la 9600 baud:
 <​code>​ <​code>​
-=== Nivel: 3 | Viteza: ​540ms === +=== SIMON SAYS === 
-  ​-> ROSU +DificultateMEDIUM 
-  ​-> VERDE +------------------ 
-  ​-> ALBASTRU +NIVEL 3 | Viteza: ​460ms 
-Randul tau+Secventa: 
-  Apasat: ​ROSU -> Corect! +  ​1. Rosu 
-  Apasat: ​VERDE -> Corect! +  ​2. Verde 
-  Apasat: ​ALBASTRU ​-> Corect! +  ​3. Albastru 
-BONUS VITEZA3 consecutive corecte!+Repeta secventa
 +  Apasat: ​Rosu -> Corect! ​(1/3) 
 +  Apasat: ​Verde -> Corect! ​(2/3) 
 +  Apasat: ​Albastru ​-> Corect! ​(3/3) 
 +Nivel completatScor: 60 
 +*** NOU HIGH SCORE*** 
 +Viteza noua: 440 | Timp replica: 9400
 </​code>​ </​code>​
  
-**3. Testare EEPROM:** +**4. Testare EEPROM:** 
-Dupa game over cu scor nou, s-a verificat ca la resetare hardware scorul persista (afisat pe LCD la pornire).+Dupa game over cu scor nou, s-a verificat ca la resetare hardware scorul persista 
 +(citit cu EEPROM.get la pornire si afisat pe LCD).
  
 ==== Optimizari realizate ==== ==== Optimizari realizate ====
  
-  * **Debounce software**: ​dupa detectarea apasarii, se asteapta ​50ms si release-ul butonului, eliminand bouncing-ul mecanic +  * **Debounce software**: ​asteptare release + delay 50ms, eliminand bouncing-ul mecanic ​fara timere hardware 
-  * **randomSeed(analogRead(A3))**: pinul A3 (neconectatciteste zgomot analogic, asigurand secvente cu adevarat aleatorii la fiecare pornire +  * **randomSeed(analogRead(A0))**: pinul A0 neconectat citeste zgomot analogic, asigurand secvente cu adevarat aleatorii la fiecare pornire 
-  * **Implementare I2C manuala**: elimina ​overhead-ul unei librarii ​externe, ​reducand dimensiunea codului compilat +  * **INPUT_PULLUP**: elimina ​rezistentele ​externe ​de pull-down pentru butoanesimplificand circuitul 
-  * **Dificultate adaptiva bidiectionala**: mentine jocul engageable indiferent de skill-ul jucatorului+  * **Validare EEPROM la citire**: protejeaza impotriva valorilor corupte sau nedefinite la prima pornire 
 +  * **Celebrare record inline**: verificarea si salvarea recordului se face dupa fiecare nivel, nu doar la Game Over, fara a intrerupe fluxul jocului 
  
 ===== Rezultate Obtinute ===== ===== Rezultate Obtinute =====
  
-Proiectul functioneaza conform specificatiilor:​ +Proiectul functioneaza conform specificatiilor ​extinse: 
-  * Secventele sunt generate aleator si afisate corect pe LED-uri cu sunet +  * Selectarea dificultaii este functionala cu feedback LED si LCD, reapare dupa fiecare Game Over 
-  * Butoanele sunt detectate corect cu debounce +  * Secventele sunt generate aleator si afisate corect pe LED-uri cu sunet specific per culoare 
-  * LCD-ul afiseaza nivel, ​viteza curenta si scor in timp real +  * Butoanele sunt detectate corect cu debounce, fara false pozitive sau omisiuni 
-  * High score-ul persista ​in EEPROM intre resetari +  * LCD afiseaza nivel, scor, countdown timp ramas si animatii ​in timp real 
-  * Dificultatea ​se ajusteaza dinamic in functie ​de performanta jucatorului+  * Dificultatea se ajusteaza automat dupa fiecare nivel in ambele directii 
 +  * Recordul se salveaza ​in EEPROM ​si persista ​intre resetari ​hardware si deconectari 
 +  * Celebrarea recordului ​se declanseaza imediat, fara sa intrerupa jocul 
 +  * Melodia "We Are the Champions"​ se canta corect cu LED-urile sincronizate pe note 
 +  * Progress bar-ul reflecta fidel progresul prin cele 20 de nivele
  
  
Line 242: Line 445:
  
 Proiectul Simon Says a fost implementat cu succes pe placa ATmega328P Xplained Mini, Proiectul Simon Says a fost implementat cu succes pe placa ATmega328P Xplained Mini,
-demonstrand utilizarea GPIO, I2C, EEPROM ​si timer-e in cadrul framework-ului Arduino.+depasind specificatiile de baza prin adaugarea mai multor functionalitati care imbunatatesc 
 +experienta de joc si complexitatea tehnica.
  
 Principalele provocari intampinate:​ Principalele provocari intampinate:​
Line 248: Line 452:
   * Conflicte de pini intre RX/TX si LED-uri — rezolvate prin relocarea LED-urilor pe PD4-PD7   * Conflicte de pini intre RX/TX si LED-uri — rezolvate prin relocarea LED-urilor pe PD4-PD7
   * Calibrarea debounce-ului butoanelor pentru raspuns fluid   * Calibrarea debounce-ului butoanelor pentru raspuns fluid
 +  * High score blocat — valoare corupta in EEPROM dintr-o sesiune anterioara; rezolvat prin validare la citire si reset manual
 +
 +Lectii invatate:
 +  * Documentarea pinilor inainte de cablare evita conflicte greu de depanat
 +  * Testarea incrementala (LED, buton, LCD, buzzer separat) economiseste timp considerabil
 +  * INPUT_PULLUP simplifica semnificativ circuitul butoanelor
 +  * Verificarea recordului in timp real (nu doar la Game Over) ofera o experienta de joc mai fluida
  
  
Line 256: Line 467:
   * [[https://​docs.arduino.cc/​learn/​built-in-libraries/​eeprom/​|Arduino EEPROM Library Documentation]]   * [[https://​docs.arduino.cc/​learn/​built-in-libraries/​eeprom/​|Arduino EEPROM Library Documentation]]
   * [[https://​docs.arduino.cc/​learn/​communication/​wire/​|Arduino Wire Library (I2C)]]   * [[https://​docs.arduino.cc/​learn/​communication/​wire/​|Arduino Wire Library (I2C)]]
 +  * [[https://​github.com/​johnrickman/​LiquidCrystal_I2C|LiquidCrystal_I2C Library - Frank de Brabander]]
   * [[https://​ocw.cs.pub.ro/​courses/​pm/​tutorial/​proiect|Ghid proiect PM - OCW UPB]]   * [[https://​ocw.cs.pub.ro/​courses/​pm/​tutorial/​proiect|Ghid proiect PM - OCW UPB]]
pm/prj2026/alexandru.jipa2803/valentina.ceban.1779637113.txt.gz · Last modified: 2026/05/24 18:38 by valentina.ceban
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