LED Matrix Schleife hängt

  • Hallo Zusammen.

    geht mal wieder um das Bier Pong Projekt
    Ich bin wieder einmal an die Grenzen meiner Programmierkünste gestoßen.
    Ich möchte in meiner nxm Matrix einen Array mit allen Randpixeln erstellen. Die Reihenfolge ist wichtig (im Uhrzeigersinn)
    Ziel ist, den Array anschließend durchzulaufen und eine LED nach der anderen anzuschalten.
    Mit einem hardgescriptetem Array wie bspw. dieser klappt das:

    Code
    uint8_t tmpArray[28] = {0,1,2,3,4,5,6,7,8,23,24,39,40,55,56,57,58,59,60,61,62,63,48,47,32,31,16,15};


    Grund für diese seltsame Nummerierung ist das Serpentinen Layout des Strips.
    Ich habe eine Schleife geschrieben um den Array zu initialisieren, diese hängt sich aber irgendwie immer auf. Ich finde den Fehler einfach nicht:


    Vielleicht findet ja einer von euch den Grund, warum die Funktion dazu führt, dass der Nano sich aufhängt.

  • Hallo hamyam,
    auf den ersten Blick sehe ich keinen Fehler (außer dass die Funktion ziemlich viel RAM-Speicher braucht!)
    Für die Analyse würde ich die serielle Ausgabe verwenden. Mache einmal am Anfang vor allem eine Ausgabe, dann nach jeder Schleife.

    Gruß
    Chris

    PS: Einen (doppelten) Fehler entdeckt ;) Du versucht einen Pointer auf ein Array im Stack zurückzugeben von einer Funktion, die keinen Rückgabewert hat (void).
    PS2: Warum rechnest du dir die nächste LED-Nummer nicht immer zur Laufzeit, das spart einige Byte Arbeitsspeicher

    PS3: hast du schon mal dran gedacht, das Serpentinenlayout für dein Programm in ein Array-Layout zu überführen? Das könnte die Entwicklung vereinfachen, also immer von einer Matrix ausgehen und erst bei der Ausgabe das neu „ordnen“

    Einmal editiert, zuletzt von ChrisvA (20. September 2016 um 13:59)

  • auf den ersten Blick sehe ich keinen Fehler (außer dass die Funktion ziemlich viel RAM-Speicher braucht!)
    Für die Analyse würde ich die serielle Ausgabe verwenden. Mache einmal am Anfang vor allem eine Ausgabe, dann nach jeder Schleife.

    Ja das mit der Ausgabe werde ich heute Abend mal testen.
    Wieso die Funktion viel Ram verbraucht ist mir aber nicht klar. Vielleicht ist das aber mit dem übernächsten Punkt verknüpft.

    PS: Einen (doppelten) Fehler entdeckt ;) Du versucht einen Pointer auf ein Array im Stack zurückzugeben von einer Funktion, die keinen Rückgabewert hat (void).

    Ups, ja natürlich. Ich habe die Funktion aus einer alten Version kopiert. Mist.
    Die tmpArray Variable wird (jetzt) schon vor der Funktion initialisiert. Die Funktion soll dann nur noch beim Setup beim Start einmalig ausgeführt werden. Dann liegt nur der Array im Arbeitsspeicher. Der sollte aber doch nicht so viel RAM verbraten, oder?


    PS2: Warum rechnest du dir die nächste LED-Nummer nicht immer zur Laufzeit, das spart einige Byte Arbeitsspeicher

    Den Punkt verstehe ich nicht. Das Skript soll auch auf Matrizen anderer Breite/Höhe laufen. Mit Hilfe dieser Funktion wird dann ein Array mit den LED des Randes erstellt; Egal welche Größe die Matrix hat (in den Schranken muss 2 dimensional sein und nicht mehr als 255x255).
    Mit diesem Array kann man dann anschließend sehr einfach den gesamten Rahmen ansteuern. Das ist für Animationen sehr hilfreich.
    Beispiel: Ein Punkt der im Uhrzeigersinn am Rand entlang läuft. Immer ein Pixel nach dem anderen.


    PS3: hast du schon mal dran gedacht, das Serpentinenlayout für dein Programm in ein Array-Layout zu überführen? Das könnte die Entwicklung vereinfachen, also immer von einer Matrix ausgehen und erst bei der Ausgabe das neu „ordnen“

    Mein Programm berücksichtigt schon das Serpentinenlayout. Die x,y Koordinaten werden dann erst beim Setzen der Pixel in int Werte umgerechnet.

    Da die Funktion aber nur einmalig beim 'booten' ausgeführt wird spare ich mir alle Rechenleistung im späteren Verlauf für den Aufruf des Randes. Außerdem gibt es in der Bibliothek die ich nutze (FastLED) eingebaute Funktionen, welche speziell auf ganze Arrays von LED angewendet werden können.

    Fürs debugging fällt mir dann erstmal nur der Serielle output für jeden Schritt ein. Mal sehen....

  • Hallo Hamyam,
    das mit dem Ram hatte ich falsch im Kopf, dachte der ATMega hat nur 128Byte Ram (sind aber 2048), da wären die 28Byte für das Array schon einiges gewesen, da er aber 2K hat, sollte es kein Problem sein, entsprechend wird auch "PS2" obsolet, das wäre auch nur ne Optimierung gewesen, um zwar zur Laufzeit weniger zu rechnen, dafür deutlich weniger Ram zu verbrauchen.
    Da du auf die Library FastLed setzt, fällt auch mein "PS3" weg, die Idee war, im Programm für die LED in der normalen Rechteckform (ohne Serpentinen) zu sehen und das erst bei der Ausgabe on the fly umzuwandeln.
    Gruß
    Chris

    PS: zum debuggen kannst du die Fuktion auch lokal in einem C Programm ausführen, sollte ja das Selbe rauskommen...

    Edit: Die rechnung im Index von tmpArray, z.B. (xMatrix-1+yMatrix-1+xMatrix-1), ist unabhängig von i, das kann nicht sein!

    Einmal editiert, zuletzt von ChrisvA (20. September 2016 um 15:39)

  • Code
    }
     if(xAction == 2 && yAction == 0){
      for(uint8_t i = (xMatrix-1); i >= 0; i--){
       tmpArray[(xMatrix-1+yMatrix-1+i)] = XYsafe(i, yPos);
      }
      xAction = 0;
      yAction = 2;
      xPos = 0;
     }

    Guten Morgen zusammen.

    Ich hab dank des debugging mit Serial.print(); den Fehler gefunden.
    Er versteckt sich in dieser Schleife oben:

    uint8_t hat einen Definitionsbereich von 0-255. Die Anweisung läuft solange i >= 0 ist.
    Da i aber nur Werte >= 0 annehmen kann habe ich mir eine schöne versteckte Dauerschleife gebastelt.

    Ich habs korrigiert und auch das Schema an sich ein wenig verbessert. Ich poste die Ergebnisse im Laufe des Tages :)

  • So hier der vollständige Code



    Die Logik dahinter:

    Ach ja, noch chris


    Code
    // Der Sketch verwendet 4.492 Bytes (14%) des Programmspeicherplatzes. Das Maximum sind 30.720 Bytes.
    
    
    // Globale Variablen verwenden 169 Bytes (8%) des dynamischen Speichers, 1.879 Bytes für lokale Variablen verbleiben. Das Maximum sind 2.048 Bytes.

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!