This tutorial is part of: Matrix ya LED ya ESP32-S3 RGB
Mradi mzuri wa kuunda kwa ajili ya matumizi ya kufurahisha na ya vitendo kwa kutumia moduli ya ESP32-S3 RGB Matrix. Viungo vya video zingine viko chini ya makala haya.
Mradi wa ESP32-S3 RGB LED Matrix 3 - Maandishi kutoka kwa simu ya mkononi
Mradi 3 – Dhibiti Maandishi ya Matrix kutoka kwenye Simu yako (Maandishi ya HTTP)
Katika mradi huu, ESP32-S3 RGB LED Matrix huweka ukurasa mdogo wa wavuti ili uweze kubadilisha maandishi yanayotembea, rangi, mwelekeo, na kasi moja kwa moja kutoka kwenye simu yako au kompyuta. Huhitaji programu tofauti – unahitaji tu kivinjari cha wavuti. Hii inafanya moduli hii kuwa onyesho dogo la maandishi la Wi-Fi ambalo unaweza kusasisha kwa wakati halisi.
Miradi yote sita katika mfululizo huu imeelezewa na kuonyeshwa katika video moja ya YouTube. Video hiyo hiyo imepachikwa kwenye ukurasa huu, ili uweze kuona jinsi kiolesura cha wavuti kinavyoonekana na jinsi maandishi yanavyosasishwa papo hapo kwenye matrix. Msimbo kamili wa chanzo wa mradi huu hupakiwa kiotomatiki chini ya makala, na unaweza kununua moduli ya ESP32-S3 RGB LED Matrix kutoka maduka washirika yaliyoorodheshwa chini ya sehemu ya msimbo.
Katika makala hii tunazingatia jinsi mantiki ya mtandao inavyofanya kazi (Wi-Fi ya nyumbani dhidi ya kituo cha ufikiaji) na ni mipangilio gani unayoweza kubadilisha kwenye msimbo ili kubinafsisha tabia.



Muhtasari wa Moduli ya ESP32-S3 RGB LED Matrix
Vifaa ni sawa na vya miradi mingine yote katika mfululizo huu: bodi ya microcontroller ya ESP32-S3 yenye matrix ya LED ya RGB ya 8×8 iliyojengewa ndani na sensor ya mwendo ya QMI8658C nyuma. Bandari ya USB-C hutumika kwa nishati na upangaji programu, na pini karibu na kingo bado zinapatikana kwa IO nyingine.:contentReference[oaicite:0]{index=0}

- ESP32-S3 – microcontroller yenye uwezo wa Wi-Fi na Bluetooth.
- Matrix ya RGB 8×8 – LED 64 za RGB zinazoweza kushughulikiwa kwa maandishi na michoro.
- Accelerometer ya QMI8658C – inayotumika katika miradi ya kuinamisha na michezo.
- Bandari ya USB – inatoa nishati kwa bodi na kupakia skechi kutoka Arduino IDE.
- Pini zilizo wazi – huruhusu sensor au viendeshaji vya ziada ikihitajika.
- Vitufe vya Boot/Reset – kwa upakiaji wa firmware na kuanzisha upya.
Kwa Mradi 3, kipengele muhimu zaidi ni Wi-Fi ya ESP32, ambayo inaruhusu bodi kufanya kazi kama seva ndogo ya wavuti kwa ukurasa wa kudhibiti maandishi.:contentReference[oaicite:1]{index=1}

