Bug in Verbindung mit dem LED Ring und Multibutton

Hy,
Folgendes Verhalten ist mir in Verbindung mit dem dynamischen Buttonlayout aufgefallen.

  • Ich habe auf den Multibutton 23 (Play+Rotary) CMD_TELL_IP_ADDRESS gelegt
  • zusätzlich ist lange Rotary drücken immer noch Shutdown

Wenn ich Play+Rotary drücke, dann kommt der rote Countdown zum Shutdown auf dem Neopixel. Ich denke, dieser sollte gar nicht angezeigt werden, da die gewünschte Funktion nicht Shutdown ist.
Drückt man die Kombination kurz, erscheint der Countdown bis man die Tasten loslässt und danach funktioniert der LED-Ring auch normal.
Drückt man die Kombination so lange, bis der Kreis rot geschlossen ist, dann leuchtet der LED-Ring nur noch rot und reagiert auch nicht mehr auf andere Eingaben (Lautstärke, neue Karte, usw). Der ESPUINO verhält sich ansonsten (in beiden Fällen) bis auf den LED-Ring normal.
Da ich nicht weiß, ob ich mich verständlich ausgedrückt habe - hier ein Video:

Ich habe zwar versucht das selbst zu fixen aber naja . Ich habe zwar was in der LED.cpp gefunden aber dies dann doch nicht verstanden :worried:
Die LED Ansteuerung wurde zuletzt von @Joe91, @tueddy und @fschrempf überarbeitet, vielleicht haben sie eine Idee, wie man das Fixen kann

Hi Joker,
Ich habe den Fehler nachstellen können. Das Problem kommt von der Zeile 356 in Led.cpp, die Abfrage ist immer wahr, sobald alle LEDs rot sind und das System wird damit in der Animation gehalten (mit der Annahme, dass wir „eh schon bald schlafen gehen“).

Der Bug baut sich eigentlich aus 2 Bugs auf:

  1. Wenn eine Knopf-Kombination gedrückt wird, wo der Shutdown-Button inkludiert ist, wird die Countdown Animation gestartet.
  2. Wenn diese Animation „endet“ (d.h. alle LEDs rot sind) reagieren die LEDs nicht mehr

Den Bug 2 kann relativ einfach gefixt werden. Das sollte relativ schnell machbar sein, es braucht hier nur eine „Escape Bedingung“, wenn wir zB 1s nach intervalToLongPress noch immer da sind. Aktuell war ich noch mit dem Memory Leak beschäftigt, am Wochenende sollte ich aber Zeit haben eine Bugfix zu erstellen.

Der Teil 1 vom Bug ist leider systematischer und tiefer. Die Led.cpp hat bei der aktuellen Implementation nur ein „Blick“ auf den Shutdown-Button (über CheckForPowerButtonAnimation) und kann unterscheide, ob eine Kombination oder nur ein Button gedrückt wird.
Das wird eine größere Änderung in Button.cpp und Led.cpp sein, da wir die Logik wann die Shutdown Animation gestartet werden soll. Wie und wo genau, wir da hineingreifen sollten, kann ich ad hoc noch nicht sagen :slight_smile:

Gruß,
Laszlo

War doch einfacher als befürchtet. Eine Änderung in CheckForPowerButtonAnimation war für Punkt 2 notwendig (statt den currentState verwende ich jetzt den isPressed, der nur wahr ist, wenn nur das eine Button gedrückt ist).

Ich habe auch ein Schutz in die Animation eingebaut. Diese sorgt dafür, dass die Animation nach 150ms beendet wird, sobald die Taste losgelassen wird (und wir noch immer wach sind).

@joker kannst du die Branch testen, ob dadurch der Fehler auch bei dir gefixt ist?

https://github.com/laszloh/ESPuino/tree/bugfix/shutdown_animation

4 „Gefällt mir“

Hy @laszloh,
Wow vielen Dank. Ich teste das natürlich gern. Wird jedoch erst morgen. Ich gebe hier da auf jeden Fall ein Feedback.

An der besagten Zeile war ich auch mal aber irgendwie war ich dann der Meinung, dass ich Zeile 187 erst mal verstehen muss und da war es bei mir aus was hier mit „Sizeof“ gemacht wird.

Da kann ich gerne helfen. sizeof gibt dir die Gesamtgröße von einem Objekt zurück. Wenn du zB ein Array hast mit uint16_t x[3] gibt es dir sizeof(uint16_t) * n2 * 3 als 6 zurück.

Zeile 187 macht nicht anderes als zu berechnen, wie viele Elemente das Array gButtons hat. (sizeof(gButtons) / sizeof(gButtons[0])) übersetzt „Gesamtgröße des Arrays divitiert durch die größe des ersten Elements des Array“ → 112 / 16 → 7

Ein Trick, die c++ Erweiterung von VSCode berechnet dir automatisch sizeof’s unter der Maus und zeigt dir ein Tooltip an:

