This tutorial is part of: Matrice LED RGB ESP32-S3
Proiect interesant de creat pentru aplicații distractive și practice folosind modulul ESP32-S3 RGB Matrix. Linkuri către alte videoclipuri sunt sub acest articol.
Proiect 3 cu matrice LED RGB ESP32-S3 - Text de pe telefonul mobil
Proiectul 3 – Controlează textul matricei de pe telefon (HTTP Text)
În acest proiect, matricea LED RGB ESP32-S3 găzduiește o mică pagină web, astfel încât să poți schimba textul derulant, culoarea, direcția și viteza direct de pe telefon sau computer. Nu ai nevoie de o aplicație separată – doar de un browser web. Astfel, modulul devine un mic afișaj text Wi-Fi pe care îl poți actualiza în timp real.
Toate cele șase proiecte din această serie sunt explicate și demonstrate într-un singur videoclip YouTube. Același videoclip este încorporat pe această pagină, astfel încât să poți vedea exact cum arată interfața web și cum se actualizează textul instantaneu pe matrice. Codul sursă complet pentru acest proiect este încărcat automat mai jos, după articol, iar modulul ESP32-S3 RGB LED Matrix poate fi achiziționat din magazinele afiliate listate sub secțiunea de cod.
În acest articol ne concentrăm pe modul în care funcționează logica de rețea (Wi-Fi de acasă vs. punct de acces) și ce setări poți modifica în cod pentru a personaliza comportamentul.



Prezentare generală a modulului ESP32-S3 RGB LED Matrix
Hardware-ul este același ca pentru toate celelalte proiecte din această serie: o placă cu microcontroler ESP32-S3 cu o matrice LED RGB integrată de 8×8 și un senzor de mișcare QMI8658C pe spate. Portul USB-C este folosit pentru alimentare și programare, iar pinii de pe margini rămân disponibili pentru alte IO.:contentReference[oaicite:0]{index=0}

- ESP32-S3 – microcontroler cu capabilități Wi-Fi și Bluetooth.
- Matrice RGB 8×8 – 64 de LED-uri RGB adresabile pentru text și grafică.
- Accelerometru QMI8658C – folosit în proiectele de înclinare și jocuri.
- Port USB – alimentează placa și încarcă schițele din Arduino IDE.
- Pini expuși – permit conectarea de senzori sau actuatoare suplimentare, dacă este necesar.
- Butoane Boot/Reset – pentru încărcarea firmware-ului și repornire.
Pentru Proiectul 3, cea mai importantă caracteristică este Wi-Fi-ul ESP32, care permite plăcii să acționeze ca un mic server web pentru pagina de control al textului.:contentReference[oaicite:1]{index=1}

