# Laser Cutter Dot Matrix Display und MQTT Client Dieses Projekt implementiert einen ESP32-basierten MQTT-Client mit Dot-Matrix-Display für einen Laser Cutter. Es misst und visualisiert die aktive Laserzeit, sendet Session-Daten an einen MQTT-Broker und bietet ein Browser-Webinterface zur Konfiguration und Steuerung. --- ## Inhaltsverzeichnis 1. [Hardware](#hardware) 2. [Pinbelegung](#pinbelegung) 3. [Display](#display) 4. [Laser-Signaldetektion](#laser-signaldetektion) 5. [Zeit-Tracking & Gratiszeit](#zeit-tracking--gratiszeit) 6. [MQTT Client](#mqtt-client) 7. [Webinterface](#webinterface) 8. [Konfiguration & Persistenz](#konfiguration--persistenz) 9. [WiFi-Setup (WiFiManager)](#wifi-setup-wifimanager) 10. [OTA Firmware-Update](#ota-firmware-update) 11. [Fehlerverhalten](#fehlerverhalten) 12. [Bibliotheken](#bibliotheken) 13. [Build & Flash](#build--flash) --- ## Hardware | Komponente | Modell / Beschreibung | |-------------------------|----------------------------------------------------| | Mikrocontroller | AZ-Delivery ESP32 DevKit V4 | | Dot-Matrix-Display | 8× GYMAX7219 Module (kompatibel zu MAX7219), 8×8 LEDs je Modul | | Display-Anordnung | 4 Module nebeneinander × 2 Reihen = 32×16 LEDs | | Display-Kaskadierung | Alle 8 Module in einer einzigen SPI-Kette | | Laser-Aktivsignal | Potentialfreier Ausgang des Laser Cutters (Optokoppler empfohlen) | | Optional | Shelly PM Mini G3 als externer Leistungsmesser (separater MQTT-Service) | --- ## Pinbelegung | Signal | ESP32 GPIO | Beschreibung | |---------------|-----------|------------------------------------------------| | MAX7219 MOSI | GPIO 23 | SPI Data (VSPI) | | MAX7219 CLK | GPIO 18 | SPI Clock (VSPI) | | MAX7219 CS | GPIO 5 | SPI Chip Select | | Laser-Signal | GPIO 4 | Potentialfreier Eingang (INPUT_PULLUP, konfigurierbar invertierbar) | > Die Polarität des Laser-Signals (HIGH = aktiv oder LOW = aktiv) ist über das Webinterface konfigurierbar. --- ## Display Das Display besteht aus 8 GYMAX7219-Modulen in einer 4×2-Anordnung (32×16 LEDs gesamt). Es ist in **zwei Zonen** aufgeteilt, die unabhängig voneinander beschrieben werden: | Zone | Module (Kette) | Anzeige-Inhalt | |------|----------------|----------------------------------------| | Oben | Module 0–3 | Akkumulierte aktive Laserzeit in **Minuten** (z.B. `42.5 min`) | | Unten | Module 4–7 | Laufender **Countdown** in Sekunden der Gratiszeit, danach `---` | - Die Anzeige aktualisiert sich sekündlich, solange der Laser aktiv ist. - Bei inaktivem Laser bleibt die letzte gemessene Zeit dauerhaft sichtbar. - Fehlerzustände (WLAN, MQTT) werden in der **unteren Zeile, erstes Modul** angezeigt. - Die Bibliotheken `MD_Parola` + `MD_MAX72XX` werden für die Ansteuerung verwendet. --- ## Laser-Signaldetektion Der ESP32 überwacht einen **digitalen GPIO-Eingang** mit internem Pull-Up-Widerstand (`INPUT_PULLUP`). Der potentialfreie Ausgang des Laser Cutters (z.B. Schließer-Kontakt über Optokoppler) wird an diesen Pin angeschlossen. - **Polarität konfigurierbar**: Im Webinterface einstellbar, ob `LOW` oder `HIGH` den aktiven Zustand bedeutet. - **Debounce**: Software-Entprellung, um Fehlmessungen bei Schaltflanken zu vermeiden. - Eine **Session** beginnt, wenn der Laser aktiv wird, und endet, wenn er inaktiv wird. --- ## Zeit-Tracking & Gratiszeit - Die Laserzeit wird **akkumulativ** in Minuten gezählt und über Neustarts hinaus im **NVS (Non-Volatile Storage)** des ESP32 gespeichert. - **Gratiszeit**: Eine konfigurierbare Zeitspanne (0–120 Sekunden) am Anfang jeder Session wird **nicht** zur akkumulierten Zeit gezählt. Dies erlaubt kurze Testläufe zum Einstellen des Laser Cutters ohne Kosten. - Standard: 20 Sekunden - Einstellbar über das Webinterface - Die untere Display-Zeile zeigt während der Gratiszeit einen Countdown an. --- ## MQTT Client Der ESP32 verbindet sich mit einem MQTT-Broker (konfigurierbar über Webinterface). ### Topics | Richtung | Topic | Format | Beschreibung | |------------|---------------------------|---------|-------------------------------------------| | Publish | `lasercutter/session` | JSON | Wird beim **Ende einer Session** gesendet | | Subscribe | `lasercutter/reset` | `"1"` | Setzt die akkumulierte Laserzeit auf 0 | | Publish | `lasercutter/status` | JSON | Heartbeat alle 60 Sekunden (online/offline)| ### JSON-Format `lasercutter/session` ```json { "session_s": 125, "total_min": 42.5, "gratiszeit_s": 20, "ts": "2026-02-22T10:30:00Z" } ``` ### JSON-Format `lasercutter/status` ```json { "online": true, "total_min": 42.5, "ip": "192.168.1.100", "uptime_s": 3600 } ``` ### Verhalten - Reconnect im Hintergrund, falls MQTT-Broker nicht erreichbar. - Bei aktivem Laser läuft die Zeitmessung unabhängig vom MQTT-Status weiter. - QoS 1 für Session- und Reset-Topics. --- ## Webinterface Das Webinterface ist über die IP-Adresse des ESP32 im Browser erreichbar. | Seite | URL | Funktion | |------------------|-------------|--------------------------------------------------------------| | Status | `/` | Aktuelle Laserzeit, letzter Session-Wert, Systemstatus | | Konfiguration | `/config` | MQTT-Broker (IP, Port, User, Passwort), Gratiszeit, Polarität | | Reset | `/reset` | Setzt akkumulierte Laserzeit zurück | | OTA Update | `/update` | Firmware-Update über Browser | --- ## Konfiguration & Persistenz Alle Einstellungen werden im **NVS (Non-Volatile Storage)** des ESP32 gespeichert und sind über das Webinterface änderbar: | Einstellung | Standard | Beschreibung | |-----------------------|---------------|-----------------------------------------| | MQTT Broker IP | `192.168.1.1` | IP-Adresse des MQTT-Brokers | | MQTT Port | `1883` | Port des MQTT-Brokers | | MQTT User | *(leer)* | MQTT Benutzername (optional) | | MQTT Passwort | *(leer)* | MQTT Passwort (optional) | | Gratiszeit | `20` | Sekunden, 0–120 | | Signal-Polarität | `LOW_ACTIVE` | `LOW_ACTIVE` oder `HIGH_ACTIVE` | | Akkumulierte Zeit | `0.0` | Gespeicherte Laserzeit in Minuten (NVS) | --- ## WiFi-Setup (WiFiManager) Beim ersten Start (oder wenn keine gespeicherten WLAN-Daten vorhanden) öffnet das Gerät einen **Access Point** mit Captive Portal: - SSID: `LaserCutter-Setup` - Im Browser öffnet sich automatisch die Konfigurationsseite. - WLAN-Credentials werden nach erfolgreicher Verbindung im NVS gespeichert. --- ## OTA Firmware-Update Firmware-Updates können kabellos über die Weboberfläche unter `/update` eingespielt werden (ElegantOTA). --- ## Fehlerverhalten | Zustand | Display-Anzeige (untere Zeile, Modul 1) | Verhalten | |----------------------|----------------------------------------|----------------------------------------| | WLAN getrennt | `WiFi ERR` | Zeiterfassung läuft weiter, Reconnect | | MQTT nicht erreichbar| `MQTT ERR` | Zeiterfassung läuft weiter, Reconnect | | WLAN + MQTT OK | Normaler Betrieb (Countdown/`---`) | – | --- ## Bibliotheken | Bibliothek | Zweck | |-----------------------|--------------------------------------| | `MD_Parola` | Dot-Matrix-Display Textausgabe | | `MD_MAX72XX` | Treiber für MAX7219/GYMAX7219 | | `PubSubClient` | MQTT Client | | `WiFiManager` | WiFi Captive Portal | | `ESPAsyncWebServer` | Asynchroner Webserver | | `AsyncTCP` | TCP-Basis für ESPAsyncWebServer | | `ArduinoJson` | JSON Serialisierung/Deserialisierung | | `Preferences` | NVS-Zugriff (built-in ESP32 Arduino) | | `ElegantOTA` | OTA-Update über Webinterface | --- ## Build & Flash ```bash # PlatformIO CLI pio run --target upload # Serieller Monitor pio device monitor ``` Ziel-Board: `az-delivery-devkit-v4` (ESP32), Upload-Port: `COM3` --- ## Projektstruktur ``` MQTT-Display-LaserCutter/ ├── src/ │ └── main.cpp # Hauptprogramm ├── include/ │ ├── config.h # Pin-Definitionen, Konstanten │ ├── display_manager.h # Display-Logik (MD_Parola) │ ├── laser_tracker.h # Signal-Detektion & Zeiterfassung │ ├── mqtt_client.h # MQTT-Wrapper (PubSubClient) │ ├── web_server.h # Webinterface (ESPAsyncWebServer) │ └── settings.h # NVS-Persistenz (Preferences) ├── parser/ │ └── shelly_parser.py # Separater Python-Parser für Shelly PM G3 ├── platformio.ini └── README.md ```