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/12 11:02]
valentina.ceban created
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 și LCD ======+====== Simon Says - Joc de memorie cu LEDsLCD si Buzzer ​======
  
 ===== Introducere ===== ===== Introducere =====
  
-Proiectul reprezinta ​un joc de memorie de tip Simon Says implementat ​pe placa ATmega328P Xplained Mini. Jocul afiseaza ​o secventa ​de lumini prin 4 LED-uri colorate ​(rosu, verde, albastru, galben), iar jucatorul trebuie sa reproduca secventa apasand butoanele corespunzatoare. ​La fiecare ​runda reusita, secventa creste ​cu un pas, iar viteza de afisare creste progresiv, facand jocul din ce in ce mai dificil.+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 
 +secventa ​in ordinea corecta, ​apasand butoanele corespunzatoare. ​Cu fiecare ​nivel reusit, secventa 
 +creste ​in lungime, iar viteza de afisare creste progresiv.
  
-Un ecran LCD 16x2 afiseaza scorul curentmesaje ​de stare si cel mai bun scor (pastrat in EEPROM intre resetari). Un buzzer pasiv ofera feedback ​sonor, cu note diferite ​pentru fiecare ​culoare ​si un sunet de eroare ​la greseala.+Proiectul integreaza:​ 
 +  * **LCD 16x2 cu modul I2C** pentru afisarea scoruluinivelului, 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
  
-===== Descriere generala =====+**Schema bloc:**
  
-Jocul functioneaza dupa urmatoarea logica:+{{pm:prj2026:​alexandru.jipa2803:​schema_electrica_valentinaceban.png?​300}}
  
-  - LCD afiseaza "​Pregateste-te..."​ si un countdown 
-  - Microcontrolerul genereaza un numar random (1-4) si il adauga la secventa 
-  - LED-urile se aprind pe rand in ordinea secventei, cu pauze intre ele 
-  - Jucatorul apasa butoanele in aceeasi ordine 
-  - Daca inputul este corect → nivel urmator (secventa mai lunga, viteza mai mare) 
-  - Daca inputul este gresit → buzzer suna, scorul e afisat, jocul se reseteaza 
  
-**Schema bloc:**+===== Descriere Generala ===== 
 + 
 +==== Logica jocului ==== 
 + 
 +  - La pornire, LCD afiseaza animatie de intro cu scroll si cel mai bun scor din EEPROM 
 +  - 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 
 +  - Microcontrolerul genereaza o secventa aleatoare si o afiseaza prin LED-uri cu sunet specific fiecarei culori 
 +  - Jucatorul reproduce secventa; pe LCD se afiseaza countdown-ul de timp ramas 
 +  - La nivel corectanimatie inima care bate, scor actualizat, dificultate crescuta 
 +  - Daca scorul depaseste recordul: celebrare imediata cu trofeu pe LCD si melodie, jocul **continua** 
 +  - La raspuns gresit sau timeout: skull animat, Game Over, scor afisat, selectie dificultate din nou 
 +  - Recordul persista in EEPROM intre resetari si deconectari 
 + 
 +==== Masina de stari ==== 
 + 
 +<​code>​ 
 +IDLE (ecran intro + animatie) 
 +    │ apasare orice buton 
 +    ▼ 
 +SELECT_DIFFICULTY (Easy / Medium / Hard) 
 +    │ apasare B1 / B2 / B3 
 +    ▼ 
 +SHOW_SEQUENCE (afisare secventa LED-uri cu sunet) 
 +    │ secventa terminata 
 +    ▼ 
 +WAIT_INPUT (asteapta input jucator, countdown vizibil pe LCD) 
 +    ├─ corect, scor > record → RECORD (trofeu + melodie) → SHOW_SEQUENCE 
 +    ├─ corect, scor <= record → CORRECT (animatie inima) → SHOW_SEQUENCE 
 +    └─ gresit / timeout → GAME_OVER (skull animat + salvare scor) → SELECT_DIFFICULTY 
 +</​code>​
  
-[De adaugat] 
  
 ===== Hardware Design ===== ===== Hardware Design =====
  
-**Lista de piese:**+==== Lista de componente ====
  
