This project involves the implementation of the classic Tetris game on an Arduino Uno platform, using an OLED display for graphical output, physical buttons for controlling the game pieces, and a buzzer to provide audio feedback. The system is designed to be fully interactive and responsive, replicating the retro gameplay experience using minimal hardware resources.
The main goal was to create a complete and functional embedded game that integrates basic peripherals and reinforces practical skills acquired during PM labs. The idea stemmed from our desire to bring a nostalgic game to life using modern embedded techniques, showcasing how even simple microcontrollers can be used to recreate iconic games. It also serves as a valuable educational tool—for ourselves, as a learning opportunity in hardware-software integration, and for others, as a straightforward example of an embedded application that is both engaging and technically relevant.
Exemplu de schemă bloc: http://www.robs-projects.com/mp3proj/newplayer.html
I2C – pentru comunicarea cu ecranul OLED (pinii A4 și A5)
PWM (modulare a lățimii impulsului) – pentru redarea de sunete prin buzzer (pinul D6)
GPIO – pentru citirea butoanelor (pinii D7, D8, D9, D10)
- Arduino Uno – Microcontrolerul principal care citește semnalele de la senzori și butoane, procesează logica stărilor și controlează afișajul și buzzerul.
- Display OLED 128×64 (I2C) – Afișează starea jocului de Tetris. Este conectat la interfața I2C a plăcii Arduino (SDA la A4, SCL la A5).
- Buzzer pasiv – Conectat la pinul D6 (compatibil PWM), este utilizat pentru a reda muzica de fundal.
- 4 butoane push – Conectate la pinii digitali D7, D8, D9 și D10, fiecare cu o rezistență de 10kΩ spre GND (configurație pull-down). Sunt folosite pentru: start/restart joc, miscare stanga, miscare dreapta, rotire.
Toate componentele sunt alimentate de la 5V și GND.
I2C – pentru comunicarea cu ecranul OLED (pinii A4 și A5)
PWM (modulare a lățimii impulsului) – pentru redarea de sunete prin buzzer (pinul D6)
GPIO – pentru citirea butoanelor (pinii D7, D8, D9, D10)
Componentă | Pin Arduino | Motivul alegerii |
OLED Display | A4 (SDA), A5 (SCL) | Pini dedicați pentru interfața I2C |
Buzzer | D6 | Pin digital compatibil PWM pentru `tone()` |
Button 1–4 | D7, D8, D9, D10 | Pini digitali disponibili, ușor de gestionat în cod |
Proiectul este dezvoltat în Arduino IDE, utilizând limbajul C++. Arduino IDE oferă un mediu prietenos pentru programare, testare și încărcare rapidă a codului pe placă. Am folosit bibliotecile standard Arduino, precum și unele biblioteci externe pentru controlul componentelor I2C și OLED.
Testarea și depanarea au fost realizate prin monitorul serial și feedback vizual/audio.
Adafruit_SSD1306 și Adafruit_GFX
Folosite pentru controlul ecranului OLED prin I2C. Oferă funcții pentru afișarea de text, pictograme și animații simple. Funcții utilizate:
- display.begin(): inițializează ecranul
- display.clearDisplay(): șterge conținutul ecranului
- display.setCursor(), display.print(): pentru afișare de text
- drawBitmap(): pentru afișarea pictogramelor
Wire.h
Folosită pentru comunicarea I2C cu ecranul OLED.
Funcționalități integrate:
- I2C – comunicarea cu afișajul OLED.
- GPIO – pentru citirea butonului.
- PWM – buzzer: redarea de tonuri diferite prin tone().
- Fiecare buton a fost testat individual – acționând stări diferite în managerul de stare.
- OLED-ul a fost validat cu mesaje și pictograme pentru fiecare stare.
- Feedback-ul audio a fost testat prin acționări repetitive și schimbări de stare.
- Comportamentul în timp real a fost verificat în sesiuni complete de testare.
Proiectul implementează un joc clasic Tetris pe un microcontroller Arduino, utilizând un display OLED SSD1306 și butoane fizice. Logica principală este centralizată în loop(), gestionând stările jocului și interacțiunile.
setup(): Configurează pinii hardware (butoane, speaker) → Inițializează comunicarea serială și display-ul OLED (display.begin()) → Afișează ecrane introductive: “Loading…” → “TETRIS” → logo-ul mantex_logo (din `PROGMEM`) → Inițializează generatorul de numere aleatoare (randomSeed()) → Generează prima piesă (nextType = random(TYPES); generate()) → Setează timer-ul principal și variabilele de debounce → starea principală a jocului.
setup() → Afișare ecrane introductive (“Loading…”, “TETRIS”, mantex_logo) →
Parametrii de joc, nu senzori fizici, definesc experiența.
Cea mai importantă abordare este utilizarea millis() pentru timer-ul jocului (timer), permițând procesarea input-ului între căderile pieselor. Bitmap-ul mantex_logo este stocat în `PROGMEM`. Display-ul este reîmprospătat prin refresh() (incluzând display.clearDisplay()).
Structura codului este modulară (ex: drawGrid(), checkLines(), generate(), copyPiece()). Utilizarea constantelor (`#define`, `const`) îmbunătățește lizibilitatea. Funcția copyPiece() centralizează logica formei pieselor.
Feedback audio (tone()) pentru acțiuni și evenimente (breakLine()). Afișarea piesei următoare (drawNextPiece()) și a scorului. Sistem de debounce pentru butoane. Funcția de restart include protecție la apăsare lungă.
Proiectul a fost finalizat cu succes, rezultând într-o versiune funcțională a jocului Tetris pe Arduino. Am implementat mecanismele de bază: generarea și controlul pieselor, detecția coliziunilor, eliminarea liniilor, scorul și “Game Over”. Sistemul rulează pe hardware, butoanele răspund, iar display-ul afișează corespunzător.
Realizarea acestui Tetris a fost o experiență valoroasă în programarea embedded și designul de jocuri simple. Am experimentat cu gestionarea stărilor, interacțiunea hardware și afișarea grafică. Procesul de debugging, în special pentru logica de coliziune și rotație, a fost o lecție importantă.
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.