This shows you the differences between two versions of the page.
pm:prj2025:vradulescu:razvan.miclius [2025/05/18 21:31] razvan.miclius [Hardware Design] |
pm:prj2025:vradulescu:razvan.miclius [2025/05/28 14:18] (current) razvan.miclius [Hardware Design] |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Nokia Snake ====== | ====== Nokia Snake ====== | ||
- | Toată pagina este WIP. | + | |
===== Introducere ===== | ===== Introducere ===== | ||
Jocul //[[https://en.wikipedia.org/wiki/Snake_(video_game_genre)|Snake]]// reprezintă un joc clasic, despre care o mare parte din lume a auzit/cu care a interacționat. Astfel, consider că o reproducere a sa este un pas bun în dezvoltarea abilităților mele de a folosi un microproceesor, având un punct de referință pentru produsul final. | Jocul //[[https://en.wikipedia.org/wiki/Snake_(video_game_genre)|Snake]]// reprezintă un joc clasic, despre care o mare parte din lume a auzit/cu care a interacționat. Astfel, consider că o reproducere a sa este un pas bun în dezvoltarea abilităților mele de a folosi un microproceesor, având un punct de referință pentru produsul final. | ||
Line 13: | Line 13: | ||
Acestuia îi sunt transmise informații despre starea joystick-ului prin cele două porturi analog A0 și A1, precum și starea butonului prin intermediul pinului 8. | Acestuia îi sunt transmise informații despre starea joystick-ului prin cele două porturi analog A0 și A1, precum și starea butonului prin intermediul pinului 8. | ||
- | {{pm:prj2025:vradulescu:razvan.png?700}} | + | {{pm:prj2025:vradulescu:circuit_razvan_final.png?700}} |
Din punct de vedere software, este folosită biblioteca [[https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library|Adafruit PCD 8544]] împreună cu un singur fișier de tip main. | Din punct de vedere software, este folosită biblioteca [[https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library|Adafruit PCD 8544]] împreună cu un singur fișier de tip main. | ||
===== Hardware Design ===== | ===== Hardware Design ===== | ||
- | || | ||
^ Piesă ^ # ^ Use case ^ Datasheet ^ | ^ Piesă ^ # ^ Use case ^ Datasheet ^ | ||
| Arduino Uno | 1 | Microcontroller | https://docs.arduino.cc/resources/datasheets/A000066-datasheet.pdf | | | Arduino Uno | 1 | Microcontroller | https://docs.arduino.cc/resources/datasheets/A000066-datasheet.pdf | | ||
| PCD8544 | 1 | Display | https://cdn.sparkfun.com/assets/b/1/b/e/f/Nokia5110.pdf | | | PCD8544 | 1 | Display | https://cdn.sparkfun.com/assets/b/1/b/e/f/Nokia5110.pdf | | ||
- | | Buzzer Activ | 1 | Sunet | N/A | | + | | Buzzer Pasiv | 2 | Sunet | N/A | |
| Rezistențe 10k ohmi | 5 | Conectare ecran LCD | N/A | | | Rezistențe 10k ohmi | 5 | Conectare ecran LCD | N/A | | ||
+ | | Potentiometru 10k | 1 | Alimentare backlight | N/A | | ||
| Joystick | 1 | Input | N/A | | | Joystick | 1 | Input | N/A | | ||
+ | | Breadboard | 1 | Conexiuni | N/A | | ||
+ | | Fire | Multe | Conexiuni | N/A | | ||
Ecranul funcționează la 3.3V, așadar rezistențele sunt necesare pentru a asigura funcționarea în parametrii. | Ecranul funcționează la 3.3V, așadar rezistențele sunt necesare pentru a asigura funcționarea în parametrii. | ||
- | {{pm:prj2025:vradulescu:razvan_live.png?700}} | + | {{pm:prj2025:vradulescu:razvan_live.jpg?700}} |
Mai multe poze cu cablajul pot fi văzute [[https://imgur.com/a/V6Ov2xe | aici]]. | Mai multe poze cu cablajul pot fi văzute [[https://imgur.com/a/V6Ov2xe | aici]]. | ||
Line 34: | Line 36: | ||
- | <note tip> | + | Fișierul principal a fost scris în Arduino IDE pentru a putea fi pus pe placă facil, în timp ce restul codului a fost scris în mod spartan în nvim. |
- | Descrierea codului aplicaţiei (firmware): | + | |
- | * mediu de dezvoltare (if any) (e.g. AVR Studio, CodeVisionAVR) | + | |
- | * librării şi surse 3rd-party (e.g. Procyon AVRlib) | + | |
- | * algoritmi şi structuri pe care plănuiţi să le implementaţi | + | |
- | * (etapa 3) surse şi funcţii implementate | + | |
- | </note> | + | |
- | ===== Rezultate Obţinute ===== | + | Biblioteca folosită, precizată și mai sus, a fost biblioteca [[https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library|Adafruit PCD 8544]] pentru a controla ecranul. |
- | <note tip> | + | Din punct de vedere al logicii programului, acesta urmează o logică de FSM, cu următoarele stări: |
- | Care au fost rezultatele obţinute în urma realizării proiectului vostru. | + | |
- | </note> | + | |
- | ===== Concluzii ===== | + | <code c> |
+ | enum STATE { | ||
+ | STATE_MAIN_MENU, | ||
+ | STATE_SETTINGS, | ||
+ | STATE_GAME, | ||
+ | STATE_PAUSE_MENU, | ||
+ | STATE_GAME_OVER | ||
+ | }; | ||
+ | </code> | ||
- | ===== Download ===== | + | Astfel, fiecare stare a mașinii reprezintă un "ecran": jocul principal, meniul principal ș.a.m.d. |
+ | Asta a facilitat implementarea diferitelor ecrane într-un mod modular. | ||
- | <note warning> | + | Implementarea efectivă are următoarea structură: |
- | O arhivă (sau mai multe dacă este cazul) cu fişierele obţinute în urma realizării proiectului: surse, scheme, etc. Un fişier README, un ChangeLog, un script de compilare şi copiere automată pe uC crează întotdeauna o impresie bună ;-). | + | |
- | 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**. | + | <code> |
- | </note> | + | main.ino <- Conține logica de FSM: un switch/case |
+ | common.h <- Conține variabilele partajate, pinii, stările, prototipurile ecranelor | ||
+ | utils.h <- Citirea JoyStick-ului | ||
+ | utils.cpp <- idem | ||
+ | main_menu.cpp <- Ecranul principal | ||
+ | settings.cpp <- Ecranul setări | ||
+ | game.cpp <- Ecranul joc | ||
+ | pause_menu.cpp <- Ecranul pauză | ||
+ | game_over.cpp <- Ecranul game over | ||
+ | </code> | ||
- | ===== Jurnal ===== | + | Pentru a întelege mai bine implementarea, o să detaliez funcționalitatea meniului de pauză. |
+ | |||
+ | Preambul: | ||
+ | <code c> | ||
+ | #include "common.h" | ||
+ | #include "utils.h" | ||
+ | |||
+ | const int pauseMenuItems = 3; // Numărul de opțiuni | ||
+ | int pauseMenuIndex = 0; // Opțiunea selectată | ||
+ | STATE pause_options[3] = {STATE_GAME, STATE_GAME, STATE_MAIN_MENU}; | ||
+ | unsigned long pauseLastMoveTime = 0; // Timestamp pentru debounce | ||
+ | const unsigned long pauseMoveDebounce = 200; | ||
+ | |||
+ | extern bool gameInitialized; | ||
+ | |||
+ | </code> | ||
+ | |||
+ | "Driver" code: | ||
+ | <code c> | ||
+ | void handlePauseMenu() { | ||
+ | // Input handling | ||
+ | uint8_t dir = readJoystick(); | ||
+ | if (millis() - pauseLastMoveTime > pauseMoveDebounce) { // Debounce | ||
+ | if (dir & UP) { | ||
+ | pauseMenuIndex = (pauseMenuIndex - 1 + pauseMenuItems) % pauseMenuItems; | ||
+ | pauseLastMoveTime = millis(); | ||
+ | tone(PIN_BUZZER, 440, 200); | ||
+ | } else if (dir & DOWN) { | ||
+ | pauseMenuIndex = (pauseMenuIndex + 1) % pauseMenuItems; | ||
+ | pauseLastMoveTime = millis(); | ||
+ | tone(PIN_BUZZER, 440, 200); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // Afișare opțiuni | ||
+ | display.clearDisplay(); | ||
+ | display.setTextSize(1); | ||
+ | display.setTextColor(BLACK); | ||
+ | display.setCursor(0, 0); | ||
+ | display.println("Paused"); | ||
+ | |||
+ | display.setCursor(10, 15); | ||
+ | display.print((pauseMenuIndex == 0) ? "> " : " "); // Decorăm opțiunea selectată. | ||
+ | display.println("Resume"); | ||
+ | |||
+ | display.setCursor(10, 25); | ||
+ | display.print((pauseMenuIndex == 1) ? "> " : " "); | ||
+ | display.println("Restart"); | ||
+ | |||
+ | display.setCursor(10, 35); | ||
+ | display.print((pauseMenuIndex == 2) ? "> " : " "); | ||
+ | display.println("Main Menu"); | ||
+ | |||
+ | display.display(); | ||
+ | |||
+ | if (pressJoystick()) { | ||
+ | delay(150); | ||
+ | tone(PIN_BUZZER, 220, 200); | ||
+ | if (pauseMenuIndex >= 1) { | ||
+ | gameInitialized = false; | ||
+ | } | ||
+ | state = pause_options[pauseMenuIndex]; | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Alte detalii care îmi plac sunt în utils și encodarea pentru direcții: | ||
+ | |||
+ | <code c > | ||
+ | |||
+ | #define UP 1 | ||
+ | #define DOWN 2 | ||
+ | #define LEFT 4 | ||
+ | #define RIGHT 8 | ||
+ | |||
+ | uint8_t readJoystick() { | ||
+ | uint8_t dir = 0; | ||
+ | int y = analogRead(PIN_STICK_Y); | ||
+ | int x = analogRead(PIN_STICK_X); | ||
+ | if (y > THRESHOLD_TOP ) dir |= DOWN; | ||
+ | else if (y < THRESHOLD_BOT) dir |= UP; | ||
+ | if (x > THRESHOLD_TOP) dir |= RIGHT; | ||
+ | else if (x < THRESHOLD_BOT) dir |= LEFT; | ||
+ | return dir; | ||
+ | } | ||
+ | </code> | ||
+ | Acest mecanism îmi permite să verific simultan atât pentru direcții verticale cât și pentru direcții orizontale. | ||
+ | ===== Rezultate Obţinute ===== | ||
+ | |||
+ | * Implementarea elementelor de grafică: Lucrul pe ecranul de Nokia a fost o experiență plăcută, asemănătoare cu lucrul folosind biblioteca ncurses din C, din care m-am inspirat pentru ecrane. | ||
+ | * Implementarea unei melodii, chiar simplificată. | ||
+ | * Implementarea unui mecanism de meniu funcțional. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | https://files.catbox.moe/ni9nyv.mp4 <- Jocul în acțiune | ||
+ | ===== Download ===== | ||
- | <note tip> | + | [[https://github.com/razvang0307/proiect-snake-pm/tree/main | Link proiect GitHub]] |
- | Puteți avea și o secțiune de jurnal în care să poată urmări asistentul de proiect progresul proiectului. | + | |
- | </note> | + | |
+ | Conectare cablaj -> Upload main.ino :) | ||
===== Bibliografie/Resurse ===== | ===== Bibliografie/Resurse ===== | ||
- | <note> | + | Hardware: |
- | Listă cu documente, datasheet-uri, resurse Internet folosite, eventual grupate pe **Resurse Software** şi **Resurse Hardware**. | + | * https://cdn.sparkfun.com/assets/b/1/b/e/f/Nokia5110.pdf |
- | </note> | + | * https://docs.arduino.cc/resources/datasheets/A000066-datasheet.pdf |
+ | Software | ||
+ | * https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library | ||
<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> | ||