- 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
232 lines
6.4 KiB
C++
232 lines
6.4 KiB
C++
/**
|
||
* 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 0–7
|
||
* 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 0–8 (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 1–8 wenn 0-basiert = 0–7)
|
||
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 0–7 angezeigt");
|
||
}
|
||
}
|