This shows you the differences between two versions of the page.
pm:prj2024:apredescu:octavian.poenaru [2024/05/04 10:35] octavian.poenaru created |
pm:prj2024:apredescu:octavian.poenaru [2024/05/27 23:09] (current) octavian.poenaru [Bibliografie] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Nume proiect ====== | + | ====== Arduino Pong Game ====== |
===== Introducere ===== | ===== Introducere ===== | ||
- | <note tip> | + | Proiectul presupune ceva destul de rudimentar : **Pong** - joc video clasic într-un format **Arduino** și care necesită două persoane pentru a putea fi jucat . Proiectul utilizează un ecran OLED , în care se va afișa scorul fiecărui jucător, mingea și cele două palete. |
- | Prezentarea pe scurt a proiectului vostru: | + | |
- | * ce face | + | |
- | * care este scopul lui | + | |
- | * care a fost ideea de la care aţi pornit | + | |
- | * de ce credeţi că este util pentru alţii şi pentru voi | + | |
- | </note> | + | |
- | ===== Descriere generală ===== | + | |
- | <note tip> | + | Scopul acestui proiect este de a oferi o interfață interactivă prin care utilizatorii să poată explora conceptele de bază ale programării și electronicii. |
- | O schemă bloc cu toate modulele proiectului vostru, atât software cât şi hardware însoţită de o descriere a acestora precum şi a modului în care interacţionează. | + | |
- | Exemplu de schemă bloc: http://www.robs-projects.com/mp3proj/newplayer.html | + | Ideea proiectului a venit din dorința de a recrea un joc video clasic într-un format nou și accesibil, combinând nostalgia cu tehnologia modernă. |
+ | ===== Descriere generală ===== | ||
+ | |||
+ | <note> | ||
+ | * Fiecare jucător are câte 2 butoane , pentru a controla paleta în sus sau în jos . | ||
+ | * Buzzer-ul va scoate sunete în momentul în care mingea atinge paleta sau atunci când este înscris un punct 8-). | ||
+ | * LED-ul verde se va aprinde pentru jucătorul care a înscris punctul iar cel roșu pentru pierzător. | ||
+ | * Cel care are 7 puncte este câștigător iar LED-urile vor pâlpâi de câteva ori . | ||
</note> | </note> | ||
+ | |||
+ | |||
+ | |||
+ | ==== Schemă bloc ==== | ||
+ | {{:pm:prj2024:apredescu:schema-bloc.jpg?700|}} | ||
+ | |||
===== Hardware Design ===== | ===== Hardware Design ===== | ||
<note tip> | <note tip> | ||
- | Aici puneţi tot ce ţine de hardware design: | + | Piese folosite: |
- | * listă de piese | + | * Arduino UNO |
- | * scheme electrice (se pot lua şi de pe Internet şi din datasheet-uri, e.g. http://www.captain.at/electronic-atmega16-mmc-schematic.png) | + | * Buzzer |
- | * diagrame de semnal | + | * OLED I2C 128x64 |
- | * rezultatele simulării | + | * 4 butoane |
+ | * 2/4 LED-uri | ||
+ | |||
+ | {{:pm:prj2024:apredescu:schema_circuit_parnaie2.png?700|}} | ||
+ | |||
+ | În schematic, OLED-ul era prea mare pentru a fi pus pe breadboard. în realitate , eu l-am lipit de breadboard. Valabil și pentru buzzer. | ||
</note> | </note> | ||
+ | |||
+ | {{:pm:prj2024:apredescu:imagine_whatsapp_2024-05-23_la_20.14.40_36453707.jpg?700| }} | ||
+ | |||
+ | Piesele sunt funcționale și deja am început să lucrez pentru Software design. | ||
+ | |||
+ | |||
===== Software Design ===== | ===== Software Design ===== | ||
+ | Dezvoltarea codului am realizat-o in Arduino IDE | ||
- | <note tip> | + | Pe partea de software am folosit bibliotecile: |
- | 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 ===== | + | - Wire.h: librărie standard pentru comunicarea I2C pe plăcile Arduino. |
+ | - Adafruit_GFX.h: librărie grafică utilizată pentru a desena forme și texte pe display-uri. | ||
+ | - Adafruit_SSD1306.h: ibrărie specifică pentru controlul display-ului OLED SSD1306 prin intermediul comunicării I2C. | ||
- | <note tip> | ||
- | Care au fost rezultatele obţinute în urma realizării proiectului vostru. | ||
- | </note> | ||
- | ===== Concluzii ===== | + | ==Algoritmi și Structuri Implementate:== |
- | ===== Download ===== | + | **Setări Inițiale:** |
- | <note warning> | + | * Configurarea pinilor pentru butoane și LED-uri. |
- | 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ă ;-). | + | * Inițializarea comunicării I2C cu display-ul OLED. |
+ | * Afișarea ecranului de start cu un splash screen "Arduino Pong". | ||
- | 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**. | + | |
- | </note> | + | **Controlul Jocului:** |
+ | |||
+ | * Butoanele sunt utilizate pentru a controla mișcarea paletelor stânga și dreapta. | ||
+ | * Algoritm pentru actualizarea pozițiilor paletelor bazat pe intrările butoanelor. | ||
+ | * Algoritm pentru actualizarea poziției mingii și detectarea coliziunilor cu paletele și marginile ecranului. | ||
+ | * Algoritm pentru gestionarea punctajului și resetarea jocului atunci când un jucător câștigă. | ||
+ | |||
+ | |||
+ | **Desenarea Jocului:** | ||
+ | |||
+ | * Desenarea mingii, paletelor și scorurilor pe display-ul OLED folosind funcțiile oferite de Adafruit_GFX și Adafruit_SSD1306. | ||
+ | |||
+ | |||
+ | **Gestionarea Vitezei și Poziției Mingi:** | ||
+ | |||
+ | * Funcții pentru ajustarea vitezei mingii după fiecare coliziune cu o paletă sau cu marginile ecranului. | ||
+ | * Funcții pentru resetarea poziției mingii și ajustarea dimensiunilor paletelor după fiecare punct marcat. | ||
+ | |||
+ | |||
+ | **Anunțarea Câștigătorului:** | ||
+ | * Funcție pentru anunțarea câștigătorului prin clipirea unui LED specific de mai multe ori. | ||
+ | |||
+ | |||
+ | |||
+ | ==== Surse și Funcții Implementate: ==== | ||
+ | |||
+ | === Setup și Loop: === | ||
+ | |||
+ | <code cpp> | ||
+ | void setup() { | ||
+ | pinMode(l_up_button, INPUT); | ||
+ | pinMode(l_down_button, INPUT); | ||
+ | pinMode(r_up_button, INPUT); | ||
+ | pinMode(r_down_button, INPUT); | ||
+ | pinMode(led1, OUTPUT); | ||
+ | pinMode(led2, OUTPUT); | ||
+ | Serial.begin(9600); | ||
+ | randomSeed(analogRead(0)); | ||
+ | |||
+ | display.begin(SSD1306_SWITCHCAPVCC, 0x3C); | ||
+ | display.display(); | ||
+ | display.clearDisplay(); | ||
+ | |||
+ | display.setTextSize(1); | ||
+ | display.setTextColor(WHITE); | ||
+ | display.setCursor(display.width() / 2 - 20, 0); | ||
+ | display.println("Arduino"); | ||
+ | display.setCursor(display.width() / 2 - 10, 8); | ||
+ | display.println("Pong"); | ||
+ | display.display(); | ||
+ | delay(2000); | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | unsigned long currentMillis = millis(); | ||
+ | if (currentMillis - previousMillis >= interval) { | ||
+ | previousMillis = currentMillis; | ||
+ | updateGame(); | ||
+ | drawGame(); | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | === Funcții pentru Actualizarea Jocului și Desenare: === | ||
+ | |||
+ | <code cpp> | ||
+ | void updateGame() { | ||
+ | if (l_score >= max_score) { | ||
+ | announce_winner(led1); | ||
+ | reset_game(); | ||
+ | return; | ||
+ | } else if (r_score >= max_score) { | ||
+ | announce_winner(led2); | ||
+ | reset_game(); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | if (digitalRead(l_up_button) && l_pos > 0) { l_pos -= 2; } | ||
+ | else if (digitalRead(l_down_button) && l_pos < (y_pixels - l_paddle_height)) { l_pos += 2; } | ||
+ | |||
+ | if (digitalRead(r_up_button) && r_pos > 0) { r_pos -= 2; } | ||
+ | else if (digitalRead(r_down_button) && r_pos < (y_pixels - r_paddle_height)) { r_pos += 2; } | ||
+ | |||
+ | x_pos += x_vel; | ||
+ | y_pos += y_vel; | ||
+ | |||
+ | if (y_pos >= y_pixels - 1 || y_pos <= 0) { y_vel = -y_vel; adjust_speed(); } | ||
+ | if (ball_on_right_paddle()) { | ||
+ | x_vel = -x_vel; | ||
+ | adjust_speed(); | ||
+ | tone(speakerPin, 300, 100); | ||
+ | } else if (ball_on_left_paddle()) { | ||
+ | x_vel = -x_vel; | ||
+ | adjust_speed(); | ||
+ | tone(speakerPin, 250, 100); | ||
+ | } | ||
+ | |||
+ | if (x_pos >= x_pixels - 1) { | ||
+ | ball_reset(false); | ||
+ | l_score += 1; | ||
+ | tone(speakerPin, 50, 100); | ||
+ | digitalWrite(led1, HIGH); | ||
+ | delay(500); | ||
+ | digitalWrite(led1, LOW); | ||
+ | } else if (x_pos <= 0) { | ||
+ | ball_reset(true); | ||
+ | r_score += 1; | ||
+ | tone(speakerPin, 50, 100); | ||
+ | digitalWrite(led2, HIGH); | ||
+ | delay(500); | ||
+ | digitalWrite(led2, LOW); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void drawGame() { | ||
+ | display.clearDisplay(); | ||
+ | display.drawPixel(x_pos, y_pos, WHITE); | ||
+ | display.fillRect(0, l_pos, paddle_width, l_paddle_height, WHITE); | ||
+ | display.fillRect(x_pixels - paddle_width, r_pos, paddle_width, r_paddle_height, WHITE); | ||
+ | |||
+ | display.setTextSize(1); | ||
+ | display.setTextColor(WHITE); | ||
+ | display.setCursor(display.width() / 4, 0); | ||
+ | display.println(l_score); | ||
+ | display.setCursor(display.width() * 3 / 4, 0); | ||
+ | display.println(r_score); | ||
+ | |||
+ | display.display(); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | === Funcții de Utilitate: === | ||
+ | <code cpp> | ||
+ | bool ball_on_right_paddle() { | ||
+ | return ((x_pos + x_vel) >= x_pixels - paddle_width - 1 && y_pos >= r_pos && y_pos <= (r_pos + r_paddle_height)); | ||
+ | } | ||
+ | |||
+ | bool ball_on_left_paddle() { | ||
+ | return ((x_pos + x_vel) <= paddle_width - 1 && y_pos >= l_pos && y_pos <= (l_pos + l_paddle_height)); | ||
+ | } | ||
+ | |||
+ | void ball_reset(bool left) { | ||
+ | y_pos = random(display.height()); | ||
+ | y_vel = random(2) ? 3 : -3; | ||
+ | |||
+ | if (left) { | ||
+ | x_vel = 2; | ||
+ | x_pos = paddle_width; | ||
+ | } else { | ||
+ | x_vel = -2; | ||
+ | x_pos = display.width() - paddle_width - 1; | ||
+ | } | ||
+ | |||
+ | adjust_paddles(); | ||
+ | } | ||
+ | |||
+ | void adjust_speed() { | ||
+ | if (x_vel > 0 && x_vel < max_vel) { | ||
+ | x_vel += 1; | ||
+ | } else if (x_vel < 0 && x_vel > -max_vel) { | ||
+ | x_vel -= 1; | ||
+ | } | ||
+ | |||
+ | if (y_vel > 0 && y_vel < max_vel) { | ||
+ | y_vel += 1; | ||
+ | } else if (y_vel < 0 && y_vel > -max_vel) { | ||
+ | y_vel -= 1; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void adjust_paddles() { | ||
+ | int new_height = random(5, 15); | ||
+ | int mode = random(3); | ||
+ | |||
+ | if (mode == 0) { | ||
+ | l_paddle_height = new_height; | ||
+ | r_paddle_height = new_height; | ||
+ | } else if (mode == 1) { | ||
+ | l_paddle_height = new_height; | ||
+ | r_paddle_height = paddle_height; | ||
+ | } else { | ||
+ | l_paddle_height = paddle_height; | ||
+ | r_paddle_height = new_height; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void announce_winner(int winner_led) { | ||
+ | for (int i = 0; i < 6; i++) { | ||
+ | digitalWrite(winner_led, HIGH); | ||
+ | delay(250); | ||
+ | digitalWrite(winner_led, LOW); | ||
+ | delay(250); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void reset_game() { | ||
+ | l_score = 0; | ||
+ | r_score = 0; | ||
+ | l_paddle_height = 10; | ||
+ | r_paddle_height = 10; | ||
+ | ball_reset(random(2)); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ===== Download ===== | ||
+ | |||
+ | {{:pm:prj2024:apredescu:pong.zip|}} | ||
===== Jurnal ===== | ===== Jurnal ===== | ||
<note tip> | <note tip> | ||
- | Puteți avea și o secțiune de jurnal în care să poată urmări asistentul de proiect progresul proiectului. | ||
- | </note> | ||
- | ===== Bibliografie/Resurse ===== | + | * 28.04.2023 - Am finalizat ideea de bază a jocului, am creat flow-ul și am ales piesele potrivite pentru circuit |
- | + | * 11.05.2023 - Am comandat piesele pentru proiect. | |
- | <note> | + | * 12.05.2023 - Mi-au venit piesele pentru hardware. |
- | Listă cu documente, datasheet-uri, resurse Internet folosite, eventual grupate pe **Resurse Software** şi **Resurse Hardware**. | + | * 15.05.2023 - Am început să lucrez la hardware , iar o parte din breadboard nu merge. Laborantul mi-a spus ca unul din breadboard-uri era mai vechi și trebuiau legate părțile între ele , după cum se poate observa în poză . |
+ | * 16.05.2023 - Deja terminasem cu hardware-ul , așa că m-am apucat din timp de software, știind că acolo va fi mai greu. | ||
+ | * 23.05.2023 - Aproape termin cu soft-ul , momentan întâmpin niște bug-uri , bila merge prea lent , paletele prea rapid iar jocul e prea ușor. | ||
+ | * 25.05.2023 - Ajung într-un punct în care codul este suficient de ok , am mărit bila și velocitatea ei , am făcut o funcție de reset , am făcut ca paletele să aibă dimensiuni random atunci când un jucator dă gol , pentru a fi mai provocator jocul. | ||
</note> | </note> | ||
+ | ===== Concluzii ===== | ||
+ | A fost un proiect destul de interesant, mi-a plăcut să lucrez la el , exceptând momentele în care a trebuit să fac debug pentru chestii simple. | ||
- | <html><a class="media mediafile mf_pdf" href="?do=export_pdf">Export to PDF</a></html> | + | ===== Bibliografie===== |
+ | * [[https://www.arduino.cc/reference/en/libraries/adafruit-gfx-library/]] | ||
+ | * [[https://www.arduino.cc/reference/en/language/functions/communication/wire/]] | ||
+ | * [[https://github.com/adafruit/Adafruit_SSD1306]] |