MQTT-Display-LaserCutter/Implementation-Plan.md
MaPaLo76 6ac33f459d feat(phase1): complete hardware setup, display and button test sketches
- platformio.ini: add all 8 libraries via Git URLs, add test-display and
  test-button environments, reduce SPI clock to 1 MHz for stability
- include/config.h: add pin definitions, DISPLAY_HW_TYPE=GENERIC_HW,
  MQTT topics, NVS keys and logging macros
- src/main.cpp: add minimal startup skeleton with config.h include
- test_sketches/test_display.cpp: diagnostic sketch showing 0-based module
  index; GENERIC_HW verified with 90 deg CCW software rotation
- test_sketches/test_button.cpp: GPIO INPUT_PULLUP test; LOW_ACTIVE confirmed
- test_sketches/README.md: add wiring tables, flash commands, results table
- README.md: update HW type to GENERIC_HW, add power supply note (0.5A /
  2.5W measured, external 5V PSU required), add Conventional Commits section
- Implementation-Plan.md: mark tasks 1.1-1.5 as complete

BREAKING CHANGE: none
2026-02-22 13:20:52 +01:00

8.5 KiB
Raw Blame History

Implementation Plan Laser Cutter MQTT Display

Dieses Dokument beschreibt die Entwicklungsreihenfolge des Projekts.
Tasks werden während der Entwicklung mit [x] abgehakt.


Phase 1 Projekt-Setup & Konfiguration

  • 1.1 platformio.ini mit allen benötigten Bibliotheken erweitern

    • MD_Parola, MD_MAX72XX
    • PubSubClient
    • WiFiManager (tzapu/WiFiManager)
    • ESPAsyncWebServer + AsyncTCP
    • ArduinoJson
    • ElegantOTA
    • Preferences (ESP32 built-in, kein Extra-Eintrag nötig)
  • 1.2 include/config.h erstellen zentrale Pin-Definitionen und Konstanten

    • GPIO-Pins (MAX7219 SPI, Laser-Signal)
    • Anzahl der Module (8), Zonen-Aufteilung
    • Standard-Werte (Gratiszeit 20s, MQTT Port 1883, etc.)
    • MQTT-Topic-Konstanten
  • 1.3 Build prüfen (leeres Projekt kompiliert fehlerfrei)

  • 1.4 Test Verdrahtung Dot-Matrix-Display

    • GYMAX7219-Module gemäß Pinbelegung angeschlossen (MOSI GPIO 23, CLK GPIO 18, CS GPIO 5)
    • Hardware-Typ FC16_HW (nicht GENERIC_HW) verifiziert
    • Modul 1 oben-links, Modul 4 oben-rechts, Modul 5 unten-links, Modul 8 unten-rechts
    • Zone 0 (0-idx 03) = obere Reihe, Zone 1 (0-idx 47) = untere Reihe
  • 1.5 Test Verdrahtung Potentialfreier Schalter (Phase 1: Push Button)

    • Push Button an GPIO 4 und GND angeschlossen (INPUT_PULLUP, kein externer Widerstand nötig)
    • Pegel verifiziert: Button offen = HIGH, Button gedrückt = LOW → Polarität: LOW_ACTIVE
    • Debounce 50 ms funktioniert

Phase 2 NVS Persistenz (Settings)

  • 2.1 include/settings.h + src/settings.cpp erstellen
    Speichert und lädt alle Konfigurationswerte über ESP32 Preferences (NVS):

    • MQTT Broker IP, Port, User, Passwort
    • Gratiszeit (0120 s)
    • Signal-Polarität (LOW_ACTIVE / HIGH_ACTIVE)
    • Akkumulierte Laserzeit (float, Minuten)
  • 2.2 Unit-Test (Serial-Output): Werte schreiben, ESP32 neu starten, Werte lesen und verifizieren


Phase 3 WiFi & WiFiManager

  • 3.1 WiFiManager einbinden

    • AP-Name: LaserCutter-Setup
    • Captive-Portal-Seite für WLAN-Credentials
    • Timeout: 120 s, danach Neustart
  • 3.2 Verbindungsstatus-Callback implementieren (für spätere Fehleranzeige)

  • 3.3 Test: Erstverbindung mit neuem AP, gespeichertes WLAN nach Neustart automatisch verbinden


Phase 4 Dot-Matrix-Display (DisplayManager)

  • 4.1 include/display_manager.h + src/display_manager.cpp erstellen
    Wrapper um MD_Parola mit zwei Zonen:

    • Zone 0 (Module 03, obere Reihe): Laserzeit in Minuten
    • Zone 1 (Module 47, untere Reihe): Countdown / Statusmeldungen
  • 4.2 Methoden implementieren:

    • showLaserTime(float minutes) obere Zeile
    • showCountdown(int seconds) untere Zeile (während Gratiszeit)
    • showIdle() --- in unterer Zeile wenn kein Countdown
    • showError(const char* msg) Fehlermeldung in unterer Zeile, Modul 1
    • update() in loop() aufrufen (MD_Parola benötigt regelmäßigen Aufruf)
  • 4.3 Test: Statische Zahlen und Scrolltext auf beiden Zonen anzeigen


