This shows you the differences between two versions of the page.
pm:prj2025:ajipa:bianca.pintilie [2025/05/18 00:26] bianca.pintilie |
pm:prj2025:ajipa:bianca.pintilie [2025/05/27 05:06] (current) bianca.pintilie [Rezultate Obţinute] |
||
---|---|---|---|
Line 17: | Line 17: | ||
* Pentru **a începe** jocul, se va apăsa un **buton**, care va fi folosit și pentru a-l opri și reporni | * Pentru **a începe** jocul, se va apăsa un **buton**, care va fi folosit și pentru a-l opri și reporni | ||
* Pentru **a deplasa** pasărea, se folosește un **joystick**, iar poziția acestuia va fi transmisă către plăcuță, unde va fi interpretată cu ajutorul **convertorului analog-digital (ADC)** | * Pentru **a deplasa** pasărea, se folosește un **joystick**, iar poziția acestuia va fi transmisă către plăcuță, unde va fi interpretată cu ajutorul **convertorului analog-digital (ADC)** | ||
- | * Jocul permite vizualizarea **scorului** (de câte tuburi a trecut pasărea), dar și a **timpului** trecut în încercarea actuală **(timer)** | + | * Jocul permite vizualizarea **scorului** (de câte tuburi a trecut pasărea) |
* După ce jucătorul se lovește de un tub și astfel își încheie tura, acesta, dacă are un scor destul de mare, îl poate păstra salvându-l în **clasament**, introducându-și numele de la **tastatura laptop-ului (UART)** | * După ce jucătorul se lovește de un tub și astfel își încheie tura, acesta, dacă are un scor destul de mare, îl poate păstra salvându-l în **clasament**, introducându-și numele de la **tastatura laptop-ului (UART)** | ||
* Când jucătorul se află în **meniul principal**, pe lângă funcția de a începe jocul, poate vizualiza și clasamentul global prin apăsarea altui **buton** decât cel de start | * Când jucătorul se află în **meniul principal**, pe lângă funcția de a începe jocul, poate vizualiza și clasamentul global prin apăsarea altui **buton** decât cel de start | ||
Line 51: | Line 51: | ||
(Plăcuța, butoanele, rezistențele și LED-urile provin din același set și au același link) | (Plăcuța, butoanele, rezistențele și LED-urile provin din același set și au același link) | ||
- | **Schema electrica:** | + | **Schema electrică:** |
{{:pm:prj2025:ajipa:biancaaa_schemaelectrica.jpeg?700|}} | {{:pm:prj2025:ajipa:biancaaa_schemaelectrica.jpeg?700|}} | ||
Line 88: | Line 88: | ||
**Asamblarea întregului circuit + testare funcționare piese (LCD):** | **Asamblarea întregului circuit + testare funcționare piese (LCD):** | ||
+ | {{:pm:prj2025:ajipa:flappybird_pozacircuit.jpeg?400|}} | ||
===== Software Design ===== | ===== Software Design ===== | ||
- | Implementarea software a joculuise poate găsi în secțiunea de **Download**. | + | Implementarea software a jocului se poate găsi în secțiunea de **Download**. |
**Biblioteci folosite:** | **Biblioteci folosite:** | ||
* **"SPI.h", "Adafruit_GFX.h", "Adafruit_ILI9341.h"** - aceste biblioteci îmi oferă posibilitatea de a comunica cu LCD-ul, dar îmi și facilitează modalitățile prin care pot scrie cuvinte (meniul principal, meniul de highscore) sau să afișez jocul (pasărea, tuburile) așa cum îmi doresc | * **"SPI.h", "Adafruit_GFX.h", "Adafruit_ILI9341.h"** - aceste biblioteci îmi oferă posibilitatea de a comunica cu LCD-ul, dar îmi și facilitează modalitățile prin care pot scrie cuvinte (meniul principal, meniul de highscore) sau să afișez jocul (pasărea, tuburile) așa cum îmi doresc | ||
+ | |||
+ | * **Funcții folosite din bibliotecile menționate:** | ||
+ | * **fillScreen()**: umple ecranul în întregime cu o culoare specificată | ||
+ | * **fillRect()**: pornind de la o poziție specificată, umple un dreptunghi de lungime width și înălțime height cu o anumită culoare aleasă | ||
+ | * **setTextColor()**: setează culoarea textului | ||
+ | * **setTextSize()**: setează mărimea textului | ||
+ | * **setCursor()**: mută cursorul la o poziție specificată | ||
+ | * **print()/println()**: afișează textul pe LCD | ||
+ | |||
+ | **Meniul principal** | ||
+ | |||
+ | {{:pm:prj2025:ajipa:functie_main_menu.png?300|}} {{:pm:prj2025:ajipa:poza_meniuprincipal.jpg?200|}} | ||
+ | |||
+ | **Pasărea** | ||
+ | |||
+ | {{:pm:prj2025:ajipa:functie_desenare_pasare.png?400|}} {{:pm:prj2025:ajipa:poza_pasare.jpg?300|}} | ||
+ | |||
+ | |||
+ | **Elemente de noutate** | ||
+ | |||
+ | Față de versiunea originală a jocului, proiectul meu are câteva elemente în plus: | ||
+ | * **mișcarea păsării** - în jocul de bază, ca să ții pasărea într-o anumită poziție trebuia să apeși continuu pe ecran, aplicându-se legile gravitației, însă în versiunea mea, prin mișcarea joystick-ului în sus și în jos, nu doar că se duce în acea poziție, dar și rămâne acolo, fără a mai fi nevoie de interacțiunea jucătorului | ||
+ | |||
+ | * **oprirea/repornirea jocului** - în versiunea originală, odată ce ai început jocul nu te mai poți opri decât dacă pierzi, în schimb jocul meu oferă opțiunea de a-l pune pe pauză și de a-l reporni prin apăsarea unui simplu buton | ||
+ | |||
+ | * **LED-uri** - în implementarea proiectului am adăugat două LED-uri care îi arată jucătorului dacă este în timpul jocului (un LED verde se aprinde și stinge continuu) sau în afara lui (un LED roșu se aprinde și stinge continuu) | ||
+ | |||
+ | **Funcționalități laborator** | ||
+ | |||
+ | * **Întreruperi** | ||
+ | |||
+ | Am configurat butoanele conectate la pinul PD2, respectiv PD4, ca intrări și le-am activat rezistențele de pull-up. În cazul butonului de pe pinul PD2, i-am activat întreruperea externă care va avea loc pe falling edge pentru a gestiona schimbările de stare în joc: | ||
+ | * dacă game_state este 0, jocul începe, resetând scorul și fundalul | ||
+ | * dacă game_state este 4, trece la actualizarea tabelului de highscore | ||
+ | * în alte cazuri, schimbă între start și pauză | ||
+ | * de asemenea, resetează starea LED-urilor și valorile PWM asociate. | ||
+ | |||
+ | {{:pm:prj2025:ajipa:setup_butoane.png?600|}} | ||
+ | |||
+ | {{:pm:prj2025:ajipa:isr.png?500|}} | ||
+ | |||
+ | * **PWM** | ||
+ | |||
+ | Am configurat pinii PD5 și PD6 ca ieșiri PWM pentru controlul LED-urilor, utilizând modul Fast PWM cu un prescaler de 64. | ||
+ | |||
+ | Funcția **fade_leds**: | ||
+ | * controlează luminozitatea LED-urilor roșu (PD5) și verde (PD6) prin variarea graduală a valorii de umplere (duty cycle) între 0 și 255 | ||
+ | * cât timp jocul rulează (game_state = 1) LED-ul verde este activ, iar în restul de cazuri (în meniul principal, în meniul de highscore, când jocul este pe pauză, când jocul s-a încheiat) LED-ul roșu este activ | ||
+ | * creșterea și descreșterea valorilor din OCR0A și OCR0B simulează un efect de fade (aprindere/stingere graduală) | ||
+ | |||
+ | {{:pm:prj2025:ajipa:setup_leduri.png?700|}} | ||
+ | |||
+ | {{:pm:prj2025:ajipa:functie_leduri.png?300|}} | ||
+ | |||
+ | **Alte funcționalități:** | ||
+ | |||
+ | * **UART** | ||
+ | În cod, folosesc UART pentru a primi un nume de la utilizator printr-o conexiune serială. | ||
+ | |||
+ | Procesul se desfășoară astfel: | ||
+ | * atunci când jocul este în starea game_state = 5 (salvare highscore), programul intră într-o buclă în care așteaptă date de la tastatură prin portul serial | ||
+ | * după ce datele sunt disponibile, folosesc funcția Serial.readStringUntil() pentru a citi numele jucătorului introdus de la tastatura laptop-ului | ||
+ | * numele citit îl utilizez pentru a actualiza tabela de highscore (names[] și scores[]), apelând funcția update_highscore() | ||
+ | * funcția update_highscore() caută poziția unde trebuie adăugat noul scor, apoi mută celelalte scoruri pentru a-i face loc astfel încât să fie în ordine descrescătoare | ||
+ | |||
+ | {{:pm:prj2025:ajipa:uart.png?400|}} | ||
+ | |||
+ | {{:pm:prj2025:ajipa:update_highscore.png?500|}} | ||
+ | |||
+ | ***ADC** | ||
+ | |||
+ | Folosesc Convertorul Analog-Digital pentru a citi poziția joystick-ului, astfel modificând poziția păsării: | ||
+ | * am configurat pinul A1 ca intrare pentru a citi semnalul analogic de la joystick | ||
+ | * utilizez funcția analogRead(A1) pentru a converti tensiunea de pe pinul A1 într-o valoare între 0 și 1023 (această valoare reprezintă poziția joystick-ului pe axa Y) | ||
+ | * după câteva încercări, am constatat că atunci când dau în jos joystick-ul primesc valori apropiate de 0 (mai mici decât 10), iar când îl dau în sus primesc valori apropiate de 1023 (mai mari decât 1010) | ||
+ | * cu aceste valori am reușit să creez o mișcare decentă pentru pasăre, limitându-i înălțimea când aceasta ar fi putut ieși din ecran | ||
+ | |||
+ | {{:pm:prj2025:ajipa:input_joystick.png?400|}} | ||
+ | |||
+ | {{:pm:prj2025:ajipa:miscarea_pasarii.png?500|}} | ||
+ | |||
+ | * **Sunete** | ||
+ | |||
+ | Am folosit funcția tone() pentru a genera semnale audio atunci când am trecut cu bine de turnuri (am generat un semnal cu o frecvență ridicată timp de 100ms), dar și atunci când m-am lovit de acestea (am generat un semnal cu o frecvență mai scăzută timp de 100ms). | ||
+ | |||
+ | {{:pm:prj2025:ajipa:sunete.png?700|}} | ||
+ | |||
+ | |||
+ | * **SPI** | ||
+ | |||
+ | Am folosit în majoritatea codului protocolul SPI fiind necesar în afișarea întregului joc pe ecranul LCD. | ||
+ | |||
+ | De la afișarea meniurilor și până la desenarea pieselor jocului, anume pasărea și turnurile, toate acestea le-am realizat utilizând funcții legate de acest protocol. | ||
+ | |||
+ | Prin utilizarea variabilei **game_state**, în funcție de valoarea acesteia, pot să determin ce stare din joc să afișez în acel moment. | ||
+ | |||
+ | **Optimizări:** | ||
+ | * creare de funcții pentru evitarea codului repetitiv (show_main_menu(), show_highscore_menu(), etc.) | ||
+ | * micșorarea size-ului variabilelor (int8_t sau int16_t în loc de int pentru a micșora memoria totală a programului) | ||
+ | * logica PWM pentru controlul LED-urilor (în loc să folosesc cicluri software pentru controlul intensității, care ar fi blocat loop-ul, am utilizat hardware PWM: OCR0A, OCR0B) | ||
+ | * manipularea eficientă a întreruperilor (prin utilizarea întreruperii hardware de la butonul roșu am evitat blocarea buclei principale) | ||
===== Rezultate Obţinute ===== | ===== Rezultate Obţinute ===== | ||
+ | |||
+ | Link YouTube: [[https://youtube.com/shorts/IP-DghO4OIs?feature=share|FlappyBird]] | ||
+ | |||
===== Concluzii ===== | ===== Concluzii ===== | ||
+ | |||
+ | Proiectul a reprezentat o oportunitate excelentă de a îmbina cunoștințele teoretice și practice dobândite în timpul orelor de curs și laboratoarelor, punându-mi în valoare atât abilitățile software, cât și cele hardware. Realizarea efectivă a jocului a fost o experiență unică și captivantă, care mi-a permis să explorez interacțiunea dintre componentele fizice și software, ducând la un rezultat funcțional de care m-am putut bucura. | ||
+ | |||
===== Download ===== | ===== Download ===== | ||
Line 104: | Line 212: | ||
===== Bibliografie/Resurse ===== | ===== Bibliografie/Resurse ===== | ||
+ | |||
+ | [[https://www.optimusdigital.ro/en/?gad_source=1&gad_campaignid=21513560576&gbraid=0AAAAADv-p3DwhPcCOgY9guycqRYwBhMVR&gclid=Cj0KCQjwotDBBhCQARIsAG5pinPZmdbjlwyYPcRXZtRa83IJr0csoiy0RhoOkBFCOTyUIHmIppgzgfcaAkxXEALw_wcB|Optimus Digital]] | ||
+ | |||
+ | [[https://sigmanortec.ro/?gad_source=1&gad_campaignid=22305750370&gbraid=0AAAAAC3W72PxHH_lWjqfxfti6gpiQGRIW&gclid=Cj0KCQjwotDBBhCQARIsAG5pinM6W7pTRfSCa5EAEixfWoWsUH15yGOgEzek3ucAcyeKkMtxJ0lEHCIaAikGEALw_wcB|Sigmanortec]] | ||
+ | |||
+ | [[https://cleste.ro/|Clește]] | ||
+ | |||
+ | [[https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf|ATmega328P Datasheet]] |