@Thorsten
Habe mich die Tage mal durch den Code der „alten“ Version gegraben und versucht kleine, einfache Ergänzungen zu machen. Einfache „Hintergrunddienste“. Also eigentlich banale Zyklische Abfragen: wenn das, dann das. Z.B. sowas wie Status LED’s aktualisieren, blinken, faden und zustandsabhängige Aktionen. Oder Abfrage einer IR Schnittstelle. Sowas hängt man eigentlich nur unten in die Main Loop, fragt die Triggerbedingung zyklisch ab und es läuft so nebenher mit.
Dabei hatte ich ziemlich zu kämpfen. Insbesondere mit den Nebenwirkungen des Admin Menüs. Hat man das mal betreten, fängt sich das Menü gerne in internen Warteschleifen (do loop until Tast x). In der Zeit wir die Main Loop für längere Zeit schlicht nicht mehr abgearbeitet. Es gibt also auch keinen Ort mehr, von dem man weiß, dass der regelmäßig abgearbeitet wird für all diese Hintergrundaktualisierungen.
Ein schönes Beispiel, wo das schon mal aufgefallen sein muss ist z.B. der set und checkStandbytimer, oder die readButton Funktion. Eigentlich alles Funktionen die hinten in der Main Loop liegen und einfach in jedem Zyklus einmalig aufgerufen werden müssten, um konsistent für den gesamten Durchlauf die Buttons zu aktualisieren, oder eben die Standbyfunktion oder andere Timeouts zu überwachen. Statt dessen tauchen die Aufrufen an diversen Stellen im Code auf. Derjenige, welcher den Standby implementiert hat, wir ne weile gebraucht haben um alle Stellen zu finden, an denen er den Timer Triggern muss. In der Loop wäre das simpel gewesen. Zurücksetzen wenn beliebiger Button oder isPlaying.
Sowas kann z.B. bei den Mehrfachaufrufen von readButtons fiese Nebeneffekte mit sich bringen. Beim ersten Lesen am Anfang der Loop war es noch kein Long pressed, 100 Takte weiter in einem anderen Zweig mit erneuter Aktualisierung ist es dann doch einer?!
Daher möchte ich für das Redesign vorschlagen, dass man sich auferlegt, auf delays oder Warteschleifen zu verzichten um sicher zu stellen, dass die main loop zuverlässig zyklisch durchlaufen wird. Statt dessen würde sich ein Zustandsautomat anbieten. Wenn die Weiterschaltbedingung nicht erfüllt ist, dann guckt man halt im nächsten Zyklus wieder. Dann kann der Prozessor in der Zwischenzeit was sinnvolles tun, oder sogar schlafen gehen.
Habt Ihr in Erwägung gezogen den Sleepmode des ATMEL und den PinChange Interrupt zu nutzen?
Weiß jemand, ob sich schon einer die Mühe gemacht hat, das Admin Menü auf Zustandsautomat oder ähnliches umzustellen? Bei dem ganzen If else while do ist mir ganz schwindelig geworden ;o).
Hab mal gespickt, gibt interessante Bibliotheken dafür:
Sehr einfach: Zustände mit Transitionen (Wechselbedingung) GitHub - jrullan/StateMachine: State machine library for Arduino
Advanced: Zustände mit Transitionen + Enter und Exit Methode. GitHub - jonblack/arduino-fsm: Arduino library for implementing a finite state machine.
Die Enter Methode kann insbesondere interessant für das Admin Menü sein, um hier einmalig die Audioansage für den Zustand zu triggern.
Und super spannend klingt dieses Paket. GitHub - tinkerspy/Automaton: Reactive State Machine Framework for Arduino
Bis wann kann man denn mit einem ersten Release der neuen Version rechnen?
MfG, Nick