This is an old revision of the document!
| Nume: | Alexandru Diaconu |
|---|---|
| Grupa: | 331CD |
Ce face?
CyberPull este un joc arcade interactiv pentru doi jucători inspirat din “trage de sfoară”. Un punct luminos pornește din centrul unei benzi LED. Fiecare jucător apasă butonul său cât mai repede pentru a trage punctul în jumătatea lui. Primul care îl duce la capătul său câștigă runda.
Care este scopul lui?
Distracție pentru doi jucători, testând viteza de reacție într-un format competitiv și vizual atractiv.
Care a fost ideea de la care am pornit?
Am vrut un proiect care să folosească toate conceptele de laborator (întreruperi, timere, PWM, ADC, I2C) într-un mod practic și interactiv, rezultând ceva ce poate fi demonstrat imediat oricui.
De ce este util?
Este un joc standalone complet funcțional, cu carcasă fizică din plexiglass, care poate fi folosit fără laptop după ce codul este încărcat.
Schema bloc a proiectului:
Modulele principale:
Listă de componente:
| Componentă | Specificații | Cantitate |
|---|---|---|
| Arduino Uno R3 | ATmega328P, DIP | 1 |
| Bandă LED WS2812B | 60 LED/m, 30 LED-uri (50cm) | 1 |
| Buton Arcade cu LED | 16mm, 3-6V, roșu | 1 |
| Buton Arcade cu LED | 16mm, 3-6V, albastru | 1 |
| Potențiometru | 10kΩ liniar | 1 |
| Buzzer Pasiv | 3.3V | 1 |
| LCD 1602 + modul I2C | PCF8574, 5V | 1 |
| Adaptor alimentare | 9V / 1A | 1 |
| Breadboard | 830 puncte | 1 |
| Rezistor 330Ω | 1/4W THT | 3 |
| Rezistor 10kΩ | 1/4W THT | 5 |
| Rezistor 100Ω | 1/4W THT | 3 |
| Condensator electrolitic | 1000µF / 35V | 1 |
| Fire Dupont M-F | 30cm, 40 buc | 1 set |
| Fire Dupont M-M | 10cm, 40 buc | 1 set |
Schema electrică:
Mediu de dezvoltare: Arduino IDE 2.x
Biblioteci folosite:
Adafruit_NeoPixel — control bandă LED WS2812BLiquidCrystal_I2C — control LCD prin I2Cavr/interrupt.h — întreruperi hardware (built-in)Concepte de laborator:
De completat după asamblare și testare.
De completat după finalizarea proiectului.
Codul sursă, schema electrică și fotografiile proiectului sunt disponibile pe GitHub:
| Dată | Activitate |
|---|---|
| Mai 2026 | Definirea conceptului, finalizarea listei de componente |
| TBD | Primirea componentelor și asamblarea hardware |
| TBD | Implementare software — întreruperi + control LED |
| TBD | Implementare software — ADC, PWM, I2C |
| TBD | Testare și debugging |
| TBD | Demo final și documentație |
Mediu de dezvoltare
Biblioteci third-party
| Bibliotecă | Rol |
|---|---|
| Adafruit NeoPixel | Controlul benzii LED WS2812B adresabile |
| LiquidCrystal_I2C | Comunicare cu LCD 16×2 prin protocolul I2C |
| avr/interrupt.h | Gestionarea întreruperilor hardware INT0/INT1 (built-in AVR) |
| Wire.h | Suport I2C pentru comunicarea cu LCD (built-in Arduino) |
Arhitectura sistemului
Firmware-ul este structurat într-un singur fișier principal:
cyberpull.ino — punctul de intrare. Inițializează toate perifericele (bandă LED, LCD, butoane, buzzer, potențiometru), configurează întreruperile hardware, pornește jocul și gestionează logica principală în bucla loop().API HTTP
Nu este cazul — proiectul este standalone, fără comunicare WiFi sau Serial în producție. Pinout-ul complet:
| Pin Arduino | Componentă | Rol |
|---|---|---|
| D2 (INT0) | Buton J1 | Întrerupere externă — apăsare jucător 1 |
| D3 (INT1) | Buton J2 | Întrerupere externă — apăsare jucător 2 |
| D4 | LED buton J1 | Iluminare buton jucător 1 |
| D5 | LED buton J2 | Iluminare buton jucător 2 |
| D6 | Bandă LED WS2812B (DIN) | Semnal date bandă LED |
| D11 (OC2A) | Buzzer pasiv | PWM Timer2 — generare sunete |
| A0 | Potențiometru 10kΩ | ADC — citire dificultate |
| A4 (SDA) | LCD I2C | Linie date I2C |
| A5 (SCL) | LCD I2C | Linie clock I2C |
Detalii cheie de implementare
Întreruperi hardware pentru butoane (Lab 2)
Butoanele jucătorilor sunt conectate pe pinii INT0 (D2) și INT1 (D3). La fiecare apăsare se declanșează automat rutinele ISR(INT0_vect) și ISR(INT1_vect). Aceasta garantează că nicio apăsare nu este pierdută, indiferent de ce face procesorul în acel moment.
Fiecare ISR implementează debouncing software cu o fereastră de 50ms — dacă două apăsări vin în mai puțin de 50ms, a doua este ignorată (zgomot mecanic al butonului).
Logica de mutare a LED-ului:
Control buzzer prin PWM (Lab 3)
Buzzerul pasiv este controlat de Timer2 în modul CTC pe pinul D11 (OC2A). Frecvența sunetului se calculează după formula:
OCR2A = F_CPU / (2 × 64 × frecvență) − 1
Sunete generate:
Citire potențiometru prin ADC (Lab 4)
Potențiometrul este citit pe pinul A0 folosind analogRead(). Valoarea de 10 biți (0–1023) este mapată la intervalul de dificultate 1–8 folosind funcția map():
difficulty = map(analogRead(A0), 0, 1023, 1, 8);
Dificultatea reprezintă numărul de apăsări necesare pentru a muta LED-ul o poziție. La dificultate 1 fiecare apăsare mută LED-ul, la dificultate 8 sunt necesare 8 apăsări.
Comunicare LCD prin I2C (Lab 6)
LCD-ul 16×2 cu modulul PCF8574 comunică prin protocolul I2C pe pinii A4 (SDA) și A5 (SCL), la adresa 0x27. Display-ul se actualizează la fiecare 500ms cu scorul curent și timpul scurs din rundă.
Funcții implementate
| Funcție | Rol |
|---|---|
setup() | Inițializează toate perifericele, configurează întreruperile, pornește jocul |
loop() | Bucla principală: citește ADC, actualizează LED și LCD, verifică câștig |
ISR(INT0_vect) | Tratează apăsarea butonului J1 — debounce + mutare LED stânga |
ISR(INT1_vect) | Tratează apăsarea butonului J2 — debounce + mutare LED dreapta |
afiseazaBanda() | Actualizează banda LED: zona J1 roșu, zona J2 albastru, LED activ alb |
animatieVictorie() | Clipire bandă LED în culoarea câștigătorului |
animatieStart() | Animație de intro la începerea rundei |
buzzerOn() | Pornește buzzerul la frecvența specificată prin Timer2 CTC |
buzzerOff() | Oprește buzzerul |
beep() | Emite un sunet scurt la frecvența și durata specificate |
melodieVictorie() | Redă melodia Do-Re-Mi-Fa-Sol la câștigarea rundei |
citesteDificultate() | Citește ADC și returnează dificultatea 1–8 |
afiseazaLCD() | Afișează scorul și cronometrul pe LCD prin I2C |
afiseazaVictorieLCD() | Afișează mesajul de victorie a rundei pe LCD |
verificaCastig() | Verifică dacă LED-ul a ajuns la capătul benzii |
resetRunda() | Resetează pozițiile și contoarele pentru o rundă nouă |
initIntreruperi() | Configurează registrele EICRA și EIMSK pentru INT0/INT1 |