4x4x4 LED Cube programmieren

  • Hallo !


    Ich schaue mich hier schon länger im forum um und habe mir viele Infos zum bau eines led cubes geholt.
    Am Anfang hatte ich noch keine Ahnung wie ich mir so ein Cube bauen soll. Hatte noch null Löterfahrung geschweige denn Ahnung von den Komponenten die ich brauchte.
    Habe mich dann etwas Informiert was ich so brauche und die Teile bestellt. Nach ca. 2 Monaten hatte ich ihn dann fertig zusammen gebaut und stand schon vor dem nächsten Problem - wie programmiere ich das ding ?
    Nach einiger Zeit googlen und youtube filme schauen installiere ich mir Atmel Studio 6 und programmierte meine erste Animation.



    Code:



    Jetzt zu meiner eigentlichen Frage:
    Wie kann ich diesen code schöner und kleiner schreiben? Ich habe mir auch schon ein Buch über c++ gekauft, bringt mich aber nicht wirklich weiter. Könnt ihr mich ein wenig unterstützen? Oder hat jemand einen einfach geschriebenen code wo ich etwas abschauen kann?
    Ist es möglich jeder einzelnen led eine Nummer zuzuweisen? Oder wäre es machbar z.B. dem PORTA=0b00000001 und PORTD=0b10000000 die Nr. 1 zu geben ?


    Wenn ich es schaffe mein Cube "richtig" zu programmieren schreibe ich ein komplettes Tutorial über den zusammenbau und der programmierung.
    Ich weiss es gibt schon einige tuts, jedoch wurde ich nicht immer schlau daraus.
    Mein Tutorial soll so einfach wie möglich werden, damit es auch Leute verstehen die nichts mit elektronik und programmierung am hut haben.

  • Hallo lynex,


    Der Cube sieht toll aus! Gerade dafür, dass das deine ersten Löterfahrungen sind, Respekt!


    Es wäre gut, wenn du den Schaltplan posten könntest. Oder sonst wie du die Led´s an den Microcontroller angeschlossen hast und welchen Microcontroller du verwendest.



    Gruß Stefan

  • Danke für dein Lob :)
    Ich selbst bin mit dem Resultat nicht ganz zufrieden, daher überall zuviel Lötzin drauf ist. Denke aber fürs erstemal ist es Akzeptabel.


    Uups! Das habe ich doch glatt vergessen!
    Es ist ein Atmega32 verbaut. Ich habe nur von Hand ein Schaltplan gezeichnet und leider nie einen mit Eagle erstellt. Bin erst nächste Woche wieder zuhause, sonst könnte ich ihn einscannen.
    Jedoch kann ich sagen welche Ports ich verwendet habe.


    Die vier Ebenen (Kathoden) sind über die Transistoren auf PortD 4-7 angeschlossen.
    Auf PortA 0-7 und PortC 0-7 die 16 "Säulen"


    Hoffe das Hilft weiter :D

  • Ich habs mit dem Programmieren zwar auch nicht so vollends drauf...aber:


    Kann das sein, dass du alle Kathoden gleichzeitig schaltest? Normalerweise tust du ja Multiplexen. Deine Variante is zwar einfacher zu programmieren aber du kannst so halt nur ganze Säulen ansprechen.

  • Normalerweise machst du das so:
    Daten für untersten Layer (deine 16 LEDs) in Ausgänge schreiben -> Kathode 1 durchschalten (8ms durchgeschaltet lassen) -> Kathode 1 auf low -> Daten für Layer 2 in Ausgänge schreiben -> Kathode 2 durchschalten (8ms durchgeschaltet lassen) -> Kathode 2 auf low -> Daten für Layer 3 in Ausgänge schreiben -> Kathode 3 durchschalten (8ms durchgeschaltet lassen) -> Kathode 3 auf low -> u.s.w.



    Ein Durchlauf dauert so etwa 33ms..was einer Bildwiederholrate von 30Hz entspricht. Dadurch dass das so schnell geht sieht dein Auge ein stehendes Bild (die LEDs erscheinen dir allerdings dunkler, da sie ja nur 1/4 der Zeit an sind). Wenn du jetzt das Bild z.b. 1s Sekunde darstellen willst musst die den Vorgang einfach mit einer Schleife 1000ms/33ms=30 mal durchlaufen. Ich hoffe es war halbwegs verständlich^^

  • Ich würde auch für die 16 LEDs pro Layer jeweils einen Transistor spendieren. Die Portpins bei den Atmels dürfen maximal mit 70mA insgesamt belastet werden.
    Wieviel mA kriegt eine LED bei Dir ab?

  • Riroithi
    Danke für die Links :)
    Schaue mich gleich mal durch. evtl. bringt mir sein code von der Seite etwas.


    Normalerweise machst du das so:
    Daten für untersten Layer (deine 16 LEDs) in Ausgänge schreiben -> Kathode 1 durchschalten (8ms durchgeschaltet lassen) -> Kathode 1 auf low -> Daten für Layer 2 in Ausgänge schreiben -> Kathode 2 durchschalten (8ms durchgeschaltet lassen) -> Kathode 2 auf low -> Daten für Layer 3 in Ausgänge schreiben -> Kathode 3 durchschalten (8ms durchgeschaltet lassen) -> Kathode 3 auf low -> u.s.w.



    Ein Durchlauf dauert so etwa 33ms..was einer Bildwiederholrate von 30Hz entspricht. Dadurch dass das so schnell geht sieht dein Auge ein stehendes Bild (die LEDs erscheinen dir allerdings dunkler, da sie ja nur 1/4 der Zeit an sind). Wenn du jetzt das Bild z.b. 1s Sekunde darstellen willst musst die den Vorgang einfach mit einer Schleife 1000ms/33ms=30 mal durchlaufen. Ich hoffe es war halbwegs verständlich^^

    Dann sieht mein code so aus:



    Bei 8ms flackert der Cube extrem stark, darum habe ich auf 3ms verkürzt. Wobei ich mir gleich die nächste Frage stelle.
    Warum musste ich auf 3ms verkürzen? Hat es etwas mit dem Quarz zutun? Ich habe einen 16MHz (HC-18U/49U) verbaut. Muss ich da noch etwas einstellen? Ich wollte mal die Fusebits setzen... Weil ich bei den vielen Tutorials nicht ganz durchblickte zerschoss ich bereits einen atmega32.


    Wenn ich alles so wie oben programmiere wird der Code elend lang, unübersichtlich und ist mühsam um Animationen zu programmieren. Da gibt es bestimmt eine elegantere Lösung.


    Shuzz


    Warum sollte ich noch weitere Transistoren einbauen? Bringt in meinen Augen nichts oder verstehe ich da was falsch?



    Konnte heute meinen Schaltplan einscannen. Ist leider nur eine Skizze, hoffe man erkennt etwas.
    [Blockierte Grafik: http://img18.imageshack.us/img18/8676/7glh.jpg]


    Uploaded with ImageShack.us

  • Hey lynex,


    wenn du einen 16 Mhz Quarz benutzt, dann musst du auch im C Code 16Mhz schreiben:

    Code
    1. #define F_CPU 16000000UL


    Die Funktion "_delay_ms" benutzt den Wert um die richtige Zeit zu warten.
    In den Fusebits musst du dann auch auf "Ext. Cristal/Resonator High Freq. stellen. Sonst nimmt der Standart mäßig den Internen.


    Die Transistoren die Shuzz meinte, hast du ja schon in deinem Schaltplan drin. Einen für jede Ebene.


    Zum Code:


    Ich hab das so gemacht, dass ich mir eine globale Variabel definiert hab: int Cube[4][4][4];
    Das ist ein dreidimensionales Array. Jeder Int steht für eine LED (1 = ein, 0 = aus).


    Nun besteht der Code im groben aus zwei Teilen. Der eine Teil ist eine Interrupt Service Routine (ISR). (http://www.mikrocontroller.net/articles/Interrupt)
    Von einem Timer wird nun immer wieder alle paar Milisekunden diese ISR aufgrufen. In der ISR wird auf das 3D Array zugegriffen und so wie von bower1988 beschrieben das Bild vom Cube "refresht".


    Im zweiten Teil des Programms wird das 3D -Array, und damit das Bild, verändert. Da fängt man mit ganz einfachen Funktionen wie z.B. "LedOn(x,y,z);" an. Die Funktion schaltet dann die Led an.
    Z.B würde dann LedOn(2,3,4); Die Led an der 2 Stelle von links, drei in die Tiefe (y-richtung) und in der Obersten Ebene einschalten.
    Des wegen ist das Array auch Dreidimensional.


    Und dann schreibt man mit Hilfe von diesen Funktionen wieder etwas komplexere. Und kann sich so dann Muster bauen.


    Gruß Stefan

  • Hey!


    stefan741


    Ich habs jetzt auf 16000000UL eingestellt. Jedoch bim ich mir bei den Fusebits noch nicht sicher. Was muss ich nehmen ? Hatte da schon einmal was verstellt und gleich den atmega zerschossen.


    Ext. Crystal/Resistor High Freq; Start-up time: 258 CK + 4 ms
    Ext. Crystal/Resistor High Freq; Start-up time: 258 CK + 64 ms


    Ext. Crystal/Resistor High Freq; Start-up time: 1K CK + 0 ms
    Ext. Crystal/Resistor High Freq; Start-up time: 1K CK + 4 ms
    Ext. Crystal/Resistor High Freq; Start-up time: 1K CK + 64 ms


    Ext. Crystal/Resistor High Freq; Start-up time: 16K CK + 0 ms
    Ext. Crystal/Resistor High Freq; Start-up time: 16K CK + 4 ms
    Ext. Crystal/Resistor High Freq; Start-up time: 16K CK + 64 ms



    Habe noch etwas gegooglet, will jedoch auf nummer sicher gehen. Sorry für die fragerei, möchte jedoch nicht wieder ein microcontroller verlieren.
    Ich tippe auf "Ext. Crystal/Resistor High Freq; Start-up time: 16K CK + 4 ms" :)


    Danke für die Beschreibung wegen dem Code. Ich probiere einfach weiterhin aus und schau mir noch ein paar C tuts an !

  • Hallo Stefan741,


    willst du vllt ein paar Schnipsel von deinem Code hier veröffentlichen? Ich weiß zwar wie man so nen Cube im Prinzip programmiert...aber so wirklich effizient is meine Vorgehensweise leider nich. Den Ansatz mit dem Array find ich echt interessant. Da ich in den Semesterferien mal einen 8^3 Cube bauen will such ich nach effizientem Code wo ich mir was abgucken kann^^

  • Auf einen externen Quarz solltest du nur umstellen, wenn auch wirklich ein externer Quarz angeschlossen ist. Der Rest ist dann nur noch die Start-up Zeit. Je schlechter die Spannungsversorgung ist umso länger sollte man die Start-up Zeit einstellen.
    Gerne genommen wird auch die Fuse Div/8. Das teilt die Taktfrequenz der ausgewählten Taktquelle noch mal durch 8. Vielleicht dies zuerst mal kontrollieren.

  • Moin moin,


    ich hab nochmal nachgeuckt, wo ich die Idee für den Code her bekommen hab.
    http://www.instructables.com/i…m-the-AVR-with-real-code/
    Das ist zwar jetzt eine Anleitung für einen 8x8x8 Cube, aber das sollte sehr ähnlich auch mit einem 4x4x4 Cube gehen.
    Im Anhang ist der Gesamte-Code, den er auch auf Instructabels zum Download stellt.



    Wegen den Fuses:
    Ich würde den auf "Ext. Crystal/Resistor High Freq; Start-up time: 16K CK + 64 ms" stellen. Denn die 64ms die er einmal beim Einschalten wartet, die hat man auch noch über ;-)

  • Hi!

    Shuzz: Warum sollte ich noch weitere Transistoren einbauen? Bringt in meinen Augen nichts oder verstehe ich da was falsch?

    Du hast 16 LEDs an Deinem Controller hängen, die können gleichzeitig leuchten. Wenn ich Deinen Schaltplan richtig lese, hat jede der LEDs einen 200R Vorwiderstand, macht dann bei blauen/weissen LEDs rund 10mA Strom pro LED. Für alle LEDs zusammen ergibt das also 160mA.


    Jeder Portpin der eine LED treibt muss daher 10mA liefern. Das ist soweit noch OK und innerhalb der Spezifikation.
    ABER woher kommt der Strom? Genau, der fliesst über den Vcc Pin erstmal in den Controller hinein. Und zwar die kompletten 160mA. Über einen Pin. Das ist zuviel.
    Steht übrigens auch explizit im Datenblatt der Atmel Controller drin.


    Auch ohne die Transistoren wird das ne Weile funktionieren, aber sauber ist das nicht und wenn Dir irgendwann Dein Atmel abraucht ist das ja auch blöd oder? ;)
    Also einfach noch ein paar PNP Transistoren vorne dran. Dann noch die Vorwiderstände anpassen und beachten, dass Du die Ansteuerung umdrehen musst.
    Vorteil: Du könntest die LEDs dann auch mit höherem Strom ansteuern (z.B. 30-40mA), dadurch erscheinen sie trotz des Multiplexens normal hell.


    Ansonsten solltest Du Dich wirklich in C einarbeiten, gibt super Tutorials auf Mikrocontroller.net. Dort gibt es auch step-by-step Erklärungen zur Programmierung einer LED Matrix.


    Zu Deinem Verständnisproblem mit den 3ms:
    Wenn Du nur alle 8ms zwischen Deinen Ebenen umschaltest kann es nur Flackern. Für ein Bild musst Du alle vier Ebenen jeweils einmal ansteuern (quasi "1 Hz"). Bei 8ms kannst Du pro Sekunde Deine Ebenen ca. 125x ansteuern. Geteilt durch vier Ebenen ergibt das also ca. 30 komplette Bildaufbauten pro Sekunde - logisch, dass das flackert.
    Bei 3ms Verzögerung kommst Du auf ca. 330 Ebenenumschaltungen pro Sekunde, geteilt durch vier Ebenen ergibt das dann rund 80 Bilder pro Sekunde - das klingt schon flimmerfreier.


    Generell solltest Du das umschalten der Ebenen usw. in einem Timerinterrupt erledigen. Wie das geht steht wiederum in den oben erwähnten Tutorials... ;)


    Die Transistoren die Shuzz meinte, hast du ja schon in deinem Schaltplan drin. Einen für jede Ebene.

    Die meinte ich nicht. Ich meinte Highside-Transistoren.

  • Damit läufst Du aber (wie oben bereits umschrieben) deutlich Gefahr Deinen Controller zu schrotten.
    Weil der halt nur mit 70mA auf GND und VCC Pins spezifiziert ist. Das überschreitest Du mit 160mA um mehr als das Doppelte.
    Also nicht wundern wenn der Cube auf einmal dunkel bleibt und der Atmel anfängt zu müffeln...

  • Weil der halt nur mit 70mA auf GND und VCC Pins spezifiziert ist.



    Datenblatt Seite 287


    EDIT: lynex: wenn du keine Lust hast dich in C einzuarbeiten kannst du es ja auch mit BASCOM versuchen, IMHO ist das wesentlich einfacher.
    Hier gibt es auch schon was fertiges, muss evtl. nur noch angepasst werden.
    Kleine Bastelei: "Borg-Cube" 3x3x3