Hallo,
ich arbeite an einem Projekt für ein 64x20 LED Lichternetz (Weihnachten und so...). Die Ansteuerung bestand ursprünglich aus einem Microcontroller+Schieberegister+LED-Treiber u.s.w..
Den Microcontroller habe ich vom Rest getrennt (zuständige Leiterbahnen unterbrochen).
Seine Aufgabe übernimmt nun ein Wemos D1 Mini. Das macht das Ganze für mich nach hinten raus weitaus flexibler (Steuerung über WLAN, Konfiguration über Webseite, eigene Texte scrollen, Wetter, Muster, ...).
Das Multiplexing zum Ansteuern der Matrix wird in einem TimerInterrupt realisiert, damit es nicht von anderen Routinen im main loop beeinflusst wird:
void setup {
....
noInterrupts();
pinMode(cs0, OUTPUT);
pinMode(cs1, OUTPUT);
pinMode(a0, OUTPUT);
pinMode(a1, OUTPUT);
pinMode(a2, OUTPUT);
pinMode(clk, OUTPUT);
pinMode(sdi, OUTPUT);
pinMode(le, OUTPUT);
pinMode(oe, OUTPUT);
digitalWrite(oe, HIGH);
timer1_isr_init();
timer1_attachInterrupt(timer1_ISR);
timer1_enable(TIM_DIV16, TIM_EDGE, TIM_SINGLE);
timer1_write(500);
interrupts();
...
}
In der Interrupt Service Routine wird einfach ein Array (displaybuf[]) auf die Matrix projiziert, indem die Schieberegister mit Daten "gefüttert" werden:
void ICACHE_RAM_ATTR timer1_ISR() {
static uint8_t row = 0; // is only set the first time through the loop because of "static"
uint8_t *head = displaybuf + row * 8; // pointer to begin of every row (8 byte per row)
uint8_t *ptr = head;
for (uint8_t byte = 0; byte < 8; byte++) {
uint8_t pixels = *ptr;
ptr++;
pixels = pixels ^ mask;
shiftOut(sdi, clk, MSBFIRST, pixels);
}
digitalWrite(oe, HIGH); // disable display
// select row
digitalWrite(a0, (row & 0x01));
digitalWrite(a1, (row & 0x02));
digitalWrite(a2, (row & 0x04));
digitalWrite(cs0, (row & 0x08));
digitalWrite(cs1, (row & 0x10));
// latch data
digitalWrite(le, LOW);
digitalWrite(le, HIGH);
digitalWrite(le, LOW);
digitalWrite(oe, LOW); // enable display
row = row + 1;
if ( row == 20 ) row = 0; // count row from 0 to 19
timer1_write(500);
}
Alles, was ich im main loop in verschiedenen Routinen (Zeit, Wetter, Muster, ...) in das displaybuf[] Array schreibe, erscheint dann auf dem LED-Netz.
Aktuell ist die Wifi Verbindung statisch konfiguriert (ESP8266WiFiMulti + feste SSIDs und Passwörter im Sketch).
Das Ganze wollte ich jetzt noch weiter verbessern, und den AsyncWifiManager einsetzen (AsyncWifi...., weil ich auch den ESPAsyncWebServer einsetze), damit der Wemos bei Bedarf zur Laufzeit mit den vor Ort gegebenen Wifi Daten "gefüttert" werden kann.
Allerdings habe ich das Problem, dass der ESP immer abstürzt, wenn sich der WifiManager erfolgreich mit dem WLAN verbunden hat - wenn es also in der Programmabarbeitung weiter geht.
Wenn ich den Timer Interrupt deaktiviere (im Setup auskommentiere), klappt das Ganze (kein Absturz + Reboot) - aber natürlich auch keine LED-Netz Ausgabe.
Scheinbar vertragen sich also WifiManager und TimerInterrupt nicht.
Kennt jemand das Problem?
Gibt es Lösungen dafür?
Beim Schreiben und Lesen ins/aus dem SPIFFS hatte ich auch solche Probleme.
Die umgehe ich einfach, indem ich bei dabei jeweils kurz den Timer Interrupt deaktiviere und im Anschluss wieder aktiviere.
P.S.
Falls der Code nicht profimäßig ist - nicht wundern.
Ich bin noch recht neu in der Materie.
Und falls jemand mehr zum Projekt wissen möchte - gerne fragen.
Viele Grüße
Daniel