Phase 5 Laser-Signaldetektion & Zeit-Tracking (LaserTracker)

  • 5.1 include/laser_tracker.h + src/laser_tracker.cpp erstellen

  • 5.2 GPIO-Eingang konfigurieren:

    • INPUT_PULLUP auf GPIO 4
    • Software-Debounce (min. 50 ms Entprellzeit)
    • Polarität über Settings auslesbar
  • 5.3 Session-Logik implementieren:

    • onLaserActive() → Session-Start, Timer starten
    • onLaserInactive() → Session-Ende, akkumulierte Zeit aktualisieren, NVS speichern
  • 5.4 Gratiszeit-Logik:

    • Countdown läuft ab Session-Start
    • Zeit wird erst nach Ablauf der Gratiszeit zur Gesamtzeit addiert
    • getCountdownRemaining() → Rückgabe verbleibende Sekunden (0 wenn abgelaufen)
  • 5.5 Öffentliche Getter:

    • getTotalMinutes() → float
    • getSessionSeconds() → int (aktuelle Session ohne Gratiszeit)
    • isActive() → bool
    • getLastSessionSeconds() → int (für MQTT Publish)
  • 5.6 Test: Laser-Signal simulieren (GPIO auf GND ziehen), Zeitmessung verifizieren


Phase 6 MQTT Client (MqttClient)

  • 6.1 include/mqtt_client.h + src/mqtt_client.cpp erstellen
    Wrapper um PubSubClient

  • 6.2 Verbindungsaufbau mit Credentials aus Settings

  • 6.3 Publish-Methode publishSession(sessionSec, totalMin, gratisSec):

    • Topic: lasercutter/session
    • JSON mit session_s, total_min, gratiszeit_s, ts
    • Wird von LaserTracker beim Session-Ende aufgerufen
  • 6.4 Publish-Methode publishStatus(totalMin, ipStr, uptimeSec):

    • Topic: lasercutter/status
    • Heartbeat alle 60 Sekunden
    • QoS 0
  • 6.5 Subscribe auf lasercutter/reset:

    • Payload "1" oder {"action":"reset"}LaserTracker::resetTotal()
    • QoS 1
  • 6.6 Reconnect-Logik (Non-blocking, max. alle 10 Sekunden versuchen)

  • 6.7 Test: Session-Daten mit MQTT Explorer empfangen, Reset auslösen und verifizieren


Phase 7 Webinterface (WebServer)

  • 7.1 include/web_server.h + src/web_server.cpp erstellen
    Basierend auf ESPAsyncWebServer

  • 7.2 Route GET / Statusseite (HTML):

    • Aktuelle Laserzeit (Minuten)
    • Letzter Session-Wert (Sekunden)
    • WLAN-Status, MQTT-Status
    • IP-Adresse
  • 7.3 Route GET /config Konfigurationsformular (HTML):

    • MQTT Broker IP, Port, User, Passwort
    • Gratiszeit (Slider 0120 s)
    • Signal-Polarität (Radio-Button)
  • 7.4 Route POST /config Konfiguration speichern (via Settings, NVS)

  • 7.5 Route POST /reset Laserzeit zurücksetzen (Button auf Statusseite)

  • 7.6 ElegantOTA unter /update einbinden

  • 7.7 Test: Alle Seiten im Browser aufrufen, Konfiguration ändern und nach Neustart prüfen


Phase 8 Integration & Hauptprogramm (main.cpp)

  • 8.1 main.cpp aufräumen und alle Module initialisieren:

    • Reihenfolge: SettingsDisplayManagerWiFiManagerMqttClientWebServerLaserTracker
  • 8.2 loop() implementieren:

    • displayManager.update()
    • laserTracker.update() (GPIO-Polling + Session-Logik)
    • mqttClient.loop() (Reconnect + Heartbeat)
    • displayManager.showLaserTime(laserTracker.getTotalMinutes())
    • displayManager.showCountdown(...) oder showIdle() oder showError(...)
  • 8.3 Callback von LaserTrackerMqttClient.publishSession(...) verdrahten

  • 8.4 WLAN/MQTT-Fehlerzustand auf Display spiegeln

  • 8.5 Watchdog Timer aktivieren (ESP32 WDT, 30 s)


Phase 9 OTA & Stabilisierung

  • 9.1 ElegantOTA in main.cpp initialisieren und in loop() einbinden

  • 9.2 Serielles Logging vereinheitlichen (Log-Level: INFO / DEBUG per #define)

  • 9.3 Langzeit-Test: 24h Betrieb, Speicherleck-Check via Serial Monitor (ESP.getFreeHeap())

  • 9.4 Edge-Cases testen:

    • Laser aktiv, WLAN wird getrennt → Display läuft weiter
    • MQTT-Broker nicht erreichbar → Reconnect
    • Reset während aktiver Session
    • Neustart nach akkumulierter Zeit → Zeit korrekt aus NVS geladen

Phase 10 Dokumentation & Abschluss

  • 10.1 README.md finalisieren (Screenshots, Schaltplan-Skizze ggf. ergänzen)

  • 10.2 platformio.ini mit finalen Library-Versionen dokumentieren

  • 10.3 MQTT-Topics in README.md validieren (mit realem Broker testen)

  • 10.4 Optionaler Schaltplan (Fritzing / ASCII) für Laser-Signal-Anschluss (Optokoppler)


Abhängigkeitsdiagramm (Reihenfolge)

Phase 1 (Setup)
    └── Phase 2 (NVS/Settings)
            ├── Phase 3 (WiFi)
            ├── Phase 4 (Display)
            └── Phase 5 (LaserTracker)
                    └── Phase 6 (MQTT)
                            └── Phase 7 (Webinterface)
                                    └── Phase 8 (Integration)
                                            └── Phase 9 (OTA/Stabilisierung)
                                                    └── Phase 10 (Doku)

Verwendete MQTT-Topics (Überblick)

Topic Richtung QoS Auslöser
lasercutter/session Publish 1 Session-Ende (Laser inaktiv)
lasercutter/status Publish 0 Heartbeat alle 60 s
lasercutter/reset Subscribe 1 Externer Reset-Befehl

Erstellt: 22. Februar 2026