Tutorial ini adalah bagian dari: Matriks LED RGB ESP32-S3
Proyek keren untuk dibuat untuk bersenang-senang dan aplikasi praktis menggunakan modul matriks RGB ESP32-S3. Tautan ke video lain ada di bawah artikel ini.
Proyek Matriks LED RGB ESP32-S3 3 - Teks dari ponsel
Proyek 3 – Kontrol Teks Matriks dari Ponsel Anda (HTTP Text)
Pada proyek ini, Matriks LED RGB ESP32-S3 menghosting halaman web kecil sehingga Anda dapat mengubah teks berjalan, warna, arah, dan kecepatan langsung dari ponsel atau komputer Anda. Anda tidak memerlukan aplikasi terpisah – cukup browser web. Ini menjadikan modul ini tampilan teks Wi-Fi kecil yang dapat Anda perbarui secara real time.
Keenam proyek dalam seri ini dijelaskan dan didemonstrasikan dalam satu video YouTube. Video yang sama disematkan di halaman ini, sehingga Anda dapat melihat dengan tepat bagaimana antarmuka web terlihat dan bagaimana teks diperbarui secara instan di matriks. Kode sumber lengkap untuk proyek ini dimuat secara otomatis di bawah artikel, dan Anda dapat membeli modul Matriks LED RGB ESP32-S3 dari toko afiliasi yang tercantum di bawah bagian kode.
Dalam artikel ini kami fokus pada cara kerja logika jaringan (Wi-Fi rumah vs titik akses) dan pengaturan apa yang dapat Anda ubah dalam kode untuk menyesuaikan perilaku.



Ikhtisar Modul Matriks LED RGB ESP32-S3
Perangkat kerasnya sama dengan semua proyek lain dalam seri ini: papan mikrokontroler ESP32-S3 dengan matriks LED RGB 8×8 bawaan dan sensor gerak QMI8658C di bagian belakang. Port USB-C digunakan untuk daya dan pemrograman, dan pin di sekitar tepi masih tersedia untuk IO lainnya.:contentReference[oaicite:0]{index=0}

- ESP32-S3 – mikrokontroler yang mampu Wi-Fi dan Bluetooth.
- Matriks RGB 8×8 – 64 LED RGB yang dapat dialamatkan untuk teks dan grafis.
- Akselerometer QMI8658C – digunakan dalam proyek kemiringan dan permainan.
- Port USB – memberi daya pada papan dan mengunggah sketsa dari Arduino IDE.
- Pin yang terbuka – memungkinkan sensor atau aktuator tambahan jika diperlukan.
- Tombol Boot/Reset – untuk unggahan firmware dan memulai ulang.
Untuk Proyek 3, fitur terpenting adalah Wi-Fi ESP32, yang memungkinkan papan bertindak sebagai server web kecil untuk halaman kontrol teks.:contentReference[oaicite:1]{index=1}

