Овој туторијал е дел од: ESP32-S3 RGB LED матрица
Одличен проект за креирање за забавни и практични апликации со користење на ESP32-S3 RGB Matrix модулот. Линкови до други видеа се наоѓаат под оваа статија.
Проект 3 со RGB LED матрица на ESP32-S3 - Текст од мобилен телефон
Проект 3 – Контролна матрица со текст од вашиот телефон (HTTP текст)
Во овој проект, ESP32-S3 RGB LED матрицата води мала веб-страница, така што можете да го менувате лизгачкиот текст, бојата, насоката и брзината директно од вашиот телефон или компјутер. Не ви треба посебна апликација – само веб-прелистувач. Ова го прави модулот мал Wi-Fi текстуален дисплеј што можете да го ажурирате во реално време.
Сите шест проекти во оваа серија се објаснети и демонстрирани во едно YouTube видео. Истото видео е вградено на оваа страница, за да можете точно да видите како изгледа веб-интерфејсот и како текстот веднаш се ажурира на матрицата. Целосниот изворен код за овој проект автоматски се вчитува под статијата, а можете да го купите ESP32-S3 RGB LED матрица модулот од партнерските продавници наведени под делот со кодот.
Во оваа статија се фокусираме на тоа како функционира мрежната логика (домашен Wi-Fi наспроти пристапна точка) и кои поставки можете да ги менувате во кодот за да го прилагодите однесувањето.



Преглед на ESP32-S3 RGB LED матрица модулот
Хардверот е ист како за сите други проекти во оваа серија: ESP32-S3 микроконтролерска плоча со вградена 8×8 RGB LED матрица и QMI8658C сензор за движење на задната страна. USB-C портата се користи за напојување и програмирање, а пиновите на рабовите се сè уште достапни за други влезно-излезни функции.:contentReference[oaicite:0]{index=0}

- ESP32-S3 – микроконтролер со Wi-Fi и Bluetooth способности.
- 8×8 RGB матрица – 64 адресирани RGB LED диоди за текст и графика.
- QMI8658C акцелерометар – се користи во проектите за навалување и игри.
- USB порта – ја напојува плочата и поставува скици од Arduino IDE.
- Изложени пинови – овозможуваат дополнителни сензори или актуатори доколку е потребно.
- Boot/Reset копчиња – за поставување фирмвер и рестартирање.
За Проект 3, најважната карактеристика е Wi-Fi на ESP32, кој овозможува плочата да дејствува како мал веб-сервер за страницата за контрола на текстот.:contentReference[oaicite:1]{index=1}