Proiecte acoperite în videoclip (Marcaje de timp)
Videoclipul unic pentru această serie acoperă toate cele șase proiecte. Pentru referință rapidă:
- 00:00 – Introducere
- 02:01 – Instalarea plăcilor ESP32
- 03:32 – Instalarea bibliotecilor
- 05:32 – Proiectul 1: Punct în mișcare
- 11:11 – Proiectul 2: Derulare text
- 12:59 – Proiectul 3: HTTP Text (acest proiect)
- 16:41 – Proiectul 4: Punct de înclinare
- 18:55 – Proiectul 5: Săgeată în sus
- 20:02 – Proiectul 6: Jocul țintă
Te încurajăm să urmărești secțiunea HTTP Text din videoclip în timp ce lucrezi cu acest articol. Videoclipul arată cum este generată pagina web de către ESP32 și cum schimbarea textului, culorii și vitezei se reflectă instantaneu pe matricea LED.:contentReference[oaicite:2]{index=2}
Instalarea plăcilor ESP32 în Arduino IDE
Dacă ai finalizat deja Proiectele 1 sau 2, configurarea plăcii este făcută și poți sări peste această secțiune. În caz contrar, urmează acești pași în Arduino IDE:
- Deschide
File > Preferencesși adaugă URL-ul plăcilor ESP32 la “Additional Boards Manager URLs”. - Mergi la
Tools > Board > Boards Manager…, cautăESP32și instalează pachetul oficial ESP32. - Selectează placa corectă ESP32-S3 RGB Matrix din
Tools > Board. - Conectează modulul prin USB și alege portul serial corect sub
Tools > Port.
Fără suportul adecvat pentru plăcile ESP32 și portul corect, schița serverului web nu se va încărca.
Instalarea NeoMatrix și a bibliotecilor necesare
Acest proiect folosește aceleași biblioteci ca proiectul anterior de derulare a textului:
Adafruit NeoMatrixAdafruit NeoPixelAdafruit GFX Library
Instalează prin Library Manager:
- Deschide
Sketch > Include Library > Manage Libraries…. - Caută
Adafruit NeoMatrixși dă clic pe Install. - Acceptă instalarea dependențelor (
Adafruit GFXșiAdafruit NeoPixel).
Odată instalate, ar trebui să vezi schițele de exemplu NeoMatrix și NeoPixel sub File > Examples.
Două moduri Wi-Fi în Proiectul 3
Cel mai important concept din acest proiect este că ESP32 poate funcționa în două moduri diferite:
- Modul Station (STA) – ESP32 se conectează la rețeaua Wi-Fi existentă de acasă.
- Modul Access Point (AP) – ESP32 își creează propria rețea Wi-Fi dacă Wi-Fi-ul de acasă nu este disponibil.
Ambele moduri folosesc aceeași interfață web: o pagină HTML servită de ESP32 însuși, unde poți schimba textul, culoarea, direcția de derulare și viteza.:contentReference[oaicite:3]{index=3}
Modul 1 – Conectare la Wi-Fi de acasă (Modul Station)
În modul Station, ESP32 se alătură rețelei Wi-Fi de acasă sau de la birou. Acesta este modul preferat ori de câte ori routerul este disponibil, deoarece:
- Telefonul și computerul tău sunt deja conectate la aceeași rețea Wi-Fi.
- Poți introduce adresa IP a ESP32 în browser și controla textul de pe orice dispozitiv din acea rețea.
În secțiunea de setări a schiței, furnizezi SSID-ul și parola Wi-Fi:
// Credențiale Wi-Fi de acasă (modul Stație) const char* WIFI_SSID = "YourHomeWiFi"; const char* WIFI_PASS = "YourHomePassword";După pornirea plăcii, aceasta încearcă să se conecteze la WIFI_SSID. Dacă reușește, codul afișează adresa IP atribuită în Monitorul Serial, de exemplu:
Connected to WiFi
IP address: 192.168.1.16
Pentru a controla textul:
- Asigurați-vă că telefonul sau PC-ul este conectat la aceeași rețea Wi-Fi (de exemplu,
YourHomeWiFi). - Deschideți un browser și introduceți adresa IP afișată, cum ar fi
http://192.168.1.16/. - Va apărea pagina de control, permițându-vă să tastați text, să alegeți culoarea, să selectați direcția și să ajustați viteza de derulare.
Modul 2 – Punct de Acces Independent (Modul AP)
Dacă ESP32 nu se poate conecta la Wi-Fi-ul de acasă (parolă greșită, rețea indisponibilă sau folosiți modulul în exterior), schița comută automat în modul Punct de Acces. În modul AP, ESP32 devine el însuși un hotspot Wi-Fi cu propriul nume de rețea și parolă.
În acest proiect, setările AP sunt fixate astfel:
// Credențiale Punct de Acces (AP) (mod de rezervă)
const char* AP_SSID = "ESP32";
const char* AP_PASS = "password";
Când modul Stație eșuează, modulul comută în modul AP și începe să transmită o rețea Wi-Fi numită ESP32. Pentru a controla matricea:
- Pe telefon sau computer, deschideți setările Wi-Fi și conectați-vă la rețeaua ESP32.
- Introduceți parola password (așa cum este definită în cod).
- După conectare, deschideți un browser și accesați
http://192.168.4.1/(IP-ul implicit pentru modul AP al ESP32). - Aceeași pagină de control apare, permițându-vă să schimbați textul, culoarea, viteza și direcția.
Acest comportament de rezervă face proiectul util oriunde: acasă, în laborator sau într-un mediu demonstrativ unde nu este disponibil un router.
Proiectul 3 – Setări Principale în Cod
Schița completă HTTP Text este încărcată mai jos de acest articol de către site. Aici documentăm doar cele mai importante opțiuni de configurare pe care probabil le veți edita.
Setări Wi-Fi și Punct de Acces
În partea de sus a schiței veți găsi secțiunea de configurare Wi-Fi. Schimbați doar credențialele pentru Stație (Wi-Fi de acasă); setările AP sunt păstrate în mod normal ca implicite:
// ---------- SETĂRI WI-FI ----------
// Wi-Fi de acasă (modul Stație)
const char* WIFI_SSID = "YourHomeWiFi"; // puneți SSID-ul routerului aici
const char* WIFI_PASS = "YourHomePassword"; // puneți parola routerului aici
// Punct de Acces de rezervă (modul AP)
const char* AP_SSID = "ESP32"; // nume AP fix
const char* AP_PASS = "password"; // parolă AP fixă
Comportament:
- Dacă
WIFI_SSIDșiWIFI_PASSsunt corecte și rețeaua este disponibilă → ESP32 se conectează ca un dispozitiv Wi-Fi normal (modul Stație). - Dacă conexiunea eșuează după un timeout → ESP32 pornește propriul AP folosind
AP_SSIDșiAP_PASS.
Pinul Matricei, Dimensiune și Luminozitate
Aceste setări sunt aceleași ca în proiectele anterioare:
// Configurarea matricei
const int MATRIX_PIN = 14; // pinul de date al matricei RGB
const int MATRIX_WIDTH = 8;
const int MATRIX_HEIGHT = 8;
// Luminozitatea generală a afișajului (0–255)
uint8_t matrixBrightness = 40; // ajustați pentru mediul dvs.
Păstrați MATRIX_PIN la 14 pentru această placă. Puteți crește matrixBrightness dacă aveți nevoie de mai multă lumină, dar valorile mai mici sunt mai confortabile pentru vizionarea de aproape.
Text Implicit și Setări de Derulare
Când placa pornește, afișează un mesaj inițial până când deschideți pagina web și tastați unul nou. Puteți schimba textul implicit în configurare:
// Mesaj implicit afișat la pornire
String currentText = "Robojax"; // suprascris ulterior din interfața web
Restul comportamentului de derulare este controlat de un set de variabile care sunt actualizate de interfața web:
// Întârziere de derulare în milisecunde (mai mic = mai rapid)
int scrollDelayMs = 50;
// Direcția de derulare: 0=stânga, 1=dreapta, 2=sus, 3=jos
int scrollDirection = 0; // implicit: derulare la stânga
Pagina web trimite valori noi pe baza selecțiilor de glisor și butoane. Din partea Arduino, trebuie doar să știți că:
- Scăderea
scrollDelayMsface textul să se miște mai repede. - Creșterea
scrollDelayMsîl face să se miște mai lent. - Schimbarea
scrollDirectioncomută între modurile de derulare stânga, dreapta, sus sau jos.
Culoarea Textului (Controlată din Pagina Web)
Culoarea textului este controlată de trei valori 0–255 (roșu, verde, albastru). Acestea sunt actualizate de fiecare dată când alegeți o nouă culoare pe pagina web:
// Culoarea curentă a textului (R, G, B)
uint8_t textRed = 255;
uint8_t textGreen = 255;
uint8_t textBlue = 255;
Când alegeți o culoare în browser și faceți clic pe Apply, ESP32 parsează valorile RGB și actualizează aceste trei variabile; textul își schimbă imediat culoarea pe matrice. În videoclip, acest comportament este demonstrat cu multiple schimbări de culoare, inclusiv exemple roșu, verde și albastru.
Rezumat
Proiectul 3 transformă matricea LED RGB ESP32-S3 într-un afișaj de text complet wireless pe care îl puteți controla folosind orice dispozitiv cu un browser web. Schița este concepută pentru a fi robustă:
- Încearcă mai întâi să se conecteze la rețeaua Wi-Fi de acasă folosind SSID-ul și parola pe care le-ai configurat.
- Dacă această încercare eșuează, devine automat un punct de acces cu numele
ESP32și parolapassword. - În ambele moduri, deschiderea adresei IP corecte într-un browser afișează aceeași pagină de control pentru text, culoare, direcție și viteză.
Codul HTTP Text complet este disponibil mai jos în acest articol (încărcat automat pe site). Pentru o prezentare detaliată pas cu pas și o demonstrație live a modului în care textul se actualizează în timp real, asigură-te că urmărești secțiunea Proiectul 3 din videoclip. Dacă dorești să construiești proiectul singur, poți achiziționa și modulul ESP32-S3 RGB LED Matrix folosind linkurile afiliate listate sub cod.
This tutorial is part of: Matrice LED RGB ESP32-S3
- Proiect ESP32-S3 cu Matrice LED RGB 1 - Punct de bază
- Proiect ESP32-S3 cu Matrice LED RGB 2 - Text Derulant
- Proiect ESP32-S3 cu matrice LED RGB 4 - Punct de înclinare
- Proiect ESP32-S3 cu matrice LED RGB 5 - Săgeata mereu în sus
- Proiect Matrice LED RGB ESP32-S3 6 - Joc Cible
- Proiect de ceas Wi-Fi + NTP cu matrice LED RGB ESP32-S3 -1 Ceas de bază
- Proiect de ceas cu matrice LED RGB ESP32-S3 conectat la internet - Afișaj de oră și dată în 2 ceasuri multicolore
- Proiect de ceas cu matrice LED RGB ESP32-S3 conectat la internet - 3 culori de noapte cu dată
- Proiect de ceas internet cu matrice LED RGB ESP32-S3 - 5 culori curcubeu
- Proiect de ceas internet cu matrice LED RGB ESP32-S3 - 4 culori aleatorii
- ESP32-S3 RGB LED Matrix test for RGB, GRB setting
/*
Project 4: HTTP Text Scroll – ESP32-S3 RGB LED Matrix (Waveshare)
- Connects to your home WiFi (station mode, with AP fallback).
- Serves a web page where you can set:
* Text
* Color
* Display ON/OFF
* Scroll direction (Left / Right / Up / Down)
* Scroll delay (speed)
- Supports 8×8 RGB LED matrix using Adafruit_NeoMatrix.
▶️ Video Tutorial:
https://youtu.be/JKLuYrRcLMI
📄 Resources & Code Page:
https://robojax.com/your-resources-page-here
HTTP_Text_Scroll
*/
#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
// ======================= WIFI SETTINGS =========================
// Home WiFi (change these to your router credentials)
const char* WIFI_SSID = "Biseem";
const char* WIFI_PASS = "wan9&Jang~";
// Fallback Access Point
const char* AP_SSID = "ESP32";
const char* AP_PASS = "password";
// ======================= MATRIX SETTINGS =======================
#define MATRIX_PIN 14
#define MATRIX_WIDTH 8
#define MATRIX_HEIGHT 8
// 0, 1, 2, or 3 – adjust if text orientation is wrong with USB up
#define MATRIX_ROTATION 0
#define BRIGHTNESS 15
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(
MATRIX_WIDTH, MATRIX_HEIGHT, MATRIX_PIN,
NEO_MATRIX_TOP + NEO_MATRIX_LEFT +
NEO_MATRIX_ROWS + NEO_MATRIX_PROGRESSIVE,
NEO_RGB + NEO_KHZ800
);
// ======================= SCROLL STATE ==========================
enum ScrollDir {
DIR_LEFT = 0,
DIR_RIGHT,
DIR_UP,
DIR_DOWN
};
String scrollText = "Robojax";
uint16_t textColor = 0xFFFF; // default white
bool displayOn = true;
ScrollDir currentDir = DIR_LEFT;
// 1 step every this many ms (lower = faster)
unsigned long scrollInterval = 80;
unsigned long lastScrollTime = 0;
// Horizontal scroll position
int scrollX = MATRIX_WIDTH;
int scrollY = 0; // top row
// State for vertical per-letter scroll
int vertCharIndex = 0; // which character of the string
int vertY = MATRIX_HEIGHT; // vertical position of that character
// ======================= WEB SERVER ============================
WebServer server(80);
// ======================= HTML PAGE ============================
const char MAIN_page[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ESP32 Text Scroll</title>
<style>
body {
font-family: Arial, sans-serif;
background: #111;
color: #eee;
text-align: center;
margin: 0;
padding: 10px;
}
.container {
max-width: 360px;
width: 100%%;
margin: 0 auto;
background: #222;
padding: 12px;
border-radius: 10px;
box-sizing: border-box;
}
input[type="text"] {
width: 100%%;
padding: 8px;
box-sizing: border-box;
border-radius: 5px;
border: 1px solid #444;
background: #111;
color: #eee;
margin-bottom: 10px;
}
.row {
margin: 10px 0;
}
.label {
display: block;
margin-bottom: 5px;
text-align: left;
}
.toggle {
display: inline-flex;
align-items: center;
gap: 8px;
}
.arrow-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
grid-template-rows: repeat(3, 50px);
gap: 8px;
justify-content: center;
margin-top: 10px;
}
.arrow-btn {
background: #333;
border: 1px solid #555;
color: #eee;
font-size: 18px;
border-radius: 10px;
cursor: pointer;
width: 100%%;
height: 100%%;
}
.arrow-btn.active {
background: #0a84ff;
}
.arrow-btn:disabled {
opacity: 0.5;
cursor: default;
}
button#applyBtn {
margin-top: 15px;
padding: 10px 20px;
border-radius: 8px;
border: none;
background: #0a84ff;
color: #fff;
font-size: 16px;
cursor: pointer;
}
button#applyBtn:active {
transform: scale(0.97);
}
</style>
</head>
<body>
<div class="container">
<h2>Robojax ESP32-S3 Matrix Text Scroll</h2>
<div class="row">
<span class="label">Text to scroll:</span>
<input type="text" id="text" value="Hello" />
</div>
<div class="row">
<span class="label">Color:</span>
<input type="color" id="color" value="#ffffff" />
</div>
<div class="row">
<span class="label">Scroll Delay (fast → slow):</span>
<input
type="range"
id="speed"
min="20"
max="300"
value="80"
oninput="document.getElementById('speedVal').innerText = this.value + ' ms';"
/>
<div id="speedVal" style="text-align:right;font-size:12px;margin-top:4px;">
80 ms
</div>
</div>
<div class="row">
<label class="toggle">
<input type="checkbox" id="power" checked />
<span>Display ON</span>
</label>
</div>
<div class="row">
<span class="label">Scroll Direction:</span>
<div class="arrow-grid">
<div></div>
<button class="arrow-btn" id="btnUp" onclick="setDir('up')">▲</button>
<div></div>
<button class="arrow-btn" id="btnLeft" onclick="setDir('left')">◀</button>
<div></div>
<button class="arrow-btn" id="btnRight" onclick="setDir('right')">▶</button>
<div></div>
<button class="arrow-btn" id="btnDown" onclick="setDir('down')">▼</button>
<div></div>
</div>
</div>
<button id="applyBtn" onclick="sendUpdate()">Apply</button>
<p id="status"></p>
</div>
<script>
let currentDir = 'left';
function setDir(dir) {
currentDir = dir;
document.querySelectorAll('.arrow-btn').forEach(b => b.classList.remove('active'));
if (dir === 'up') document.getElementById('btnUp').classList.add('active');
if (dir === 'down') document.getElementById('btnDown').classList.add('active');
if (dir === 'left') document.getElementById('btnLeft').classList.add('active');
if (dir === 'right') document.getElementById('btnRight').classList.add('active');
sendUpdate();
}
function sendUpdate() {
const text = document.getElementById('text').value;
const color = document.getElementById('color').value;
const power = document.getElementById('power').checked ? '1' : '0';
const speed = document.getElementById('speed').value;
const url = `/update?text=${encodeURIComponent(text)}&color=${encodeURIComponent(color)}&power=${power}&dir=${currentDir}&speed=${speed}`;
fetch(url)
.then(r => r.text())
.then(t => {
document.getElementById('status').innerText = t;
})
.catch(err => {
document.getElementById('status').innerText = 'Error sending update';
});
}
// Set default active
setDir('left');
</script>
</body>
</html>
)rawliteral";
// ======================= HELPERS ===============================
bool isHexChar(char c) {
return (c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'f') ||
(c >= 'A' && c <= 'F');
}
String urlDecode(const String &src) {
String result;
result.reserve(src.length());
for (size_t i = 0; i < src.length(); i++) {
char c = src[i];
if (c == '+') {
result += ' ';
} else if (c == '%' && i + 2 < src.length()) {
char h1 = src[i + 1];
char h2 = src[i + 2];
if (isHexChar(h1) && isHexChar(h2)) {
char hex[3] = {h1, h2, 0};
int val = (int)strtol(hex, nullptr, 16);
result += (char)val;
i += 2;
} else {
result += c;
}
} else {
result += c;
}
}
return result;
}
uint16_t colorFromHex(const String &hex) {
// Expect "#RRGGBB" or "RRGGBB"
String c = hex;
if (c.startsWith("#")) c.remove(0, 1);
if (c.length() != 6) {
// default white
return matrix.Color(255, 255, 255);
}
long value = strtol(c.c_str(), NULL, 16);
uint8_t r = (value >> 16) & 0xFF;
uint8_t g = (value >> 8) & 0xFF;
uint8_t b = (value) & 0xFF;
return matrix.Color(r, g, b);
}
void resetScrollPosition() {
int textWidth = scrollText.length() * 6; // default font ~6 px per char
int textHeight = 8; // 5x7 font fits in 8
switch (currentDir) {
case DIR_LEFT:
// Start from just outside the right edge
scrollX = MATRIX_WIDTH;
scrollY = 0;
break;
case DIR_RIGHT:
// Start from just outside the left edge
scrollX = -textWidth;
scrollY = 0;
break;
case DIR_UP:
// Per-letter vertical scroll, starting with first character below matrix
vertCharIndex = 0;
vertY = MATRIX_HEIGHT; // 8 → enters from bottom
break;
case DIR_DOWN:
// Per-letter vertical scroll, starting with first character above matrix
vertCharIndex = 0;
vertY = -textHeight; // -8 → enters from top
break;
}
}
// ======================= HTTP HANDLERS =========================
void handleRoot() {
server.send_P(200, "text/html", MAIN_page);
}
void handleUpdate() {
if (server.hasArg("text")) {
String txt = urlDecode(server.arg("text"));
if (txt.length() == 0) {
scrollText = " ";
} else {
scrollText = txt;
}
}
if (server.hasArg("color")) {
String hex = server.arg("color");
textColor = colorFromHex(hex);
}
if (server.hasArg("power")) {
String p = server.arg("power");
displayOn = (p == "1");
}
if (server.hasArg("dir")) {
String d = server.arg("dir");
if (d == "left") currentDir = DIR_LEFT;
else if (d == "right") currentDir = DIR_RIGHT;
else if (d == "up") currentDir = DIR_UP;
else if (d == "down") currentDir = DIR_DOWN;
}
if (server.hasArg("speed")) {
String s = server.arg("speed");
int val = s.toInt();
// simple safety clamp
if (val < 10) val = 10; // very fast
if (val > 1000) val = 1000; // 1 second max
scrollInterval = (unsigned long)val;
// Serial.print("Scroll interval set to ");
// Serial.print(scrollInterval);
// Serial.println(" ms");
}
resetScrollPosition();
server.send(200, "text/plain", "Updated");
}
// ======================= SCROLL LOGIC ==========================
void drawScroll() {
if (!displayOn) {
matrix.fillScreen(0);
matrix.show();
return;
}
int textWidth = scrollText.length() * 6;
int textHeight = 8;
matrix.fillScreen(0);
matrix.setTextSize(1);
matrix.setTextWrap(false);
matrix.setTextColor(textColor);
// -------- HORIZONTAL SCROLL (LEFT / RIGHT) --------
if (currentDir == DIR_LEFT || currentDir == DIR_RIGHT) {
matrix.setCursor(scrollX, 0);
matrix.print(scrollText);
matrix.show();
if (currentDir == DIR_LEFT) {
scrollX--;
if (scrollX < -textWidth) {
scrollX = MATRIX_WIDTH;
}
} else { // DIR_RIGHT
scrollX++;
if (scrollX > MATRIX_WIDTH) {
scrollX = -textWidth;
}
}
return;
}
// -------- VERTICAL SCROLL (UP / DOWN) – PER LETTER --------
if (scrollText.length() == 0) {
matrix.show();
return;
}
// Current character
char c = scrollText[vertCharIndex];
int charWidth = 6;
int baseX = (MATRIX_WIDTH - charWidth) / 2; // center horizontally
matrix.setCursor(baseX, vertY);
matrix.print(c);
matrix.show();
if (currentDir == DIR_UP) {
// Move character upwards
vertY--;
if (vertY < -textHeight) {
// This character is fully passed, go to next
vertY = MATRIX_HEIGHT;
vertCharIndex++;
if (vertCharIndex >= scrollText.length()) {
vertCharIndex = 0; // loop back to first character
}
}
} else if (currentDir == DIR_DOWN) {
// Move character downwards
vertY++;
if (vertY > MATRIX_HEIGHT) {
// This character is fully passed, go to next
vertY = -textHeight;
vertCharIndex++;
if (vertCharIndex >= scrollText.length()) {
vertCharIndex = 0; // loop back
}
}
}
}
// ======================= WIFI INIT =============================
void startAPFallback() {
Serial.println("Starting AP fallback...");
WiFi.mode(WIFI_AP);
bool apOk = WiFi.softAP(AP_SSID, AP_PASS);
if (apOk) {
Serial.print("AP started. SSID: ");
Serial.print(AP_SSID);
Serial.print(" IP: ");
Serial.println(WiFi.softAPIP());
} else {
Serial.println("Failed to start AP.");
}
}
void connectWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
Serial.print("Connecting to WiFi ");
Serial.print(WIFI_SSID);
unsigned long startAttempt = millis();
const unsigned long timeout = 10000; // 10s
while (WiFi.status() != WL_CONNECTED && (millis() - startAttempt) < timeout) {
Serial.print(".");
delay(500);
}
Serial.println();
if (WiFi.status() == WL_CONNECTED) {
Serial.print("Connected. IP address: ");
Serial.println(WiFi.localIP());
} else {
Serial.println("WiFi connect failed, starting AP fallback.");
startAPFallback();
}
}
// ======================= SETUP & LOOP ==========================
void setup() {
Serial.begin(115200);
delay(500);
// Matrix init
matrix.begin();
matrix.setRotation(MATRIX_ROTATION);
matrix.setBrightness(BRIGHTNESS);
matrix.fillScreen(0);
matrix.show();
// WiFi
connectWiFi();
// Web server routes
server.on("/", handleRoot);
server.on("/update", handleUpdate);
server.onNotFound([]() {
server.send(404, "text/plain", "Not found");
});
server.begin();
Serial.println("HTTP server started.");
resetScrollPosition();
}
void loop() {
server.handleClient();
unsigned long now = millis();
if (now - lastScrollTime >= scrollInterval) {
lastScrollTime = now;
drawScroll();
}
}
Lucruri de care ai putea avea nevoie
-
Amazon
-
eBay
-
AliExpressPurchase ESP32-S3 RGB Matrix from AliExpresss.click.aliexpress.com
-
AliExpressPurchase ESP32-S3 RGB Matrix from AliExpress (2)s.click.aliexpress.com
Resurse și referințe
-
Internă🎨 Color picker Toolrobojax.com
Fișiere📁
Fișier Fritzing
-
esp32-S3-supermini-tht fritzing part
esp32-S3-supermini-tht.fzpz0.02 MB