Consola va fi encapsulata intr-o carcasa printata 3d si va avea un ecran color pe care se desfasoara jocurile, incluzand un meniu de selectie. Pe langa acestea, vor fi amplasate butoane pentru controlul in cadrul jocurilor, pentru controlul sunetului sau a statusul consolei (on, sound, sleep).
Ceea ce doresc sa realizez este si functionalitatea de power management a consolei pentru conservarea energiei cand nu se joaca nimeni pe ea.
Ideea a pornit mai mult din dorinta de a face ceva fun si interactiv si sa invat mai mult despre cum se poate construi un proiect practic pana la stadiul de a fi chiar utilizabil.
Pentru salvarea high scores sau a nivelurilor la care jucatorul a ajuns voi folosi un card micro sd conectat la placuta care sa memoreze aceste date.
Placuta de ESP32 va actiona drept 'creierul' consolei de joc. De la acesta se vor trimite comenzile de desenare prin SPI catre ecran, se vor salva si respectiv retrage datele despre highscores si nivelurile la care a ajuns jucatorul si va interpreta comenzile de la butoane prin intreruperi. De asemenea prin timerele interne ale placutei se va monitoriza perioada de inactivitate pentru a trece consola intr-un sistem de low power pentru conservarea bateriei.
Modul Pin | ESP32 Pin | Protocol | Funcție |
---|---|---|---|
VCC | 3V3 | Power | Alimentare 3.3 V |
GND | GND | Power | Masă comună |
SCK | GPIO18 | SPI_CLK | Ceas SPI |
MISO | GPIO19 | SPI_MISO | Date SPI din SD |
MOSI | GPIO23 | SPI_MOSI | Date SPI către TFT/SD |
CS | GPIO5 | SPI_CS | Chip-select pentru TFT |
DC | GPIO2 | GPIO/SPI | Data/Command TFT |
RST | GPIO16 | GPIO | Reset hardware TFT |
SDCS | GPIO4 | SPI_CS | Chip-select pentru microSD |
BL | GPIO15 | PWM | Reglaj backlight (PWM SAFE) |
Funcție | GPIO Pin | Config | Interrupție |
---|---|---|---|
D-pad Sus | GPIO32 | INPUT_PULLUP | FALLING (apăsare) |
D-pad Jos | GPIO33 | INPUT_PULLUP | FALLING (apăsare) |
D-pad Stânga | GPIO25 | INPUT_PULLUP | FALLING (apăsare) |
D-pad Dreapta | GPIO26 | INPUT_PULLUP | FALLING (apăsare) |
Buton A | GPIO27 | INPUT_PULLUP | FALLING (apăsare) |
Buton B | GPIO14 | INPUT_PULLUP | FALLING (apăsare) |
Sound | GPIO21 | INPUT_PULLUP | FALLING (apăsare) |
Menu | GPIO22 | INPUT_PULLUP | FALLING (apăsare) |
Power | GPIO12 | INPUT_PULLUP + WAKE | FALLING (deep-sleep wake) |
Divizor node | ESP32 Pin | Protocol | Descriere |
---|---|---|---|
Între R1 și R2 | GPIO35 | ADC1_CH7 (ADC_11db) | Măsurare tensiune baterie (factor 2×) |
Încărcător CC/CV pentru o singură celulă Li-Ion, alimentat la 5 V (micro-USB sau boost). Conține circuit de protecție la supraîncărcare, scurt-circuit și sub-tensiune. Pinii B+/B– se conectează la baterii, iar OUT+/OUT– livrează tensiunea protejată către consolă.
Nume piesă | Cantitate | Link |
---|---|---|
Placă de dezvoltare ESP32 cu WiFi & Bluetooth 4.2 | 1 | ESP32 |
Display LCD TFT 320×240 2.2″ cu slot microSD | 1 | Display TFT 2.2″ |
Modul DC-DC 1.5–5 V → 3.3 V | 1 | DC-DC 1.5–5 V→3.3 V |
Modul încărcător TP4056 LiPo 1 A cu protecție | 1 | TP4056 charger |
Card de memorie MicroSDHC 4 GB, Class 10 | 1 | MicroSD card 4 GB |
Suport baterii 2×18650 | 1 | Battery holder 2×18650 |
Celule Li-Ion 18650 3.7 V | 2 | 18650 Li-Ion 3.7 V |
Buzzer pasiv | 1 | – |
Push-buttons tactile (momentary) | 9 | – |
Fire jumper (duse-întoarse) | 10 | – |
Rezistoare 100 kΩ | 2 | – |
Link proiect Github: https://github.com/Bogdan-Rusu17/Retro_Games_Console
Link video cu demo: https://youtu.be/d9HI2PYjIhI
Cateva fragmente de cod interesante:
const int8_t shapes[7][4][4][2] = { // I-piece { // 0° 90° 180° 270° {{-2,0},{-1,0},{0,0},{1,0}}, //orizontal {{0,-2},{0,-1},{0,0},{0,1}}, // vertical {{-2,-1},{-1,-1},{0,-1},{1,-1}},// orizontal {{-1,-2},{-1,-1},{-1,0},{-1,1}} // vertical }, //... };
{ {cos(pi / 2), sin(pi / 2)}, {cos(pi / 2), -sin(pi / 2)} }
void IRAM_ATTR onBtn(volatile uint32_t &lastTime, uint32_t debounce, volatile bool &flag) { uint32_t now = micros(); if (now - lastTime > debounce) flag = true; lastTime = now; }
void IRAM_ATTR onUp() { if (state == TETRIS) { onBtn(lastUp, DEB_SOUND, btnUpFlag); } else if (state == SNAKE) { onBtn(lastUp, DEB_FAST, btnUpFlag); } onBtn(lastUp, DEB_SOUND, btnUpFlag); } // alte butoane
pinMode(TFT_BL, OUTPUT); analogWrite(TFT_BL, brightness); ledcAttachChannel(BUZZER_PIN, 2000, 8, 2); ledcWriteTone(BUZZER_PIN, 0); //...
if (digitalRead(BTN_A)==LOW && now - lastBright > BRIGHT_DEBOUNCE_MS) { brightness = min(brightness + 16, 255); analogWrite(TFT_BL, brightness); lastBright = now; } if (digitalRead(BTN_B)==LOW && now - lastBright > BRIGHT_DEBOUNCE_MS) { brightness = max(brightness - 16, 0); analogWrite(TFT_BL, brightness); lastBright = now; }
Prin functia `analogWrite` cresc sau descresc factorul de umplere ca sa maresc/micsorez luminozitatea ecranului in termeni discreti pana la rezolutia maxima a timer-ului 0 pe care se bazeaza acest PWM.
#define TFT_DC 2 #define TFT_RST -1 // pus la 3v3 #define TFT_BL 15 // pwm pt luminozitate ecran #define SD_CS 4 // select la card // instantiaza obiectul tft cu care am acces la functiile ecranului Adafruit_ILI9341 tft(TFT_CS, TFT_DC, TFT_RST); /* {...} */ SPI.begin(18, 19, 23); tft.begin(); tft.setRotation(0);
analogReadResolution(12); analogSetAttenuation(ADC_11db); pinMode(BAT_ADC_PIN, INPUT);
void drawBattery() { // updateaza bateria doar odata la 1s ca sa nu fie flicker int now = millis(); if (now - lastBatUpdate < 1000) { return; } lastBatUpdate = now; int raw = analogRead(BAT_ADC_PIN); float m = (raw / 4095.0f) * 3.3f, v = m * 2.0f * BAT_CAL_FACTOR; int pct = constrain(int((v - BAT_EMPTY_VOLTAGE) / (BAT_FULL_VOLTAGE - BAT_EMPTY_VOLTAGE) * 100 + 0.5), 0, 100); tft.fillRect(0, 0, tft.width(), 20, ILI9341_BLACK); tft.setCursor(2,2); tft.setTextSize(2); tft.setTextColor(ILI9341_WHITE); tft.print(v,2); tft.print("V"); tft.setCursor(tft.width()-50, 2); tft.print(pct); tft.print("%"); }
Per total a fost un proiect destul de interesant de realizat in care am imbinat si cunostinte de electronica si de programare intr-un mod destul de placut si sunt destul de multumit de cum a functionat totul intr-un final.
Mi-ar fi placut in schimb sa gasesc niste fire mai bune de lipit cu care sa realizez proiectul pe perfboard intrucat ar fi aratat mult mai clean…, dar a fost interesant sa imi reamintesc cum se fac lipituri, pentru partea de baterii si la ecran (nu avea pinii pusi).