De reden van deze opzet is dat er voor de door mij gebruikte HUB08 Panelen geen libraries bestaan voor ESP chips (zelfs chatgpt wist geen raad ! )
Arduino dient voor opbouw van display : 2 zones of 4 zones.
WiFi / MQTT
ESP32 Wifi en data voor display ! Settings IP MQTT server en MQTT Topics Helderheid
|
UART (Serial) MQTT Topics / 2 of 4 lijnen / en helderheid van display
|
Arduino UNO Dient enkel voor aansturing van de display.
|
HUB08 16×64 LED Display die je nooit moet kopen alleen aanstuurbaar door Uno
ESP32 UNO
TX2 (GPIO17) RX (D0)
RX2 (GPIO16) TX (D1)
GND GND
⚠️ UNO loskoppelen van USB bij upload ESP32
⚠️ Baudrate = 115200
Display +5V → externe voeding
Display GND → voeding GND
Arduino GND → zelfde GND
Als GND niet gedeeld is → werkt niks / rare fouten
Board: Arduino Nano
Processor: ATmega328P (Old Bootloader) (vaak nodig)
Baudrate: 115200
Variabele data via Web UI instellen.
WIFI / MQTT server / opbouw display 2 of 4 lijnen
MQTT Topics per bericht instellen
WEB UI, Eertste keer toegang via AP van de ESP32 chip gebruiken, Zoek in je wifi naar "ESP32-setup" inloggen zonder wachtwoord.
naar browser 192.168.4.1 gaan en daar je eigen wifi instellen !
Libs nodig voor ESP32
#include <WiFi.h>
#include <PubSubClient.h>
#include <WebServer.h>
#include <Preferences.h>
Libs nodig voor Uno
#include <SPI.h>
#include "HUB08SPI.h"
#include "TimerOne.h"
#include "Buffer.h"
#include "ronnAnimation.h"
#include <SPI.h>
#include "HUB08SPI.h"
#include "TimerOne.h"
#include "Buffer.h"
#define WIDTH 64
#define HEIGHT 16
uint8_t displaybuf[WIDTH * HEIGHT / 8];
Buffer buff(displaybuf, WIDTH, HEIGHT);
HUB08SPI display;
// MOET NA Buffer
#include "ronnAnimation.h"
/* ===== TEKST ===== */
String line1 = "1";
String line2 = "2";
String line3 = "3";
String line4 = "4";
String ipText = "";
/* ===== INSTELLINGEN ===== */
int brightness = 100;
int zoneMode = 4;
/* ===== STATES ===== */
bool showIP = true; // start met Waiting IP
bool needsRedraw = true;
unsigned long ipShownAt = 0;
const unsigned long ipShowTime = 2000;
/* ===== REFRESH ISR ===== */
void refresh() {
display.scan();
}
/* ================================================= */
void setup() {
Serial.begin(115200);
display.begin(displaybuf, WIDTH, HEIGHT);
Timer1.initialize(100);
Timer1.attachInterrupt(refresh);
display.setBrightness(brightness);
buff.clear();
ronn.setFont();
ronn.printText("Arduino Uno", 0, 0);
ronn.printText("Boot OK", 0, 8);
delay(1000);
// Waiting IP
ipText = "Waiting IP";
showIP = true;
needsRedraw = true;
}
/* ================================================= */
void loop() {
/* ===== SERIAL ===== */
if (Serial.available()) {
String cmd = Serial.readStringUntil('\n');
cmd.trim();
if (cmd == "CLR") {
buff.clear();
needsRedraw = true;
return;
}
if (cmd.startsWith("BR:")) {
brightness = constrain(cmd.substring(3).toInt(), 0, 255);
display.setBrightness(brightness);
return;
}
if (cmd.startsWith("ZONES:")) {
zoneMode = cmd.substring(6).toInt();
if (zoneMode == 1) zoneMode = 2;
needsRedraw = true;
return;
}
if (cmd.startsWith("IP:")) {
ipText = cmd.substring(3);
showIP = true;
ipShownAt = millis();
needsRedraw = true;
return;
}
if (cmd.startsWith("L1:")) { line1 = cmd.substring(3); needsRedraw = true; }
if (cmd.startsWith("L2:")) { line2 = cmd.substring(3); needsRedraw = true; }
if (cmd.startsWith("L3:")) { line3 = cmd.substring(3); needsRedraw = true; }
if (cmd.startsWith("L4:")) { line4 = cmd.substring(3); needsRedraw = true; }
}
/* ===== IP TIMEOUT ===== */
if (showIP && ipText != "Waiting IP") {
if (millis() - ipShownAt > ipShowTime) {
showIP = false;
needsRedraw = true;
}
}
/* ===== REDRAW ===== */
if (!needsRedraw) return;
needsRedraw = false;
buff.clear();
ronn.setFont();
if (showIP) {
if (ipText == "Waiting IP") {
ronn.printText("Waiting IP", 0, 4);
} else {
ronn.printText("IP:", 0, 0);
ronn.printText(ipText, 0, 8);
}
return;
}
// NORMALE DISPLAY
if (zoneMode == 2) {
ronn.printText(line1, 0, 0);
ronn.printText(line2, 0, 8);
} else {
ronn.printText(line1, 0, 0);
ronn.printText(line2, 32, 0);
ronn.printText(line3, 0, 8);
ronn.printText(line4, 32, 8);
}
}
#include <WiFi.h>
#include <PubSubClient.h>
#include <WebServer.h>
#include <Preferences.h>
/* ========= OBJECTEN ========= */
WiFiClient espClient;
PubSubClient client(espClient);
WebServer server(80);
Preferences prefs;
/* ========= WIFI ========= */
String wifi_ssid;
String wifi_pass;
/* ========= MQTT ========= */
String mqtt_server;
String mqtt_user;
String mqtt_pass;
int mqtt_port = 1883;
/* ========= TOPICS & LABELS ========= */
String topicLine1, topicLine2, topicLine3, topicLine4;
String labelLine1, labelLine2, labelLine3, labelLine4;
/* ========= DISPLAY ========= */
int displayBrightness = 180;
int zoneMode = 4;
/* ========================================================= */
/* ======================= MQTT CALLBACK =================== */
/* ========================================================= */
void callback(char* topic, byte* payload, unsigned int length) {
String msg;
for (unsigned int i = 0; i < length; i++) msg += (char)payload[i];
if (zoneMode == 4) {
if (strcmp(topic, topicLine1.c_str()) == 0)
Serial2.println("L1:" + labelLine1 + " " + msg);
else if (strcmp(topic, topicLine2.c_str()) == 0)
Serial2.println("L2:" + labelLine2 + " " + msg);
else if (strcmp(topic, topicLine3.c_str()) == 0)
Serial2.println("L3:" + labelLine3 + " " + msg);
else if (strcmp(topic, topicLine4.c_str()) == 0)
Serial2.println("L4:" + labelLine4 + " " + msg);
} else {
if (strcmp(topic, topicLine1.c_str()) == 0)
Serial2.println("L1:" + labelLine1 + " " + msg);
else if (strcmp(topic, topicLine2.c_str()) == 0)
Serial2.println("L2:" + labelLine2 + " " + msg);
}
}
/* ========================================================= */
/* ======================= SETTINGS ======================== */
/* ========================================================= */
void loadSettings() {
wifi_ssid = prefs.getString("w_ssid", "");
wifi_pass = prefs.getString("w_pass", "");
mqtt_server = prefs.getString("m_host", "");
mqtt_user = prefs.getString("m_user", "");
mqtt_pass = prefs.getString("m_pass", "");
mqtt_port = prefs.getInt("m_port", 1883);
topicLine1 = prefs.getString("t1", "display/line1");
topicLine2 = prefs.getString("t2", "display/line2");
topicLine3 = prefs.getString("t3", "display/line3");
topicLine4 = prefs.getString("t4", "display/line4");
labelLine1 = prefs.getString("l1", "Line1");
labelLine2 = prefs.getString("l2", "Line2");
labelLine3 = prefs.getString("l3", "Line3");
labelLine4 = prefs.getString("l4", "Line4");
displayBrightness = prefs.getInt("br", 180);
zoneMode = prefs.getInt("zones", 4);
if (zoneMode != 2 && zoneMode != 4) zoneMode = 4;
}
/* ========================================================= */
/* ======================= WIFI ============================ */
/* ========================================================= */
bool connectWiFi() {
if (wifi_ssid == "") return false;
WiFi.mode(WIFI_STA);
WiFi.begin(wifi_ssid.c_str(), wifi_pass.c_str());
unsigned long start = millis();
while (WiFi.status() != WL_CONNECTED) {
delay(500);
if (millis() - start > 15000) return false;
}
return true;
Serial2.println("IP:" + WiFi.localIP().toString());
}
void startAP() {
WiFi.mode(WIFI_AP);
WiFi.softAP("ESP32-Setup");
Serial.println("AP IP: " + WiFi.softAPIP().toString());
}
/* ========================================================= */
/* ======================= MQTT ============================ */
/* ========================================================= */
void reconnectMQTT() {
if (mqtt_server == "") return;
while (!client.connected()) {
String id = "ESP32-" + String(random(0xffff), HEX);
if (client.connect(id.c_str(), mqtt_user.c_str(), mqtt_pass.c_str())) {
client.subscribe(topicLine1.c_str());
client.subscribe(topicLine2.c_str());
client.subscribe(topicLine3.c_str());
client.subscribe(topicLine4.c_str());
} else {
delay(2000);
}
}
}
/* ========================================================= */
/* ======================= WEB UI ========================== */
/* ========================================================= */
void handleRoot() {
String html =
"<!DOCTYPE html><html><head><meta charset='UTF-8'>"
"<title>SPIKE TECH – ESP32</title>"
"<style>"
"body{font-family:Arial;background:#f2f3f5}"
".box{width:400px;margin:10px auto;background:#fff;padding:35px;border-radius:10px}"
"h2{text-align:center;color:#e53935;letter-spacing:4px}"
"h3{border-bottom:2px solid #e53935;color:#e53935;margin-top:35px}"
"label{font-weight:bold;margin-top:10px;display:block}"
"input,select{width:100%;padding:8px;margin-top:5px}"
".row{display:flex;gap:20px}"
".col{flex:1}"
"button{margin-top:30px;padding:14px;width:100%;background:#e53935;color:#fff;font-size:18px;border:none;border-radius:6px}"
"</style></head><body><div class='box'>"
"<h2>SPIKE TECH</h2>"
"<form action='/save' method='POST'>"
"<h3>Display</h3>"
"<div class='row'>"
"<div class='col'><label>Brightness</label><input name='br' value='" + String(displayBrightness) + "'></div>"
"<div class='col'><label>Zones</label><select name='zones'>"
"<option value='2'" + String(zoneMode==2?" selected":"") + ">2 Zones</option>"
"<option value='4'" + String(zoneMode==4?" selected":"") + ">4 Zones</option>"
"</select></div></div>"
"<h3>Lines</h3>";
auto lineRow = [&](int n, String lbl, String top) {
return "<div class='row'><div class='col'><label>L"+String(n)+" Label</label>"
"<input name='lbl"+String(n)+"' value='"+lbl+"'></div>"
"<div class='col'><label>L"+String(n)+" Topic</label>"
"<input name='l"+String(n)+"' value='"+top+"'></div></div>";
};
html += lineRow(1,labelLine1,topicLine1);
html += lineRow(2,labelLine2,topicLine2);
html += lineRow(3,labelLine3,topicLine3);
html += lineRow(4,labelLine4,topicLine4);
html +=
"<h3>WiFi</h3>"
"<label>SSID</label><input name='ssid' value='"+wifi_ssid+"'>"
"<label>Password</label><input type='password' name='wpass' value='"+wifi_pass+"'>"
"<h3>MQTT</h3>"
"<div class='row'>"
"<div class='col'><label>Server</label><input name='mhost' value='"+mqtt_server+"'></div>"
"<div class='col'><label>Port</label><input name='mport' value='"+String(mqtt_port)+"'></div>"
"</div>"
"<label>User</label><input name='muser' value='"+mqtt_user+"'>"
"<label>Password</label><input type='password' name='mpass' value='"+mqtt_pass+"'>"
"<button type='submit'>Save (Live)</button></form></div></body></html>";
server.send(200, "text/html", html);
}
/* ========================================================= */
/* ======================= SAVE ============================ */
/* ========================================================= */
void handleSave() {
int oldZone = zoneMode;
wifi_ssid = server.arg("ssid");
wifi_pass = server.arg("wpass");
mqtt_server = server.arg("mhost");
mqtt_user = server.arg("muser");
mqtt_pass = server.arg("mpass");
mqtt_port = server.arg("mport").toInt();
displayBrightness = server.arg("br").toInt();
zoneMode = server.arg("zones").toInt();
if (zoneMode != 2 && zoneMode != 4) zoneMode = oldZone;
topicLine1 = server.arg("l1");
topicLine2 = server.arg("l2");
topicLine3 = server.arg("l3");
topicLine4 = server.arg("l4");
labelLine1 = server.arg("lbl1");
labelLine2 = server.arg("lbl2");
labelLine3 = server.arg("lbl3");
labelLine4 = server.arg("lbl4");
prefs.putString("w_ssid", wifi_ssid);
prefs.putString("w_pass", wifi_pass);
prefs.putString("m_host", mqtt_server);
prefs.putString("m_user", mqtt_user);
prefs.putString("m_pass", mqtt_pass);
prefs.putInt("m_port", mqtt_port);
prefs.putString("t1", topicLine1);
prefs.putString("t2", topicLine2);
prefs.putString("t3", topicLine3);
prefs.putString("t4", topicLine4);
prefs.putString("l1", labelLine1);
prefs.putString("l2", labelLine2);
prefs.putString("l3", labelLine3);
prefs.putString("l4", labelLine4);
prefs.putInt("br", displayBrightness);
prefs.putInt("zones", zoneMode);
Serial2.println("BR:" + String(displayBrightness));
if (oldZone != zoneMode) {
Serial2.println("ZONES:" + String(zoneMode));
// Serial2.println("BR:" + String(displayBrightness));
}
// 🔁 NETTE REDIRECT
server.sendHeader("Location", "/");
server.send(303);
delay(200);
// 🔄 reconnect NA response
WiFi.disconnect();
connectWiFi();
client.disconnect();
reconnectMQTT();
}
/* ========================================================= */
/* ======================= SETUP =========================== */
/* ========================================================= */
void setup() {
Serial.begin(115200);
Serial2.begin(115200, SERIAL_8N1, 16, 17);
prefs.begin("display", false);
loadSettings();
if (!connectWiFi()) startAP();
Serial2.println("IP:" + WiFi.localIP().toString());
Serial2.println("ZONES:" + String(zoneMode));
client.setServer(mqtt_server.c_str(), mqtt_port);
client.setCallback(callback);
server.on("/", handleRoot);
server.on("/save", HTTP_POST, handleSave);
server.begin();
}
/* ========================================================= */
/* ======================= LOOP ============================ */
/* ========================================================= */
void loop() {
if (WiFi.status() == WL_CONNECTED) {
if (!client.connected()) reconnectMQTT();
client.loop();
}
server.handleClient();
}
Bij Opstart eerste meldind Arduino Boot OK = UNO en Display werken
Waiting IP, we wachten tot esp verbinding heeft met netwerk en geeft dan IP Nummer weer. Via browser nummer ingeven !
Voorbeeld met 4 Zone's
Voorbeeld eerste test, Hardware di direct op display kan verbonden worden !