Matrix in C

  • Hi ihr,
    ich bins wieder mal seit langem, eure Nervensäge!
    Da ich Zeit und Lust habe wollte ich mal meine 5^3 Matrix reparieren und bin zum Schluss gekommen, mein Mega16 ist tot.
    Bis ich einen neuen habe möchte ich versuchen ein C Prog zu machen um die Dinge möglichst einfach anzusteuern.
    Da ich aber dank der langen Pause mit dem Lernen neu anfangen musst bin ich nicht so gut, und wollte fragen wie ich das am besten anstelle.
    Einzeln die Portpins auf High zu setzen ist ja unschön und viel arbeit.
    Wollte es mit einem Array int LED[5][5][5] machen, aber da kann ich ja eig nur die BIT-sequenz Speichern, leider aber ohne die PORTs, außerdem müsste ich ja für Ebene und Säule meiner Matrix 2 Dinge einspeichern.
    Ich würde am liebsten LED[1][2] [3] eingeben und wissen: aha, jetzt wird die LED ausgeben, die auf der x_1 Achse an stelle 2, x_2 Achse an stelle 3 und x_3 Achse an stelle 4 ist (da beim array ja bei 0 angefangen wird zu zählen).
    Ich bitte um keinen Code, aber vielleicht um ein Stichwort nachdem ich suchen kann, damit ich drauf komm.
    Möchte C lieber "praktisch" lernen, um die Motivation nicht zu verlieren.
    Wie gesagt, ich will in dem array 2 Pin-sequenzen speichern, als z.b. PORTB=0b00001010 ; PORTC=01000101; .
    und dann irgendwie versuchen das ganze flimmern zu lassen (das Fachwort ist mir entfallen :P ).


    Würde mich freuen!


    Grüßle

  • Naja ne Matrix/Cube schreit ja eigentlich nach nem 2-dim/3-dim Array. Und soweit wie ich mich jetzt da eingearbeitet hab musst du ja für die Bitsequenzen nen Struct erstellen. Wenn du jetzt das 2-dim/3-dim Array von dem Struct erzeugst kannste ja quasi mehrere Infos für ein Feld speichern.


    Nur mal zur Anschauung:



    die einzelnen Felder, bzw die Werte in den Feldern dann einfach mit
    Feld[x][y][z].Port....etc ansprechen.


    Ich hoffe ich hab die Frage richtig verstanden und das war jetzt nicht nur verwirrend^^


    Mfg Seb

  • Entweder, du verpackst die Zustände der einzelnen LEDs in ein Bitfeld (geht das eigentlich mit mehreren Dimensionen?), was aber die Anzahl der LEDs stark einschränkt (Bei Visual C z.B. sind es max. 32 Bit in einem Feld) oder du spendierst jeder LED ein ganzes Byte und verpackst die in ein mehrdimensionals Feld (da kann man dann auch die Helligkeit hinterlegen; für ein- und ausschalten ist das Platzverschwendung) oder, was ich persönlich vorziehen würde, du lagerst die Abbildung, welche LED an- oder ausgeschaltet werden soll und wie das im Speicher organisiert ist in eine eigene Funktion aus. Du würdest also nicht mehr direkt in das Feld schreiben, sondern der Funktion sagen, welche LED an- oder ausgeschaltet werden soll und die Funktion sorgt dafür, dass das im Speicher korrekt abgelegt wird.
    Die Funktion zur Ausgabe des Musters greift natürlich direkt auf den Speicher zu.

  • Danke für die Antworten!
    Also persönlich hätte ich es ja so gemacht, dass ich ganz viele #defines geschrieben hätte, wobei jedes define eine LED multiplext, dann eben 125 mal schreiben, eventuell noch für die ebenen und Diagonalen einzelne Befehle und dann eben fertig.
    Das Problem hier ist eben, dass ich , wenn ich z.b. sagen will, LED1 an, LED2 an, LED1 aus, dass das ja nicht geht.
    Da ich ja multiplexen will hab ich ja das Problem, dass diese "flackern" ja ne schleife ist, die ja nicht durbrochen wird?


    Admiralawesome:
    Kannst du vielleicht ein Beispiel machen, da ich mich noch nicht so mit Arrays auskenne


    Mirfaelltkeinerein:
    Klingt eigentlich am schönsten, aber wie gesagt wäre auch hier vielleicht ein Beispiel nett


    Grüßle
    Martin


    edit:
    Habe mich auhc mal probiert, und wollte fragen wie ich am besten 125 Bit als Variablen haben könnte, sprich dieses struct mit einem 5³ array drin.
    Danach würde ich gern alle Bits auf 0 stellen, wie ginge das?

  • Bitfeld meinte ich nicht Bitsequenz. Und wenns mit einem Struct implementiert ist, geht auch ein Array.
    Mein Wissen beschränkt sich zwar auf C++, aber C ist wie ich gesehen habe im großen und ganzen ja doch das gleiche.
    Also kleiner kompakter Struct und Array Exkurs.
    Nehmen wir an eine Led kann folgenden Sachen:


    Sie hat Koordinaten in einer Matrix. Sie hat den Zustand ihrer Farbe und Helligkeit. Einfach jetzt mal als Integer.
    Man erstellt zu erst ein Struct "Werte". ein Struct ist so was ähnliches wie eine Klasse nur sehr vereinfacht.


    struct Werte {
    int Farbe;
    int Helligkeit
    };


    einfach vor main definieren.
    Um eine Struct zu benutzen muss er initalisiert werden. Die geschieht indem man eine Variable davon erzeugt, bzw einen in unserem Fall ein Array.


    Werte led; // erzeugt eine Variable led vom Typ Werte.


    gleiches mit Arrays.


    Werte led[9]; //Array mit 10 Feldern.


    In jedem dieser 9 Felder kannst du nun die Werte "Helligkeit" und "Farbe" der led abrufen wenn du sie vorher dort eingespeichert hast.
    Für mehrere Dimensionen das gleiche.
    Um jetzt z.B. in ein Feld zu schreiben oder es zu lesen, benutzt du es einfach wie ne normale Variable:


    Z.B. Den Wert Farbe mit 200 und den Wert Helligkeit mit 400 für die Led (3,6,5) setzen.


    led[3][6][5].Farbe=200;
    led[3][6][5].Helligkeit=400;


    Da die Koordinaten natürlich auch Schleifenvariablen sein können z.B. kannst du ein dreidimansionales Array einfach mit drei verschachtelten Schleifen füllen. Wie das ein Mikrocontroller so findet sei mal dahin gestellt. Ich kann dir mal noch die Seite von unserem Dozenten ans Herz legen, da stehen halt so ein paar Grundsachen drin. Is leider C++ aber es is wie gesagt fast gleich, vll. hilft es manchmal.

  • Hab es mal Probiert wie du es gesagt hast(Codeausschnitt):


    Das Problem ist, dass ich eine Fehlermeldung vom Compiler bekomme.
    Selbst wenn es funktionieren würde:
    Wie krieg ich hin, dass mein "t" nun 128 Bit hat, dass jeder int vom array ein bit sein kann?
    Wie mach ich, dass alle 125 dann auf 1 Bit gesetzt werden (mein Code würde ja nur t.a[0][0][0],t.a[0][0][0],t.a[1][1][1],t.a[2][2][2],t.a[3][3][3],t.a[4][4][4] auf ein Bit setzen?
    Wie weiße ich jedem dieser Bits dann den Wert 0 zu? (In meinem code sind ja nur 2 stk null gesetzt, wobei eine Fehlermeldung kommt, das es t nicht gibt?

  • Wie krieg ich hin, dass mein "t" nun 128 Bit hat

    char data[16];


    char ist immer 1 Byte groß, also 8 Bit -> 128 / 8 = 16.


    Wie weiße ich jedem dieser Bits dann den Wert 0 zu?

    memset(data, 0, 16);


    Du musst dir dann nur noch eine Funktion basteln, die dir für die Eingabewerte x, y, z dann das richtige Bit + die richtige Arrayposition ausgibt. Das machst du im Grunde einfach alles mit den Bitoperatoren |= &= ~ << >>.


    Gepeichert wird dann in data quasi "Bit gesetzt -> LED an, Bit nicht gesetzt, LED aus". Wenn du noch Helligkeiten und Farbe speicher musst, musst du das natürlich erweitern.

  • Danke für die Antwort!
    Also würde es vielleicht so gehen (Ich hab mal schon voraussgesetzt, dass z.B. LED1 bedeutet, dass eben die Ports so belegt sind, dass die LED leuchtet.
    Wobei ich dann eben, in meinem fall, eine variable will, die die LED wieder ausschaltet.


  • Wieso ist da ein struct in einer Schleife drin (redefine-Fehler)? Was soll das char a[5][5][5] zu Beginn? Warum nimmst du nicht einfach ein Byte für eine LED-Reihe (so wie die auch an die Ports angeschlossen sind, alle die gleichzeitig angesteuert werden)? Das verschwendet zwar einige Bits, vereinfacht aber die Ausgabe sehr stark, ohne dass man das Ausgabewort erst zusammen bauen muss.

  • Also der Struct in der Schleife macht mich irgendwie stuzig. Ich würd ihn der übersicht halber mal auch nicht "int" nennen. Deklarier den Struct mal vor deiner "main-methode". Füllen kannst du das Array dann mit der for-schleife. und wenn du ein 3-dim-array füllen willst brauchst du 3 for schleifen.



    So würde beispielsweise dein komplettes Array erstmal mit ner 1 gefüllt.

  • Irgendwie fehlt da noch ne wichtige Information: Was brauchst du den pro LED? Soll die nur ein- und ausgeschaltet werden oder soll sie unterschiedliche Helligkeitsstufen (wenn ja wie viele) annehmen koennen.


    Im ersteren Fall nimmst du pro Zeile ein Byte (von dem du die oberen 3 Bits nicht benutzt). Dann brauchst du nur ein 2 dimmensionales Array und kannst diese Byte direkt an den entsprechenden Port zuweisen - vorrausgesetzt die Hardware sieht entsprechend aus.


    Bei mehr als einer Helligkeitsstufe musst du ein Bild mehrfach anzeigen und dann ab und zu die dunkleren LEDs auslassen. Keine Ahnung wie viele Durchlaeufe dein Atmega schafft. Das ist jedenfalls die maximale Zahl der moeglichen Helligkeitsstufen. Da waere es dann wichtig, dass du nicht jede LED einzel ansteuerst, sondern die Belegung einer Zeile ausrechnest und dann die ganze Zeile anzeigst. So kommst du auf eine hoehere zeitliche Aufloesung - und eine hoehere Helligkeit.
    Wenn du was in diese Richtung vor hast solltest du dir dringend die bitweisen Operatoren nochmal anschauen. Also & | << >>


    Fabi

  • Ich versuchs nochmal neu zu scripten,
    aber erstmal hier wie die Pins angeschlossen sind:
    Säule1 -Säule8 : PA0-PA7
    Säule9 -Säule16 : PC0-PC7
    Säule17-Säule24 : PD0-PD7
    Säule25 : PB0


    Ebene1: PB1
    Ebene2: PB2
    Ebene3: PB3
    Ebene4: PB4
    Ebene5: PB5


    Wobei ich die Säulen von links nach rechts zähle, und wenn die ersten fünf "abgezählt" sind, geht es in der nächsten Reihe wieder links los.
    Sprich: links hinten LED1, rechts vorne LED25.
    Ist ein ATmega16, wobei eben jeweils bei Ebenenbit auf high und Säulenbit auf high eine LED leuchtet.
    (Wobei 4Säulen nicht funktionieren, weil der Mega16 tot ist....eigentlich funzt alles, aber die Pins wollen nicht, ich hab die LEDs ohne avr getestet, und da gings!)


    Grüßle

  • Wie, Ebenenbit auf high UND Säulenbit auf high? Du meinst wohl eher EbenenPORT/-ausgang auf high und SäulenPORT/-ausgang auf high. Aber aus der Anschlussbelegung ergibt sich doch schon fast automatisch die Datenstruktur. Entweder eine zweidimensionales Feld mit 5 Elementen für die Ebenen und vier Elementen für die vier Ports der Säulen (wobei von PB nur PB0 verwendet wird, beim Portbits setzen aufpassen), oder ein eindimensionales Feld mit fünf 32-Bit-Worten. In den 32-Bit-Worten stehen in den unteren 25 Bit die Daten für die kompletten Ebenen drin.
    Jetzt brauchst du nur noch eine Routine zum einfachen Erzeugen der Daten. Entweder offline auf z.B. einem PC, oder online, die von Linienroutinen oder so was aufgerufen wird. Irgendwas in der Form 'SetPixel(Zeile, Spalte, Ebene)' und 'ClearPixel(Zeile, Spalte, Ebene)'. Diese Routinen sorgen jetzt dafür, dass an die richtige Stelle im Datenfeld ein Bit gesetzt oder gelöscht wird.

  • Man kann aber auch trotzdem 5x5 Arrays nehmen und die Bits dann on the fly richtig hinschieben


    Also


    Edit: muss natuerlich "img[h][4] << 4" heissen.

  • Versteh' ich nicht. Kannst du das mal kommentieren?


    There are only 10 types of people: those who understand binary and those who don't.

    Doh! Wie waere es wenn du dir ne neue Signatur suchst!


    In Img ist ein Bild gespeichert. Immer 5 Bits in einerm char ergeben eine Zeile. 5 chars ergeben eine Ebene, 5 Ebenen ergeben den ganzen Wuerfel. Um den Wuerfel anzuzeigen werden in der Schleife die Ebenen durchlaufen. Die Bits in den einzelnen Zeilen werden dann mit << und >> an die richtige Position im Port geschoben und dann mit | (binaeres oder) uebereinander gelegt. Der Code geht davon aus, dass in img immer nur die unteren 5 Bit belegt sind - also nur Werte <= 0x1F drinstehen, sonst werden die 3Bits der Zeile dahinter ueberschrieben oder sogar zusaetzliche Ebenen ausgewaehlt. Zu guterletzt wird in PB noch die aktuelle Ebene aktiviert.


    Da muss jetzt natuerlich noch ne Schleife drumrum, die durch die Bilder der Animation durchwechselt und dann immer kurz wartet.


    Fabi

  • Die Frage war auch weniger für mein eigenes Verständnis gestellt...

    In Img ist ein Bild gespeichert. Immer 5 Bits in einerm char ergeben eine Zeile. 5 chars ergeben eine Ebene, 5 Ebenen ergeben den ganzen Wuerfel.
    ... Der Code geht davon aus, dass in img immer nur die unteren 5 Bit belegt sind - also nur Werte <= 0x1F drinstehen, ...

    ... und diese ja nicht ganz unwichtige Information hat gefehlt. Eine gewisse Beschreibung ist auch für Profis hilfreich, weil man dann nicht erst die Logikoperationen nachvollziehen muss, um rauszubekommen, was wirklich passiert.


    M.E. nach kann man das natürlich so machen, verliert durch die schieberei aber bei jeden Frame unnötig Zeit, weil man gleich passend speichern könnte.
    Dieses Verfahren ist hilfreich, wenn man sich die Figuren mit einem Hexeditor generiert, aber wer macht das schon...

  • Oder wenn man die Figuren algorithmisch generiert. Dann wird man aber u.U. die 5x5 Arrays vor dem Abspielen mit diesem Code in 5x32Bit konvertieren und dann so speichern.


    Fuer ein solch einfache Anwendung ohne Graustufen sollte die Performance eh noch keine Rolle spielen. Wenn es um Graustufen geht braucht man eh nochmal ganz andere Datenstrukturen...


    Fabi