Autor: STAMATIE Mihai-Robert, 333CA
Proiectul reprezinta o implementare hardware a jocului clasic Snake pe o matrice de LED-uri 8×8, avand ca microcontroller o placa Arduino Leonardo (ATmega32U4 @ 16 MHz). Jucatorul controleaza sarpele cu ajutorul unui joystick analogic, iar butonul integrat al joystick-ului (SW — apasarea in jos a manetei) permite resetarea jocului in orice moment.
Firmware-ul este scris in C bare-metal (avr-libc + avr-gcc), fara framework-ul Arduino, cu acces direct la registrele microcontrollerului — abordare care permite control fin asupra timpilor si folosirea eficienta a resurselor disponibile pe ATmega32U4.
Logica jocului implementeaza:
Motivatia: mi-am dorit un proiect care sa combine partea de I/O analogic (joystick, citire ADC) cu o componenta de afisare controlata printr-un protocol serial (SPI software, prin MAX7219) si cu stocare persistenta (EEPROM), pentru a acoperi cat mai multe notiuni din curs intr-un singur proiect. In plus, Snake este un joc cu logica simpla dar captivanta, iar provocarea de a-l face sa ruleze pe doar 64 de pixeli este parte din distractie.
Sistemul este compus din trei parti functionale principale:
Alimentarea se face de la portul micro-USB al PC-ului (5V), care serveste simultan si ca interfata de programare prin USB-ul nativ al ATmega32U4.
| Nr. | Componenta | Cantitate | Descriere / Rol |
|---|---|---|---|
| 1 | Placa Arduino Leonardo | 1 | Microcontroller ATmega32U4 @ 16 MHz |
| 2 | Matrice LED 8×8 cu driver MAX7219 (LED Dot Matrix Display, Red) | 1 | Display-ul propriu-zis al jocului |
| 3 | Modul joystick analogic (Generic, ex. KY-023) | 1 | Control directie X/Y + buton SW integrat pentru restart |
| 4 | Breadboard mic (Solderless Breadboard Half Size) | 1 | Suport pentru cablaj |
| 5 | Fire dupont tata-mama (Female/Female Jumper Wires) | ~10 | Conexiuni Arduino — module |
| 6 | Fire dupont generice (Jumper wires generic) | ~5 | Conexiuni pe breadboard |
| 7 | Cablu micro-USB | 1 | Programare si alimentare |
| Componenta | Pin componenta | Pin Arduino Leonardo | Port / Pin AVR |
|---|---|---|---|
| Joystick | VCC | 5V | — |
| Joystick | GND | GND | — |
| Joystick | VRX | A0 | PF7 (ADC7) |
| Joystick | VRY | A1 | PF6 (ADC6) |
| Joystick | SW (buton integrat) | D2 | PD1 (pull-up intern, active LOW — folosit pentru restart) |
| Matrice MAX7219 | VCC | 5V | — |
| Matrice MAX7219 | GND | GND | — |
| Matrice MAX7219 | DIN | D11 | PB7 |
| Matrice MAX7219 | CS | D10 | PB6 |
| Matrice MAX7219 | CLK | D13 | PC7 |
Schema de mai sus prezinta cablajul complet realizat pe breadboard: joystick-ul analogic conectat la pinii A0 (VRX), A1 (VRY) si D2 (SW pentru restart), iar matricea LED 8×8 cu driver MAX7219 conectata la pinii D11 (DIN), D10 (CS), D13 (CLK). Alimentarea de 5V este distribuita prin rail-urile breadboard-ului direct de la pinii Arduino.
avr-gcc + avr-libc + avr-objcopyavrdude (protocol avr109 pentru Leonardo, baud 57600)
Codul este organizat modular in mai multe grupuri de functii, toate in main.c:
spi_init(), spi_tx(), mx_wr(), mx_init() — toggle direct pe PORTB / PORTC pentru DIN, CS, CLK.fb_clr(), fb_dot(), fb_push() — un array uint8_t fb[8] tine starea matricei (un byte per linie, fiecare bit = un LED). Push pe matrice se face cu mx_wr(r+1, fb[r]).adc_init(), adc_rd(ch) — citire pe canalele ADC6 / ADC7 (A1 / A0), prescaler 128.btn_init(), btn_rst() — pull-up intern pe PD1, debounce software 30 ms.ee_load(), ee_save() — high-score-ul e salvat la adresa 0x00, cu un byte “guard” (0xD4) la adresa 0x01 pentru a detecta EEPROM neinitializat la primul boot.read_joy() (citeste joystick + previne intoarcerea pe directia opusa), game_step() (actualizeaza pozitia cu wrap-around la margini, detecteaza coliziuni, mananca hrana), place_apple() (random pana se gaseste o celula libera), cur_steps() (calculeaza viteza curenta in functie de scor).draw() (deseneaza sarpe + hrana blinking), show_score() (afiseaza scorul cu font 3×5), anim_boot() / anim_dead() (animatii).Pt snake[MAXLEN], unde MAXLEN = 64. Capul e snake[0]. La fiecare pas, toate elementele sunt shift-uite cu o pozitie si capul nou e scris la index 0.snake[] si se verifica daca noul cap se suprapune cu vreun segment existent.0xB400, seed-uit la boot din zgomotul ADC al ambelor axe — nu necesita hardware suplimentar.cur_steps() returneaza numarul de tick-uri (de 20 ms fiecare) intre deplasari — scade liniar cu scorul, de la 14 (start) la 4 (rapid).DIG[10][5] — fiecare cifra ocupa 3×5 pixeli, codificata ca 5 byti (low 3 biti activi per linie).Proiectul a fost finalizat cu succes — jocul Snake este complet functional pe placa Arduino Leonardo, ruleaza fluid pe matricea LED 8×8 si raspunde rapid la input-ul de la joystick. Implementarea in C bare-metal s-a dovedit a fi o alegere potrivita pentru acest tip de proiect, oferind control direct asupra timpilor de executie si o intelegere mai profunda a modului de functionare a microcontrollerului ATmega32U4 la nivel de registre.
0xD4) previne afisarea de valori reziduale la primul boot dupa flashing.JOY_LO = 300, JOY_HI = 700) a necesitat experimentare — prea mica genereaza schimbari de directie false, prea mare face controlul lent si imprecis.STEPS_SLOW = 14, STEPS_FAST = 4) au necesitat ajustare pentru un gameplay placut: prea rapid in faza incipienta, jocul devine frustrant; prea lent, devine plictisitor.
Arhiva contine varianta finala a proiectului, gata de compilat si rulat pe Arduino Leonardo. Include sursele complete (main.c), Makefile pentru build si flash, plus un fisier README cu instructiuni de utilizare.
Pentru a rula proiectul:
snake_game.zipmake pentru a compilamake flash (sau scriptul flash.ps1 pe Windows) pentru a incarca firmware-ul