MQTT-Display-LaserCutter/test_sketches/test_display.cpp
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

232 lines
6.4 KiB
C++
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.

/**
* TEST SKETCH 1.4 GYMAX7219 Modulnummern-Diagnose
*
* Jedes Modul zeigt seine eigene 0-basierte Index-Nummer (0..7).
* Direkte MD_MAX72XX API kein Parola, keine Zonen.
*
* Ablauf:
* 1. Alle Module zeigen dauerhaft ihre Indexnummer 07
* 2. Alle 3 s wird abwechselnd getestet:
* a) Alle LEDs EIN (volle Helligkeit → Stromtest)
* b) Alle LEDs AUS
* c) Jedes Modul zeigt seine Nummer wieder
*
* Serial Monitor zeigt welcher hw-Typ gerade aktiv ist.
* → Nummern richtig/lesbar + Reihenfolge notieren, dann in config.h eintragen.
*
* Flash: pio run -e test-display --target upload
* Monitor: pio device monitor -e test-display
*/
#include <Arduino.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
// ---- Pins ----
#define CS_PIN 5
#define NUM_MOD 8
// ---- Zu testende Hardware-Typen ----
// Kommentiere einen aus und flashe erneut, bis die Zahlen AUFRECHT stehen.
// Dann diesen Typ in config.h als DISPLAY_HW_TYPE eintragen.
#define HW_TYPE MD_MAX72XX::GENERIC_HW
//#define HW_TYPE MD_MAX72XX::FC16_HW
//#define HW_TYPE MD_MAX72XX::PAROLA_HW
// Lesbare Bezeichnung für Serial (muss zur obigen Wahl passen)
#define HW_TYPE_NAME "GENERIC_HW"
//#define HW_TYPE_NAME "FC16_HW"
//#define HW_TYPE_NAME "PAROLA_HW"
MD_MAX72XX mx = MD_MAX72XX(HW_TYPE, CS_PIN, NUM_MOD);
// 5-spaltige 7-Segment-ähnliche Ziffern 08 (8 Zeilen, Spalten links→rechts)
// Jeder Eintrag: 8 Bytes = 8 Pixelzeilen von oben nach unten
static const uint8_t DIGIT[9][8] = {
// 0
{ 0b00111100,
0b01000010,
0b01000010,
0b01000010,
0b01000010,
0b01000010,
0b00111100,
0b00000000 },
// 1
{ 0b00010000,
0b00110000,
0b00010000,
0b00010000,
0b00010000,
0b00010000,
0b00111000,
0b00000000 },
// 2
{ 0b00111100,
0b01000010,
0b00000010,
0b00001100,
0b00110000,
0b01000000,
0b01111110,
0b00000000 },
// 3
{ 0b00111100,
0b01000010,
0b00000010,
0b00011100,
0b00000010,
0b01000010,
0b00111100,
0b00000000 },
// 4
{ 0b00001000,
0b00011000,
0b00101000,
0b01001000,
0b01111110,
0b00001000,
0b00001000,
0b00000000 },
// 5
{ 0b01111110,
0b01000000,
0b01000000,
0b01111100,
0b00000010,
0b01000010,
0b00111100,
0b00000000 },
// 6
{ 0b00111100,
0b01000000,
0b01000000,
0b01111100,
0b01000010,
0b01000010,
0b00111100,
0b00000000 },
// 7
{ 0b01111110,
0b00000010,
0b00000100,
0b00001000,
0b00010000,
0b00010000,
0b00010000,
0b00000000 },
// 8
{ 0b00111100,
0b01000010,
0b01000010,
0b00111100,
0b01000010,
0b01000010,
0b00111100,
0b00000000 },
};
// Dreht eine 8x8 Bitmap 90° gegen den Uhrzeigersinn
// Kompensiert die 90° CW physische Ausrichtung der Module
// Formel: new[r][c] = old[c][7-r]
// → new_row[r] |= (1<<(7-c)) wenn old_row[c] Bit r gesetzt ist
void rotateCCW(const uint8_t src[8], uint8_t dst[8]) {
memset(dst, 0, 8);
for (uint8_t r = 0; r < 8; r++) {
for (uint8_t c = 0; c < 8; c++) {
if (src[c] & (1 << r)) {
dst[r] |= (1 << (7 - c));
}
}
}
}
// Schreibt Ziffer d (0-basiert) in Modul moduleIdx mit 90° CCW Korrektur
void showDigit(uint8_t moduleIdx, uint8_t d) {
if (d > 8) d = 8;
uint8_t rotated[8];
rotateCCW(DIGIT[d], rotated);
for (uint8_t row = 0; row < 8; row++) {
mx.setRow(moduleIdx, row, rotated[row]);
}
}
void allLedsOn() { for (uint8_t m=0;m<NUM_MOD;m++) for(uint8_t r=0;r<8;r++) mx.setRow(m,r,0xFF); }
void allLedsOff() { for (uint8_t m=0;m<NUM_MOD;m++) for(uint8_t r=0;r<8;r++) mx.setRow(m,r,0x00); }
void showAllNumbers() {
// Modul 0 zeigt "0", Modul 1 zeigt "1" ... Modul 7 zeigt "7"
// (entspricht physischer Modul-Nummerierung 18 wenn 0-basiert = 07)
for (uint8_t i = 0; i < NUM_MOD; i++) {
showDigit(i, i); // 0-basierter Index als Ziffer
}
}
// Doppelte Initialisierung: alle Module sicher ansprechen, auch wenn
// sie beim ersten begin() noch nicht vollständig gebootet waren.
static void initDisplay() {
mx.begin();
mx.control(MD_MAX72XX::INTENSITY, 5);
mx.control(MD_MAX72XX::TEST, MD_MAX72XX::OFF);
mx.clear();
}
void setup() {
Serial.begin(115200);
// Längere Wartezeit: Module brauchen Zeit zum Hochfahren.
// Ohne dies verpassen Module mit langsamerem Power-On-Rise die Init-Sequenz.
delay(1000);
initDisplay();
// Zweiter Durchlauf nach kurzer Pause holt Module nach die beim ersten
// Aufruf noch nicht bereit waren (z. B. bei externem Netzteil mit Anlaufverzögerung)
delay(200);
initDisplay();
Serial.println("============================================");
Serial.println(" MODUL-DIAGNOSE: Jedes Modul zeigt seinen");
Serial.println(" 0-basierten Index (0 = erstes in Kette)");
Serial.println("============================================");
Serial.printf(" HW-Typ: %s\n", HW_TYPE_NAME);
Serial.println("--------------------------------------------");
Serial.println(" Beobachte welches Modul welche Zahl zeigt:");
Serial.println(" 0 = erstes Modul nach ESP32 DIN");
Serial.println(" 7 = letztes Modul in der Kette");
Serial.println("--------------------------------------------");
Serial.println(" Wenn Ziffern auf dem Kopf stehen:");
Serial.println(" → anderen HW_TYPE auskommentieren + neu flashen");
Serial.println(" Reihenfolge: FC16_HW → PAROLA_HW → GENERIC_HW");
Serial.println("============================================");
// --- Schritt 1: Alle EIN ---
Serial.println("\n[1] Alle LEDs EIN (2 s)");
allLedsOn();
delay(2000);
// --- Schritt 2: Alle AUS ---
Serial.println("[2] Alle LEDs AUS (1 s)");
allLedsOff();
delay(1000);
// --- Schritt 3: Modulnummern ---
Serial.println("[3] Jedes Modul zeigt seinen 0-Index dauerhaft");
showAllNumbers();
Serial.println("\nErwartetes Bild auf der Hardware:");
Serial.println(" [0][1][2][3] ← obere Reihe (idx 0 = links)");
Serial.println(" [4][5][6][7] ← untere Reihe (idx 7 = rechts)");
Serial.println("\nWenn die Ziffern aufrecht und in dieser Reihenfolge");
Serial.println("stehen → HW_TYPE korrekt! In config.h übernehmen.");
}
void loop() {
// Alle 4 s: kurz blinken damit man sieht dass der Controller läuft
static uint32_t last = 0;
if (millis() - last >= 4000) {
last = millis();
allLedsOff();
delay(100);
showAllNumbers();
Serial.println("[LIVE] Module 07 angezeigt");
}
}