-^ Componenta ^ Model ^ Rol ^ +^ Componenta ^ Model/Valoare ^ Cantitate ​^ Rol in proiect ​
-| Microcontroller | ATmega328P Xplained Mini | Unitate centrala de control | +| Microcontroller | ATmega328P Xplained Mini | 1 | Unitate centrala de control | 
-| Display LCD | 16x2 | Afisare scor si mesaje | +| Display LCD | 16x2 cu modul I2C (PCF8574) | 1 | Afisare scor, nivel, countdown, animatii ​
-| Potentiometru | 10kΩ | Reglaj contrast LCD +| LED rosu | 5mm, 2V, 20mA | 1 | Culoarea 1 a jocului ​
-| LED rosu | 5mm + rezistor 220Ω | Culoarea 1 | +| LED verde | 5mm, 2.1V, 20mA | 1 | Culoarea 2 a jocului ​
-| LED verde | 5mm + rezistor 220Ω | Culoarea 2 | +| LED galben ​| 5mm, 2V, 20mA | 1 | Culoarea 3 a jocului ​
-| LED albastru ​| 5mm + rezistor 220Ω | Culoarea 3 | +| LED albastru ​| 5mm, 3.2V, 20mA | 1 | Culoarea 4 a jocului | 
-| LED galben ​| 5mm + rezistor ​220Ω | Culoarea ​4 | +| Rezistenta | 220Ω | 4 | Protectie LED-uri (limiteaza curentul la ~15mA) ​
-| Butoane tactile | x4 | Input jucator | +| Butoane tactile | 6x6mm, 4 pini | 4 | Input jucator | 
-| Buzzer ​pasiv | 5V | Feedback sonor | +| Buzzer ​activ | 5V | 1 | Feedback sonor, note diferite per culoare ​
-| Breadboard ​+ fire — | Prototipare |+| Breadboard | 830 puncte | 1 | Prototipare ​circuit | 
 +| Fire jumper | M-M | ~25 | Conexiuni intre componente ​|
  
-**Conexiuni principale:**+==== Pinii folositi ==== 
 + 
 +^ Componenta ^ Pin ATmega ^ Pin Arduino ^ Motivatie alegere ^ 
 +| 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 | 
 +| Buton rosu | PD6 | D6 | GPIO cu pull-up intern disponibil | 
 +| Buton verde | PD7 | D7 | 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 | 
 +| Buzzer activ | PB2 | D10 | Compatibil cu functia tone() | 
 +| LCD SDA | PC4 | A4 | Pin hardware TWI/I2C al ATmega328P | 
 +| LCD SCL | PC5 | A5 | Pin hardware TWI/I2C al ATmega328P | 
 + 
 +**Motivatia alegerii pinilor:** 
 +  * **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 prin protocol hardware, nu software bitbang 
 +  * **Butoanele folosesc INPUT_PULLUP intern** — elimina necesitatea rezistentelor externe de pull-down, simplificand circuitul si reducand numarul de componente 
 + 
 +==== Schema electrica ==== 
 + 
 +**LED-uri (x4, conectare identica):​** 
 +<​code>​ 
 +Pin GPIO (D2-D5) ── Rezistenta 220Ω ── Anod LED (+, picior lung) 
 +                                        Catod LED (-, picior scurt) ── GND 
 +</​code>​ 
 + 
 +**Butoane (x4, cu pull-up intern, fara rezistente externe):​** 
 +<​code>​ 
 +Pin GPIO (D6-D9) ── Pin 1 buton (o latura) 
 +GND ─────────────── Pin 2 buton (latura opusa, de cealalta parte a canalului central) 
 +Pull-up intern activat prin INPUT_PULLUP → citeste LOW la apasare, HIGH in repaus 
 +</​code>​ 
 + 
 +**Buzzer activ:** 
 +<​code>​ 
 +D10 ── Pin + buzzer (marcat cu +) 
 +GND ── Pin - buzzer (marcat cu -) 
 +</​code>​ 
 + 
 +**LCD I2C:** 
 +<​code>​ 
 +A4 (SDA/PC4) ── SDA modul I2C 
 +A5 (SCL/PC5) ── SCL modul I2C 
 +5V ──────────── VCC modul I2C 
 +GND ─────────── GND modul I2C 
 +Potentiometru albastru pe modul = reglaj contrast 
 +</​code>​ 
 + 
 +{{pm:​prj2026:​alexandru.jipa2803:​5211176995717324748.jpg?​300}}
  
-  * LCD RS → D2 (PD2) 
-  * LCD EN → D3 (PD3) 
-  * LCD D4-D7 → D4-D7 (PD4-PD7) 
-  * LCD VDD → 5V, VSS → GND, RW → GND 
-  * LCD V0 → wiper potentiometru (intre 5V si GND) 
-  * LED rosu → D8 (PB0) prin rezistor 220Ω 
-  * LED verde → D9 (PB1) prin rezistor 220Ω 
-  * LED albastru → D10 (PB2) prin rezistor 220Ω 
-  * LED galben → D11 (PB3) prin rezistor 220Ω 
-  * Buton 1 → A0 (PC0) → GND (pull-up intern activat) 
-  * Buton 2 → A1 (PC1) → GND (pull-up intern activat) 
-  * Buton 3 → A2 (PC2) → GND (pull-up intern activat) 
-  * Buton 4 → A3 (PC3) → GND (pull-up intern activat) 
-  * Buzzer + → D12 (PB4), Buzzer - → GND 
  
 ===== Software Design ===== ===== Software Design =====
  