Proyek yang Dicakup dalam Video (Stempel Waktu)
Satu video untuk seri ini mencakup keenam proyek. Untuk referensi cepat:
- 00:00 – Pendahuluan
- 02:01 – Menginstal papan ESP32
- 03:32 – Menginstal pustaka
- 05:32 – Proyek 1: Titik Bergerak
- 11:11 – Proyek 2: Gulir Teks
- 12:59 – Proyek 3: HTTP Text (proyek ini)
- 16:41 – Proyek 4: Titik Kemiringan
- 18:55 – Proyek 5: Panah ke Atas
- 20:02 – Proyek 6: Permainan Target
Anda disarankan untuk menonton bagian HTTP Text dalam video sambil mengerjakan artikel ini. Video menunjukkan bagaimana halaman web dihasilkan oleh ESP32 dan bagaimana perubahan teks, warna, dan kecepatan tercermin secara instan pada matriks LED.:contentReference[oaicite:2]{index=2}
Menginstal Papan ESP32 di Arduino IDE
Jika Anda telah menyelesaikan Proyek 1 atau 2, pengaturan papan sudah selesai dan Anda dapat melewati bagian ini. Jika tidak, ikuti langkah-langkah berikut di Arduino IDE:
- Buka
File > Preferencesdan tambahkan URL papan ESP32 ke “Additional Boards Manager URLs”. - Buka
Tools > Board > Boards Manager…, cariESP32, dan instal paket ESP32 resmi. - Pilih papan Matriks RGB ESP32-S3 yang benar dari
Tools > Board. - Hubungkan modul melalui USB dan pilih port serial yang benar di bawah
Tools > Port.
Tanpa dukungan papan ESP32 yang tepat dan port yang benar, sketsa server web tidak akan terunggah.
Menginstal NeoMatrix dan Pustaka yang Diperlukan
Proyek ini menggunakan pustaka yang sama dengan proyek gulir teks sebelumnya:
Adafruit NeoMatrixAdafruit NeoPixelAdafruit GFX Library
Instal melalui Library Manager:
- Buka
Sketch > Include Library > Manage Libraries…. - Cari
Adafruit NeoMatrixdan klik Install. - Terima instalasi dependensi (
Adafruit GFXdanAdafruit NeoPixel).
Setelah terinstal, Anda akan melihat contoh sketsa NeoMatrix dan NeoPixel di bawah File > Examples.
Dua Mode Wi-Fi dalam Proyek 3
Konsep terpenting dalam proyek ini adalah ESP32 dapat bekerja dalam dua mode berbeda:
- Mode Station (STA) – ESP32 terhubung ke jaringan Wi-Fi rumah Anda yang sudah ada.
- Mode Access Point (AP) – ESP32 membuat jaringan Wi-Fi sendiri jika Wi-Fi rumah tidak tersedia.
Kedua mode menggunakan antarmuka web yang sama: halaman HTML yang disajikan dari ESP32 itu sendiri, di mana Anda dapat mengubah teks, warna, arah gulir, dan kecepatan.:contentReference[oaicite:3]{index=3}
Mode 1 – Terhubung ke Wi-Fi Rumah (Mode Station)
Dalam mode Station, ESP32 bergabung dengan jaringan Wi-Fi rumah atau kantor Anda. Ini adalah mode yang disukai setiap kali router Anda tersedia karena:
- Ponsel dan komputer Anda sudah terhubung ke jaringan Wi-Fi yang sama.
- Anda dapat mengarahkan browser ke alamat IP ESP32 dan mengontrol teks dari perangkat mana pun di jaringan tersebut.
Di bagian pengaturan sketsa, Anda memberikan SSID dan kata sandi Wi-Fi Anda:
// Kredensial Wi-Fi rumah (Mode Station) const char* WIFI_SSID = "YourHomeWiFi"; const char* WIFI_PASS = "YourHomePassword";Setelah board melakukan boot, ia mencoba terhubung ke WIFI_SSID. Jika berhasil, kode mencetak alamat IP yang ditetapkan ke Serial Monitor, misalnya:
Connected to WiFi
IP address: 192.168.1.16
Untuk mengontrol teks:
- Pastikan ponsel atau PC Anda terhubung ke jaringan Wi-Fi yang sama (misalnya,
YourHomeWiFi). - Buka browser dan masukkan alamat IP yang dicetak, seperti
http://192.168.1.16/. - Halaman kontrol akan muncul, memungkinkan Anda mengetik teks, memilih warna, memilih arah, dan menyesuaikan kecepatan gulir.
Mode 2 – Access Point Mandiri (Mode AP)
Jika ESP32 tidak dapat terhubung ke Wi-Fi rumah Anda (salah kata sandi, jaringan tidak tersedia, atau Anda menggunakan modul di luar ruangan), sketsa secara otomatis beralih ke mode Access Point. Dalam mode AP, ESP32 itu sendiri menjadi hotspot Wi-Fi dengan nama jaringan dan kata sandi sendiri.
Dalam proyek ini, pengaturan AP ditetapkan sebagai:
// Kredensial Access Point (AP) (mode cadangan)
const char* AP_SSID = "ESP32";
const char* AP_PASS = "password";
Ketika mode Station gagal, modul beralih ke mode AP dan mulai menyiarkan jaringan Wi-Fi bernama ESP32. Untuk mengontrol matriks:
- Di ponsel atau komputer Anda, buka pengaturan Wi-Fi dan sambungkan ke jaringan ESP32.
- Masukkan kata sandi password (seperti yang didefinisikan dalam kode).
- Setelah terhubung, buka browser dan pergi ke
http://192.168.4.1/(IP default untuk mode AP ESP32). - Halaman kontrol yang sama muncul, memungkinkan Anda mengubah teks, warna, kecepatan, dan arah.
Perilaku cadangan ini membuat proyek berguna di mana saja: di rumah, di laboratorium, atau di lingkungan demo di mana tidak ada router yang tersedia.
Proyek 3 – Pengaturan Utama dalam Kode
Sketsa HTTP Text lengkap dimuat di bawah artikel ini oleh situs web. Di sini kami hanya mendokumentasikan opsi konfigurasi paling penting yang mungkin Anda edit.
Pengaturan Wi-Fi dan Access Point
Di bagian atas sketsa, Anda akan menemukan bagian konfigurasi Wi-Fi. Hanya ubah kredensial Station (Wi-Fi rumah); pengaturan AP biasanya dipertahankan sebagai default:
// ---------- PENGATURAN WI-FI ----------
// Wi-Fi rumah (Mode Station)
const char* WIFI_SSID = "YourHomeWiFi"; // letakkan SSID router Anda di sini
const char* WIFI_PASS = "YourHomePassword"; // letakkan kata sandi router Anda di sini
// Access Point cadangan (Mode AP)
const char* AP_SSID = "ESP32"; // nama AP tetap
const char* AP_PASS = "password"; // kata sandi AP tetap
Perilaku:
- Jika
WIFI_SSIDdanWIFI_PASSbenar dan jaringan tersedia → ESP32 terhubung sebagai perangkat Wi-Fi normal (Mode Station). - Jika koneksi gagal setelah waktu tunggu → ESP32 memulai AP sendiri menggunakan
AP_SSIDdanAP_PASS.
Pin Matriks, Ukuran, dan Kecerahan
Pengaturan ini sama dengan proyek sebelumnya:
// Konfigurasi matriks
const int MATRIX_PIN = 14; // pin data matriks RGB
const int MATRIX_WIDTH = 8;
const int MATRIX_HEIGHT = 8;
// Kecerahan tampilan keseluruhan (0–255)
uint8_t matrixBrightness = 40; // sesuaikan untuk lingkungan Anda
Pertahankan MATRIX_PIN pada 14 untuk board ini. Anda dapat meningkatkan matrixBrightness jika membutuhkan lebih banyak cahaya, tetapi nilai yang lebih rendah lebih nyaman untuk melihat dari dekat.
Teks Default dan Pengaturan Gulir
Ketika board dimulai, ia menampilkan pesan awal sampai Anda membuka halaman web dan mengetik yang baru. Anda dapat mengubah teks default dalam konfigurasi:
// Pesan default yang ditampilkan saat startup
String currentText = "Robojax"; // ditimpa dari UI web nanti
Sisa perilaku gulir dikendalikan oleh serangkaian variabel yang diperbarui oleh antarmuka web:
// Penundaan gulir dalam milidetik (lebih rendah = lebih cepat)
int scrollDelayMs = 50;
// Arah gulir: 0=kiri, 1=kanan, 2=atas, 3=bawah
int scrollDirection = 0; // default: gulir ke kiri
Halaman web mengirim nilai baru berdasarkan pilihan slider dan tombol. Dari sisi Arduino, Anda hanya perlu tahu bahwa:
- Mengurangi
scrollDelayMsmembuat teks bergerak lebih cepat. - Meningkatkan
scrollDelayMsmembuatnya bergerak lebih lambat. - Mengubah
scrollDirectionberalih antara mode gulir kiri, kanan, atas, atau bawah.
Warna Teks (Dikendalikan dari Halaman Web)
Warna teks dikendalikan oleh tiga nilai 0–255 (merah, hijau, biru). Nilai-nilai ini diperbarui setiap kali Anda memilih warna baru di halaman web:
// Warna teks saat ini (R, G, B)
uint8_t textRed = 255;
uint8_t textGreen = 255;
uint8_t textBlue = 255;
Ketika Anda memilih warna di browser dan klik Terapkan, ESP32 mengurai nilai RGB dan memperbarui tiga variabel ini; teks segera berubah warna di matriks. Dalam video, perilaku ini didemonstrasikan dengan beberapa perubahan warna, termasuk contoh merah, hijau, dan biru.
Ringkasan
Proyek 3 mengubah ESP32-S3 RGB LED Matrix Anda menjadi tampilan teks sepenuhnya nirkabel yang dapat Anda kontrol menggunakan perangkat apa pun dengan browser web. Sketsa dirancang untuk menjadi kuat:
- Pertama-tama, perangkat mencoba terhubung ke Wi-Fi rumah Anda menggunakan SSID dan kata sandi yang telah Anda konfigurasi.
- Jika gagal, perangkat secara otomatis menjadi titik akses dengan nama
ESP32dan kata sandipassword. - Dalam kedua mode, membuka alamat IP yang benar di browser akan menampilkan halaman kontrol yang sama untuk teks, warna, arah, dan kecepatan.
Kode HTTP Text lengkap tersedia di bawah artikel ini (dimuat secara otomatis di situs web). Untuk panduan langkah demi langkah yang lengkap dan demonstrasi langsung tentang bagaimana teks diperbarui secara real time, pastikan untuk menonton bagian Project 3 dari video tersebut. Jika Anda ingin membangun proyek ini sendiri, Anda juga dapat membeli modul ESP32-S3 RGB LED Matrix menggunakan tautan afiliasi yang tercantum di bawah kode.
Tutorial ini adalah bagian dari: Matriks LED RGB ESP32-S3
- Proyek Matriks LED RGB ESP32-S3 1- Titik Dasar
- Proyek Matriks LED RGB ESP32-S3 2 - Teks Berjalan
- Proyek Matriks LED RGB ESP32-S3 4 - Titik miring
- Proyek Matriks LED RGB ESP32-S3 5 - Panah selalu ke atas
- Proyek Matriks LED RGB ESP32-S3 6 - Permainan Cible
- Proyek Jam Wi-Fi + NTP dengan Matriks LED RGB ESP32-S3 -1 Jam Dasar
- Proyek Jam Internet Matriks LED RGB ESP32-S3 - 2 Jam Tampilan Waktu & Tanggal Multi Warna
- Proyek Jam Internet Matriks LED RGB ESP32-S3 - 3 Warna Malam dengan Tanggal
- Proyek Jam Internet Matriks LED RGB ESP32-S3 - 5 Warna Pelangi
- Proyek Jam Internet Matriks LED RGB ESP32-S3 - 4 Warna acak
- 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();
}
}
Hal-hal yang mungkin Anda butuhkan
-
Amazon
-
eBay
-
AliExpressPurchase ESP32-S3 RGB Matrix from AliExpresss.click.aliexpress.com
-
AliExpressPurchase ESP32-S3 RGB Matrix from AliExpress (2)s.click.aliexpress.com
Sumber daya & referensi
-
Internal🎨 Color picker Toolrobojax.com
Berkas📁
File Fritzing
-
esp32-S3-supermini-tht fritzing part
esp32-S3-supermini-tht.fzpz0.02 MB