und er kann auch das Ergebnis der Rechnung anzeigen, du musst dich nur auf die richtige Klammer (bzw operator) stellen. Ab und zu ist es eine Spielerei, aber wenn es funktioniert recht nützlich :slight_smile:

1 „Gefällt mir“

Hallo @laszloh,
ich bin leider nicht eher zum Testen und Antworten gekommen.
Vielen Dank für deine Hilfe und für deine Erläuterung von sizeof(). Die Grundzüge hatte ich nach googln auch verstanden. Ich hatte glaube vielmehr ein Verständigungsproblem warum dies gemacht wird - naja ich brauche wohl noch etwas um den Code zu verstehen bzw. meine Programmierkenntnisse aufzubessern :slight_smile:

Ich habe deine Änderung getestet. Es kommt keine Shutdownanimation mehr und der LED-Ring hängt sich auch nicht mehr auf. Ansonsten verhalten sich die LEDs wie immer. Ich bin dir wirklich sehr dankbar. Die Änderungen sind ja wirklich minimal, ich bin mir aber nicht sicher ob das bei mir rausgekommen wäre.

Nach dem Drücken kommt es zu einer Zwischenanzeige. Alles Rot, wenn keine Karte aufgelegt wurde oder alles grün, wenn eine Karte aufgelegt wurde. @biologist was sagt das aus bzw. ist das gewollt? Hier ein Video dazu

Vom Design her, sollte immer ein grüner Kreis angezeigt werden, sobald der Befehl CMD_TELL_IP_ADDRESS empfangen wird und der ESP32 mit einem WLAN verbunden ist (wenn er keine IP hat → roter Kreis / Fehler).

Den fälschliche roten Kreis (LedIndicatorType::Error) konnte ich zu Audiplayer.cpp:391 zurückverfolgen. Der setzt den Fehler-Indikator, wenn ein trackCommand empfangen wird, aber aktuell keine Wiedergabe statt findet. Das ist auch OK so, zB Fehlerindikator soll ja auch komen, wenn gerade nicht abgespielt wird und der Button mit CMD_PLAYPAUSE gedrückt wird.

Der Schuldige für den Aufruf ist hier:

Die einfachste Lösung ist die Zeilen 277-279 auszukommentieren / zu löschen. Sie haben kein Einfluss auf das Verhalten des Systems, da wir die letzte RFID Karte wieder an uns senden, sobald ide IP Wiedergabe beendet ist, siehe AudioPlayer.cpp:717.

Ich habe die Branch bei mir mit der Änderung aktualisiert.
Gruß,
Laszlo

1 „Gefällt mir“

Hy Laszlo,
Vielen Dank für die schnelle Antwort.
Ich werde das heute Abend mal testen.

Wer weiß, warum die Zeile damals eingefügt wurde.

Ich habe Sa noch eine Verständnisfrage, wie macht man das debugging.
Im Netz lese ich immer, dass die das über den Jtag machen - ich vermute jedoch, dass wir die Pins für andere Sachen verwenden. Gibt es noch eine andere Möglichkeit bzw nach was muss ich suchen, wenn ich mich aufschlauen möchte?

Das hat super funktioniert - Danke

Ich habe keine Probleme mit der auskommentierten Zeile gehabt

Hallo Joker,
Debuggen am Besten mit JTAG :slight_smile:. Leider funktioniert das bei ESPuino nicht, da JTAG und SD_MMC die gleichen Pins verwenden und ESPuino ohne SD-Karte nicht viel macht (und eine SD-Karten Emulation wäre eine echte Herausforderung :slight_smile:.
Auch habe ich JTAG mit dem ESP-PROG Adapter bisher nur unter Linux stabil zum Laufen gebracht.

Bis jetzt bin ich den klassischen Arduino Weg des debuggen gegangen, Code anschauen und an den relevanten Stellen mit Serial.println / Serial.printf versehen.

Ein weiterer Trick ist, wenn du raus finden möchtest, wer eine Funktion aufgerufen hat (zb gibt es sehr viele Aufrufe zu System_IndicateError) ist in dieser ein assert(<bool Bedingung die false sein muss>) (zB assert(0) für alle Aufrufe, oder wenn einem x == 5 interessiert assert(x != 5) ) zu platzieren. Wenn der Ausdruck von assert 0 wird führt es zu einer Exception und der Stack-Trace verrät die aufrufenden Funktionen.

@biologist Ich mache heute Abend ein PR mit den beiden Fixes auf der dev-Branche bereit.

Gruß,
Laszlo

2 „Gefällt mir“

Hallo Laszlo,
vielen Dank für deine ausführlichen Antworten.
Leider habe ich den Inhalt deiner Antwort befürchtet. Irgendwie hatte ich gehoft, dass es einen speziellen Debugmodus gibt oder am Breakpoint oder ähnliches setzen kann - was weiß ich.
Okay, da werde ich das nächste mal mein Glück versuchen bzw. da meinem Wissen noch etwas nachhelfen.
VG Mirko