Miradi Inayoshughulikiwa kwenye Video (Vidokezo vya Muda)
Video moja ya mfululizo huu inashughulikia miradi yote sita. Kwa marejeleo ya haraka:
- 00:00 – Utangulizi
- 02:01 – Kusakinisha bodi za ESP32
- 03:32 – Kusakinisha maktaba
- 05:32 – Mradi 1: Nukta Inayotembea
- 11:11 – Mradi 2: Maandishi Yanayotembea
- 12:59 – Mradi 3: Maandishi ya HTTP (mradi huu)
- 16:41 – Mradi 4: Nukta ya Kuinamisha
- 18:55 – Mradi 5: Mshale Juu
- 20:02 – Mradi 6: Mchezo wa Shabaha
Unahimizwa kutazama sehemu ya Maandishi ya HTTP kwenye video unapofanya kazi na makala hii. Video inaonyesha jinsi ukurasa wa wavuti unavyozalishwa na ESP32 na jinsi kubadilisha maandishi, rangi, na kasi kunavyoakisiwa papo hapo kwenye matrix ya LED.:contentReference[oaicite:2]{index=2}
Kusakinisha Bodi za ESP32 kwenye Arduino IDE
Ikiwa tayari umekamilisha Mradi 1 au 2, usanidi wa bodi umekamilika na unaweza kuruka sehemu hii. Vinginevyo, fuata hatua hizi kwenye Arduino IDE:
- Fungua
File > Preferencesna ongeza URL ya bodi za ESP32 kwenye “Additional Boards Manager URLs”. - Nenda kwenye
Tools > Board > Boards Manager…, tafutaESP32, na usakinishe kifurushi rasmi cha ESP32. - Chagua bodi sahihi ya ESP32-S3 RGB Matrix kutoka
Tools > Board. - Unganisha moduli kupitia USB na uchague bandari sahihi ya mfululizo chini ya
Tools > Port.
Bila usaidizi sahihi wa bodi ya ESP32 na bandari sahihi, skechi ya seva ya wavuti haitapakia.
Kusakinisha NeoMatrix na Maktaba Zinazohitajika
Mradi huu unatumia maktaba sawa na zile za mradi uliopita wa maandishi yanayotembea:
Adafruit NeoMatrixAdafruit NeoPixelAdafruit GFX Library
Sakinisha kupitia Meneja wa Maktaba:
- Fungua
Sketch > Include Library > Manage Libraries…. - Tafuta
Adafruit NeoMatrixna ubonyeze Install. - Kubali usakinishaji wa vitegemezi (
Adafruit GFXnaAdafruit NeoPixel).
Mara tu zikisakinishwa, unapaswa kuona skechi za mfano za NeoMatrix na NeoPixel chini ya File > Examples.
Njia Mbili za Wi-Fi katika Mradi 3
Dhana muhimu zaidi katika mradi huu ni kwamba ESP32 inaweza kufanya kazi katika njia mbili tofauti:
- Njia ya Kituo (STA) – ESP32 inaunganisha kwenye mtandao wako uliopo wa Wi-Fi wa nyumbani.
- Njia ya Kituo cha Ufikiaji (AP) – ESP32 inaunda mtandao wake wa Wi-Fi ikiwa Wi-Fi ya nyumbani haipatikani.
Njia zote mbili hutumia kiolesura kile kile cha wavuti: ukurasa wa HTML unaotolewa kutoka ESP32 yenyewe, ambapo unaweza kubadilisha maandishi, rangi, mwelekeo wa kutembea, na kasi.:contentReference[oaicite:3]{index=3}
Njia 1 – Unganisha kwenye Wi-Fi ya Nyumbani (Njia ya Kituo)
Katika njia ya Kituo, ESP32 inajiunga na mtandao wako wa Wi-Fi wa nyumbani au ofisini. Hii ndiyo njia inayopendekezwa wakati wowote router yako inapatikana kwa sababu:
- Simu yako na kompyuta tayari zimeunganishwa kwenye mtandao huo huo wa Wi-Fi.
- Unaweza kuelekeza kivinjari chako kwenye anwani ya IP ya ESP32 na kudhibiti maandishi kutoka kifaa chochote kwenye mtandao huo.
Katika sehemu ya mipangilio ya skechi, unatoa SSID na nenosiri lako la Wi-Fi:
// Vitambulisho vya Wi-Fi vya Nyumbani (Hali ya Kituo) const char* WIFI_SSID = "YourHomeWiFi"; const char* WIFI_PASS = "YourHomePassword";Baada ya bodi kuwasha, inajaribu kuunganisha kwenye WIFI_SSID. Ikifanikiwa, msimbo unachapisha anwani ya IP iliyopewa kwenye Serial Monitor, kwa mfano:
Connected to WiFi
IP address: 192.168.1.16
Ili kudhibiti maandishi:
- Hakikisha simu yako au PC imeunganishwa kwenye mtandao huo wa Wi-Fi (kwa mfano,
YourHomeWiFi). - Fungua kivinjari na ingiza anwani ya IP iliyochapishwa, kama vile
http://192.168.1.16/. - Ukurasa wa udhibiti utaonekana, ukikuruhusu kuandika maandishi, kuchagua rangi, kuchagua mwelekeo, na kurekebisha kasi ya kusogeza.
Njia ya 2 – Sehemu ya Kufikia Inayojitegemea (Hali ya AP)
Ikiwa ESP32 haiwezi kuunganisha kwenye Wi-Fi yako ya nyumbani (neno la siri lisilo sahihi, mtandao usiopatikana, au unatumia moduli nje), mchoro huo unarudi kiotomatiki kwenye hali ya Sehemu ya Kufikia. Katika hali ya AP, ESP32 yenyewe inakuwa hotspot ya Wi-Fi yenye jina lake la mtandao na neno la siri.
Katika mradi huu, mipangilio ya AP imewekwa kama ifuatavyo:
// Vitambulisho vya Sehemu ya Kufikia (AP) (hali ya mbadala)
const char* AP_SSID = "ESP32";
const char* AP_PASS = "password";
Wakati hali ya Kituo inashindwa, moduli inabadilika kwenye hali ya AP na kuanza kutangaza mtandao wa Wi-Fi unaoitwa ESP32. Ili kudhibiti matrix:
- Kwenye simu yako au kompyuta, fungua mipangilio ya Wi-Fi na uunganishe kwenye mtandao ESP32.
- Ingiza neno la siri password (kama ilivyofafanuliwa kwenye msimbo).
- Mara tu ukiunganishwa, fungua kivinjari na uende kwenye
http://192.168.4.1/(IP ya kawaida ya hali ya AP ya ESP32). - Ukurasa huo wa udhibiti unaonekana, ukikuruhusu kubadilisha maandishi, rangi, kasi, na mwelekeo.
Tabia hii ya mbadala inafanya mradi huu kuwa muhimu popote: nyumbani, kwenye maabara, au katika mazingira ya maonyesho ambapo hakuna router inayopatikana.
Mradi wa 3 – Mipangilio Kuu kwenye Msimbo
Mchoro kamili wa HTTP Text umepakiwa chini ya makala hii na tovuti. Hapa tunaandika tu chaguzi muhimu zaidi za usanidi ambazo kuna uwezekano utazibadilisha.
Mipangilio ya Wi-Fi na Sehemu ya Kufikia
Juu ya mchoro utapata sehemu ya usanidi wa Wi-Fi. Badilisha tu vitambulisho vya Kituo (Wi-Fi ya nyumbani); mipangilio ya AP kawaida huwekwa kama chaguo-msingi:
// ---------- MIPANGILIO YA WI-FI ----------
// Wi-Fi ya Nyumbani (Hali ya Kituo)
const char* WIFI_SSID = "YourHomeWiFi"; // weka SSID ya router yako hapa
const char* WIFI_PASS = "YourHomePassword"; // weka neno la siri la router yako hapa
// Sehemu ya Kufikia Mbadala (Hali ya AP)
const char* AP_SSID = "ESP32"; // jina la AP lililowekwa
const char* AP_PASS = "password"; // neno la siri la AP lililowekwa
Tabia:
- Ikiwa
WIFI_SSIDnaWIFI_PASSni sahihi na mtandao unapatikana → ESP32 inaunganisha kama kifaa cha kawaida cha Wi-Fi (Hali ya Kituo). - Ikiwa muunganisho unashindwa baada ya muda → ESP32 inaanzisha AP yake kwa kutumia
AP_SSIDnaAP_PASS.
Pini ya Matrix, Ukubwa, na Mwangaza
Mipangilio hii ni sawa na miradi ya awali:
// Usanidi wa Matrix
const int MATRIX_PIN = 14; // pini ya data ya matrix ya RGB
const int MATRIX_WIDTH = 8;
const int MATRIX_HEIGHT = 8;
// Mwangaza wa jumla wa onyesho (0–255)
uint8_t matrixBrightness = 40; // rekebisha kwa mazingira yako
Weka MATRIX_PIN kwenye 14 kwa bodi hii. Unaweza kuongeza matrixBrightness ikiwa unahitaji mwanga zaidi, lakini thamani za chini ni vizuri zaidi kwa kutazama karibu.
Maandishi ya Chaguo-Msingi na Mipangilio ya Kusogeza
Wakati bodi inawasha, inaonyesha ujumbe wa awali hadi ufungue ukurasa wa wavuti na uandike mpya. Unaweza kubadilisha maandishi ya chaguo-msingi kwenye usanidi:
// Ujumbe wa chaguo-msingi unaoonyeshwa wakati wa kuwasha
String currentText = "Robojax"; // badilisha kutoka kwenye UI ya wavuti baadaye
Tabia iliyobaki ya kusogeza inadhibitiwa na seti ya vigezo ambavyo vinasasishwa na kiolesura cha wavuti:
// Ucheleweshaji wa kusogeza kwa millisecond (chini = haraka)
int scrollDelayMs = 50;
// Mwelekeo wa kusogeza: 0=kushoto, 1=kulia, 2=juu, 3=chini
int scrollDirection = 0; // chaguo-msingi: sogeza kushoto
Ukurasa wa wavuti hutuma thamani mpya kulingana na uteuzi wa slider na kitufe. Kutoka upande wa Arduino, unahitaji tu kujua kwamba:
- Kupunguza
scrollDelayMskunafanya maandishi yasogee haraka. - Kuongeza
scrollDelayMskunafanya yasogee polepole. - Kubadilisha
scrollDirectionkunabadilisha kati ya njia za kusogeza kushoto, kulia, juu, au chini.
Rangi ya Maandishi (Inadhibitiwa kutoka kwenye Ukurasa wa Wavuti)
Rangi ya maandishi inadhibitiwa na thamani tatu za 0–255 (nyekundu, kijani, bluu). Zinasasishwa kila wakati unapochagua rangi mpya kwenye ukurasa wa wavuti:
// Rangi ya sasa ya maandishi (R, G, B)
uint8_t textRed = 255;
uint8_t textGreen = 255;
uint8_t textBlue = 255;
Unapochagua rangi kwenye kivinjari na kubofya Apply, ESP32 inachambua thamani za RGB na kusasisha vigezo hivi vitatu; maandishi hubadilisha rangi mara moja kwenye matrix. Katika video, tabia hii inaonyeshwa na mabadiliko mengi ya rangi, ikijumuisha mifano ya nyekundu, kijani na bluu.
Muhtasari
Mradi wa 3 unageuza ESP32-S3 RGB LED Matrix yako kuwa onyesho la maandishi lisilo na waya kabisa ambalo unaweza kudhibiti kwa kutumia kifaa chochote chenye kivinjari. Mchoro umeundwa kuwa imara:
- Kwanza inajaribu kuungana na Wi-Fi yako ya nyumbani kwa kutumia SSID na nenosiri uliloweka.
- Ikishindikana, inakuwa kiotomatiki eneo la ufikiaji lenye jina
ESP32na nenosiripassword. - Katika njia zote mbili, kufungua anwani sahihi ya IP kwenye kivinjari kunaonyesha ukurasa huo huo wa udhibiti wa maandishi, rangi, mwelekeo, na kasi.
Msimbo kamili wa HTTP Text unapatikana chini ya makala hii (hupakiwa kiotomatiki kwenye tovuti). Kwa mwongozo kamili wa hatua kwa hatua na onyesho la moja kwa moja la jinsi maandishi yanavyosasishwa kwa wakati halisi, hakikisha unatazama sehemu ya Mradi 3 ya video. Ikiwa ungependa kujenga mradi huo mwenyewe, unaweza pia kununua moduli ya ESP32-S3 RGB LED Matrix kwa kutumia viungo vya washirika vilivyoorodheshwa chini ya msimbo.
This tutorial is part of: Matrix ya LED ya ESP32-S3 RGB
- Mradi wa Matrix ya LED ya RGB ya ESP32-S3 1- Nukta ya Msingi
- Mradi wa Matrix ya LED ya RGB ya ESP32-S3 2 - Maandishi Yanayotembea
- Mradi wa ESP32-S3 RGB LED Matrix 4 - Nukta ya kuinamia
- Mradi wa Matrix ya LED ya RGB ya ESP32-S3 5 - Mshale daima juu
- Mchezo wa Cible wa Mradi wa Matrix ya LED ya RGB ya ESP32-S3 6
- Mradi wa Saa ya Matrix ya LED ya RGB ya ESP32-S3 Wi-Fi + NTP -1 Saa ya Msingi
- Mradi wa Saa ya Mtandao ya Matrix ya LED ya RGB ya ESP32-S3 - Saa 2 za rangi nyingi za Kuonyesha Muda na Tarehe
- Mradi wa Saa ya Mtandao ya Matrix ya LED ya RGB ya ESP32-S3 - Rangi 3 za Usiku na Tarehe
- Mradi wa Saa ya Mtandao ya Matrix ya LED ya RGB ya ESP32-S3 - Rangi 5 za Upinde wa mvua
- Mradi wa Saa ya Mtandao ya Matrix ya LED ya RGB ya ESP32-S3 - Rangi 4 za Nasibu
- 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();
}
}
Tänker att du kanske behöver
-
Amazon
-
eBay
-
AliExpressPurchase ESP32-S3 RGB Matrix from AliExpresss.click.aliexpress.com
-
AliExpressPurchase ESP32-S3 RGB Matrix from AliExpress (2)s.click.aliexpress.com
Resurser och referenser
-
Interna🎨 Color picker Toolrobojax.com
Filer📁
Fritzing-fil
-
esp32-S3-supermini-tht fritzing part
esp32-S3-supermini-tht.fzpz0.02 MB