MQTT-Display-LaserCutter/README.md
2026-02-22 11:13:16 +01:00

231 lines
9.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 03 | Akkumulierte aktive Laserzeit in **Minuten** (z.B. `42.5 min`) |
| Unten | Module 47 | 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 (0120 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, 0120 |
| 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
```