Проекти покриени во видеото (временски ознаки)
Едното видео за оваа серија ги покрива сите шест проекти. За брза референца:
- 00:00 – Вовед
- 02:01 – Инсталирање на ESP32 плочи
- 03:32 – Инсталирање библиотеки
- 05:32 – Проект 1: Подвижна точка
- 11:11 – Проект 2: Лизгање текст
- 12:59 – Проект 3: HTTP текст (овој проект)
- 16:41 – Проект 4: Точка со навалување
- 18:55 – Проект 5: Стрелка нагоре
- 20:02 – Проект 6: Игра цел
Ве охрабруваме да го гледате делот за HTTP текст во видеото додека работите со оваа статија. Видеото покажува како веб-страницата се генерира од ESP32 и како промената на текстот, бојата и брзината веднаш се одразува на LED матрицата.:contentReference[oaicite:2]{index=2}
Инсталирање на ESP32 плочи во Arduino IDE
Ако веќе сте ги завршиле Проектите 1 или 2, поставувањето на плочата е готово и можете да го прескокнете овој дел. Во спротивно, следете ги овие чекори во Arduino IDE:
- Отворете
File > Preferencesи додајте ја URL-адресата за ESP32 плочи во „Additional Boards Manager URLs”. - Одете на
Tools > Board > Boards Manager…, пребарајтеESP32и инсталирајте го официјалниот ESP32 пакет. - Изберете ја точната ESP32-S3 RGB Matrix плоча од
Tools > Board. - Поврзете го модулот преку USB и изберете ја точната сериска порта под
Tools > Port.
Без соодветна поддршка за ESP32 плочи и точна порта, скицата за веб-серверот нема да се постави.
Инсталирање на NeoMatrix и потребните библиотеки
Овој проект ги користи истите библиотеки како претходниот проект за лизгање текст:
Adafruit NeoMatrixAdafruit NeoPixelAdafruit GFX Library
Инсталирајте преку Library Manager:
- Отворете
Sketch > Include Library > Manage Libraries…. - Пребарајте
Adafruit NeoMatrixи кликнете Install. - Прифатете ја инсталацијата на зависностите (
Adafruit GFXиAdafruit NeoPixel).
Откако ќе се инсталираат, треба да ги видите пример-скиците NeoMatrix и NeoPixel под File > Examples.
Два Wi-Fi режими во Проект 3
Најважниот концепт во овој проект е дека ESP32 може да работи во два различни режими:
- Station (STA) режим – ESP32 се поврзува на вашата постоечка домашна Wi-Fi мрежа.
- Access Point (AP) режим – ESP32 создава своја Wi-Fi мрежа ако домашниот Wi-Fi не е достапен.
Двата режима ја користат истата веб-интерфејс: HTML страница сервирана од самиот ESP32, каде што можете да го менувате текстот, бојата, насоката на лизгање и брзината.:contentReference[oaicite:3]{index=3}
Режим 1 – Поврзување на домашен Wi-Fi (Station режим)
Во Station режим, ESP32 се приклучува на вашата домашна или канцелариска Wi-Fi мрежа. Ова е претпочитан режим секогаш кога вашиот рутер е достапен затоа што:
- Вашиот телефон и компјутер се веќе поврзани на истата Wi-Fi мрежа.
- Можете да го насочите вашиот прелистувач кон IP адресата на ESP32 и да го контролирате текстот од кој било уред на таа мрежа.
Во делот за поставки на скицата, ги внесувате вашите Wi-Fi SSID и лозинка:
// Домашни Wi-Fi акредитиви (Station режим) const char* WIFI_SSID = "YourHomeWiFi"; const char* WIFI_PASS = "YourHomePassword";Откако плочката ќе се подигне, таа се обидува да се поврзе на WIFI_SSID. Ако е успешно, кодот ја печати доделената IP адреса на Serial Monitor, на пример:
Connected to WiFi
IP address: 192.168.1.16
За да го контролирате текстот:
- Проверете дали вашиот телефон или компјутер е поврзан на истата Wi-Fi мрежа (на пример,
YourHomeWiFi). - Отворете прелистувач и внесете ја испечатената IP адреса, како што е
http://192.168.1.16/. - Ќе се појави контролната страница, која ви овозможува да внесете текст, да изберете боја, да изберете насока и да ја прилагодите брзината на движење.
Режим 2 – Самостоен пристапен пункт (AP режим)
Ако ESP32 не може да се поврзе на вашиот домашен Wi-Fi (погрешна лозинка, мрежата не е достапна или го користите модулот надвор), скицата автоматски се префрла во режим на пристапен пункт. Во AP режим, самиот ESP32 станува Wi-Fi жариште со сопствено име на мрежа и лозинка.
Во овој проект, AP поставките се фиксни:
// Access Point (AP) акредитиви (резервен режим)
const char* AP_SSID = "ESP32";
const char* AP_PASS = "password";
Кога режимот Station ќе пропадне, модулот се префрла во AP режим и започнува да емитува Wi-Fi мрежа наречена ESP32. За да ја контролирате матрицата:
- На вашиот телефон или компјутер, отворете ги Wi-Fi поставките и поврзете се на мрежата ESP32.
- Внесете ја лозинката password (како што е дефинирано во кодот).
- Откако ќе се поврзете, отворете прелистувач и одете на
http://192.168.4.1/(стандардната IP адреса за ESP32 AP режим). - Ќе се појави истата контролна страница, која ви овозможува да го менувате текстот, бојата, брзината и насоката.
Ова однесување со резервен режим го прави проектот корисен насекаде: дома, во лабораторија или во демо опкружување каде што нема достапен рутер.
Проект 3 – Главни поставки во кодот
Целосната HTTP Text скица е вчитана под овој напис од веб-сајтот. Овде ги документираме само најважните опции за конфигурација што најверојатно ќе ги уредувате.
Wi-Fi и поставки за пристапен пункт
На врвот на скицата ќе го најдете делот за Wi-Fi конфигурација. Променете ги само акредитивите за Station (домашен Wi-Fi); AP поставките обично се задржуваат како стандардни:
// ---------- Wi-Fi ПОСТАВКИ ----------
// Домашен Wi-Fi (Station режим)
const char* WIFI_SSID = "YourHomeWiFi"; // внесете го SSID на вашиот рутер овде
const char* WIFI_PASS = "YourHomePassword"; // внесете ја лозинката на вашиот рутер овде
// Резервен пристапен пункт (AP режим)
const char* AP_SSID = "ESP32"; // фиксно име на AP
const char* AP_PASS = "password"; // фиксна лозинка на AP
Однесување:
- Ако
WIFI_SSIDиWIFI_PASSсе точни и мрежата е достапна → ESP32 се поврзува како нормален Wi-Fi уред (Station режим). - Ако поврзувањето пропадне по одредено време → ESP32 започнува сопствен AP користејќи ги
AP_SSIDиAP_PASS.
Пин на матрицата, големина и осветленост
Овие поставки се исти како кај претходните проекти:
// Конфигурација на матрицата
const int MATRIX_PIN = 14; // пин за податоци на RGB матрицата
const int MATRIX_WIDTH = 8;
const int MATRIX_HEIGHT = 8;
// Вкупна осветленост на екранот (0–255)
uint8_t matrixBrightness = 40; // прилагодете за вашата околина
Задржете го MATRIX_PIN на 14 за оваа плочка. Можете да го зголемите matrixBrightness ако ви треба повеќе светлина, но пониските вредности се поудобни за гледање одблиску.
Стандарден текст и поставки за движење
Кога плочката ќе се стартува, таа прикажува почетна порака додека не ја отворите веб-страницата и не внесете нова. Можете да го промените стандардниот текст во конфигурацијата:
// Стандардна порака прикажана при стартување
String currentText = "Robojax"; // подоцна се препишува од веб-интерфејсот
Остатокот од однесувањето на движењето е контролирано од сет на променливи што се ажурираат преку веб-интерфејсот:
// Доцнење на движењето во милисекунди (пониско = побрзо)
int scrollDelayMs = 50;
// Насока на движење: 0=лево, 1=десно, 2=горе, 3=долу
int scrollDirection = 0; // стандардно: движење налево
Веб-страницата испраќа нови вредности врз основа на изборите на лизгачот и копчињата. Од страната на Arduino, само треба да знаете дека:
- Намалувањето на
scrollDelayMsго прави текстот да се движи побрзо. - Зголемувањето на
scrollDelayMsго прави да се движи побавно. - Промената на
scrollDirectionпрефрла помеѓу режимите на движење налево, надесно, нагоре или надолу.
Боја на текстот (контролирана од веб-страницата)
Бојата на текстот е контролирана од три вредности од 0–255 (црвена, зелена, сина). Тие се ажурираат секогаш кога ќе изберете нова боја на веб-страницата:
// Тековна боја на текстот (R, G, B)
uint8_t textRed = 255;
uint8_t textGreen = 255;
uint8_t textBlue = 255;
Кога ќе изберете боја во прелистувачот и ќе кликнете Apply, ESP32 ги парсира RGB вредностите и ги ажурира овие три променливи; текстот веднаш ја менува бојата на матрицата. Во видеото, ова однесување е демонстрирано со повеќе промени на бои, вклучувајќи примери со црвена, зелена и сина боја.
Резиме
Проектот 3 ја претвора вашата ESP32-S3 RGB LED матрица во целосно безжичен текстуален екран што можете да го контролирате со кој било уред што има веб-прелистувач. Скицата е дизајнирана да биде робусна:
- Прво се обидува да се поврзе со вашата домашна Wi-Fi мрежа користејќи го SSID-от и лозинката што сте ги конфигурирале.
- Ако тоа не успее, автоматски станува пристапна точка со име
ESP32и лозинкаpassword. - Во двата режима, отворањето на точната IP адреса во прелистувач прикажува иста контролна страница за текст, боја, насока и брзина.
Целосниот HTTP текст код е достапен под оваа статија (се вчитува автоматски на веб-страницата). За целосно чекор-по-чекор објаснување и live демонстрација за тоа како текстот се ажурира во реално време, задолжително погледнете го делот Project 3 од видеото. Ако сакате сами да го изградите проектот, можете да го купите и ESP32-S3 RGB LED Matrix модулот користејќи ги affiliate линковите наведени под кодот.
Овој туторијал е дел од: ESP32-S3 RGB LED матрица
- ESP32-S3 RGB LED матричен проект 1 - Основна точка
- ESP32-S3 RGB LED матричен проект 2 - Лизгачки текст
- Проект 4 со RGB LED матрица на ESP32-S3 - Тилт точка
- ESP32-S3 RGB LED матричен проект 5 - Стрелка секогаш нагоре
- ESP32-S3 RGB LED матрица проект 6 - Игра „Цел“
- ESP32-S3 RGB LED матрица Wi-Fi + NTP часовник проект -1 Основен часовник
- Проект за интернет часовник со RGB LED матрица базиран на ESP32-S3 - 2 часовници со повеќебоен приказ на време и датум
- ESP32-S3 RGB LED матричен интернет часовник проект - 3 ноќни бои со датум
- Проект за интернет часовник со RGB LED матрица базиран на ESP32-S3 - 5 виножито боја
- Проект за интернет часовник со RGB LED матрица базиран на ESP32-S3 - 4 случајни бои
- 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();
}
}
Работи што можеби ќе ви требаат
-
Amazon
-
eBay
-
AliExpressPurchase ESP32-S3 RGB matrix from AliExpresss.click.aliexpress.com
-
AliExpressPurchase ESP32-S3 RGB matrix from AliExpress (2)s.click.aliexpress.com
Ресурси и референци
-
Внатрешно🎨 Color picker Toolrobojax.com
Датотеки📁
Fritzing датотека
-
esp32-S3-supermini-tht fritzing part
esp32-S3-supermini-tht.fzpz0.02 MB