-**Mediu de dezvoltare:** PlatformIO + framework Arduino (MiniCore)+==== Mediu de dezvoltare ​====
  
-^ Periferic ^ Utilizare ^ +  * **Arduino IDE** cu framework Arduino 
-| Timer1 | Generare timinguri non-blocante pentru secventa | +  * Limbaj: **C++** cu API Arduino 
-| GPIO output | Control LED-uri | +  * Upload prin USB (mEDBG integrat pe placa Xplained Mini
-| GPIO input (pull-up| Citire butoane | +  * **Serial Monitor** la 9600 baud pentru debugging si logging
-| PWM (tone()) | Generare note buzzer pasiv | +
-| EEPROM | Stocare high score intre resetari |+
  
-**Structura software:**+==== Biblioteci folosite ====
  
-  * Masina de stari: IDLE → SHOW_SEQUENCE → WAIT_INPUT → GAME_OVER +^ Biblioteca ^ Sursa ^ Motivatie ^ 
-  * Secventa stocata intr-un array, lungime crescatoare la fiecare nivel +| Wire.h | Built-in Arduino | Comunicatie I2C hardware cu LCD | 
-  * Viteza ​de afisare scade cu fiecare nivel (dificultate adaptiva) +| LiquidCrystal_I2C.h | Frank de Brabander | Abstractizare comenzi LCDinitializarecursorprintcaractere custom | 
-  * Debounce software pentru butoane +| EEPROM.h | Built-in Arduino | Acces la memoria ​EEPROM ​pentru persistenta high score |
-  * Note diferite per culoareDOREMISOL (frecvente fixe) +
-  * High score salvat ​in EEPROM, persistent intre resetari+
  
-===== Rezultate Obtinute =====+==== Elementul de noutate ​====
  
-(se completeaza dupa finalizarea implementarii)+  * **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 
 +  * **Dificultate adaptiva bidiectionala**:​ viteza creste la succese ​(−20ms/​nivel) si scade la greseli (+30ms), cu limite 150ms–600ms,​ mentinand jocul accesibil indiferent de nivel 
 +  * **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 LCD cu caractere custom**: 8 simboluri definite ca matrici 5x8 pixeli (inima, skull, trofeu, note muzicale, sageata, progress barfolosite 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 jucatorului,​ LCD afiseaza secundele ramase, actualizate in timp real
  
-===== Concluzii =====+==== Functionalitati din laborator utilizate ​====
  
-(se completeaza dupa finalizarea implementarii)+^ Functionalitate ^ Utilizare in proiect ^ 
 +| 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 D6-D9 | 
 +| Timer (tone()) | Generare frecvente audio pentru buzzer — intern foloseste Timer2 | 
 +| TWI/I2C (Wire.h) | Comunicatie cu modulul LCD prin 2 fire (SDA/SCL
 +| EEPROM | Stocare persistenta a high score-ului la adresa 0 cu EEPROM.put/​get | 
 +| Debounce software | Eliminarea bouncing-ului mecanic: asteptare release + delay 50ms |
  
-===== Download =====+==== Scheletul proiectului si portiuni de cod relevante ​====
  
-(link catre codul sursa - GitHub)+=== Selectare dificultate ===
  
-===== Jurnal =====+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:
  
-  * **12.05.2026** — Milestone 1: Documentatie ​initiala, schema de conectare+^ 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 |
  
-===== Bibliografie/Resurse =====+<code cpp> 
 +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
  
-**Hardware:​**+  // Aprinde LED-urile ca indicatori vizuali 
 +  for (int i = 0; i < 3; i++) digitalWrite(ledPins[i],​ HIGH);
  
-  ​[[https://​ww1.microchip.com/​downloads/​en/​DeviceDoc/​Atmel-42743-ATmega328P_Datasheet.pdf|Datasheet ATmega328P]] +  ​while (!ales) { 
-  ​* [[https://​www.microchip.com/​en-us/​development-tool/​atmega328p-xmini|ATmega328P Xplained Mini User Guide]]+    if (digitalRead(btnPins[0]) == LOW) { viteza=600; timpReplica=12000;​ ales=true; } 
 +    if (digitalRead(btnPins[1]) == LOW) { viteza=500; timpReplica=10000;​ ales=true; } 
 +    if (digitalRead(btnPins[2]) == LOW) { viteza=300; timpReplica=7000; ​ ales=true; } 
 +  ​
 +
 +</code>
  
-**Software & Tutoriale:​**+=== Dificultate adaptiva bidiectionala ===
  
-  * [[https://ocw.cs.pub.ro/courses/pm/tutorial/proiect|Ghid proiect PM]] +Dupa fiecare nivel, viteza si timpul de replica se ajusteaza automat. 
-  * [[https://​docs.arduino.cc/​libraries/​liquidcrystal/​|Arduino ​LiquidCrystal ​Library]]+Limitele explicite previn ca jocul sa devina imposibil sau prea lent: 
 + 
 +<code cpp> 
 +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>​ 
 + 
 +==== Validare functionare ==== 
 + 
 +Validarea s-a realizat in mai multe etape: 
 + 
 +**1. Testare LED-uri individual:​** 
 +<code cpp> 
 +// Aprinde fiecare LED pe rand cu delay, verifica orientarea si conexiunile 
 +void loop() { 
 +  for (int i = 0; i < 4; i++) { 
 +    digitalWrite(ledPins[i],​ HIGH); delay(500);​ 
 +    digitalWrite(ledPins[i],​ LOW);  delay(200);​ 
 +  } 
 +
 +</​code>​ 
 + 
 +**2. Testare butoane cu Serial Monitor:​** 
 +<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>​ 
 +=== SIMON SAYS === 
 +Dificultate:​ MEDIUM 
 +------------------ 
 +NIVEL 3 | Viteza: 460ms 
 +Secventa: 
 +  1. Rosu 
 +  2. Verde 
 +  3. Albastru 
 +Repeta secventa! 
 +  Apasat: Rosu -> Corect! (1/3) 
 +  Apasat: Verde -> Corect! (2/3) 
 +  Apasat: Albastru -> Corect! (3/3) 
 +Nivel completat! Scor: 60 
 +*** NOU HIGH SCORE! *** 
 +Viteza noua: 440 | Timp replica: 9400 
 +</​code>​ 
 + 
 +**4. Testare EEPROM:** 
 +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 ==== 
 + 
 +  * **Debounce software**: asteptare release + delay 50ms, eliminand bouncing-ul mecanic fara timere hardware 
 +  * **randomSeed(analogRead(A0))**:​ pinul A0 neconectat citeste zgomot analogic, asigurand secvente cu adevarat aleatorii la fiecare pornire 
 +  * **INPUT_PULLUP**:​ elimina rezistentele externe de pull-down pentru butoane, simplificand circuitul 
 +  * **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 ===== 
 + 
 +Proiectul functioneaza conform specificatiilor extinse: 
 +  * Selectarea dificultaii este functionala cu feedback LED si LCD, reapare dupa fiecare Game Over 
 +  * Secventele sunt generate aleator si afisate corect pe LED-uri cu sunet specific per culoare 
 +  * Butoanele sunt detectate corect cu debounce, fara false pozitive sau omisiuni 
 +  * LCD afiseaza nivel, scor, countdown timp ramas si animatii in timp real 
 +  * 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 
 + 
 + 
 +===== Concluzii ===== 
 + 
 +Proiectul Simon Says a fost implementat cu succes pe placa ATmega328P Xplained Mini, 
 +depasind specificatiile de baza prin adaugarea mai multor functionalitati care imbunatatesc 
 +experienta de joc si complexitatea tehnica. 
 + 
 +Principalele provocari intampinate:​ 
 +  * Compatibilitatea librariei LiquidCrystal_I2C cu toolchain-ul MiniCore — rezolvata prin implementare manuala Wire.h 
 +  * Conflicte de pini intre RX/TX si LED-uri — rezolvate prin relocarea LED-urilor pe PD4-PD7 
 +  * 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 
 + 
 + 
 +===== Bibliografie ===== 
 + 
 +  ​* [[https://ww1.microchip.com/​downloads/​en/​DeviceDoc/​Atmel-42743-ATmega328P_Datasheet.pdf|Datasheet ATmega328P - Microchip]] 
 +  * [[https://www.microchip.com/en-us/development-tool/​atmega328p-xmini|ATmega328P Xplained Mini User Guide]] 
 +  * [[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://​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]]
pm/prj2026/alexandru.jipa2803/valentina.ceban.1778572947.txt.gz · Last modified: 2026/05/12 11:02 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