LED-Cube 8x8x8 Matrix

(Mai 2010) Als erstes die Idee …
Ich hatte, soweit ich’s noch weiss, bei YouTube ein Video von einem LED-Cube gesehen und dachte mir: „Das will ich auch!“
=> gedacht -> geplant -> gekauft
Da LEDs in der Menge (man bedenke 8×8 LEDs für eine Ebene = 64 LEDs und davon dann 8 Ebenen = 512 LEDs!!) einiges kosten und erst recht wenn diese dann auch noch blau sein sollen, muss eine günstige Quelle erschlossen werden. Und was gibt es da wohl besseres als die einschlägigen Online Auktionshäuser?
Aber so einfach war das dann doch nicht, denn unter den vielen Angeboten muss erst mal das passende gefunden werden.
Am Ende hab ich dann welche für so um die 45€ bekommen und sogar noch mit Vorwiderstand für jede LED, den ich gar nicht gebraucht hätte … 🙂

Auf dem Bild ist übrigens nur ein Teil der LEDs zu sehen.
Wer genau hinschaut kann erkennen das alle LEDs schon gebogen sind.
Übrigens scheiß viel Arbeit.
Ich war allein mit dem Biegen einige Abende beschäftigt (und dabei locker 5-6 Filme geschaut ;-)).

Als Nächstes mussten die Leuchten in Position gebracht werden.
Dafür hatte ich mir aus einem kleinen Brett eine Schablone gebaut, womit ich auch gleich die „Köpfe“ weiß lackieren konnte.
Denn vorherige Leuchttests haben ergeben das auf diese Art bearbeitete LEDs besser aussehen.

Der nächste Schritt war übrigens auch nur geringfügig weniger Aufwand … Das Löten nämlich.
Die Länge des benötigten Drahtes ist nicht zu unterschätzen. Ein paar Meter waren es am Ende dann doch schon geworden.

Irgendwann viel später kann das Ergebnis dann ungefähr so aussehen.

Was nun noch fehlt ist … richtig, die Steuerung.
Verwendet habe ich hierfür so genannte 8-bit D-Latch/e/es, keine Ahnung wie man die im Plural schreibt :-)).
Das „tolle“ an diesen IC’s ist, dass ich per µC jeweils 1 Byte an das Latch geben kann und es erst dann ausgeben lassen wenn ich einen Eingang des IC’s setze. D.h. ich kann die Datenleitungen aller 8 IC’s zusammenlegen und immer nur das IC die Daten ausgeben lassen, welches ich dann auswählen kann.
Die 8 Ebenen können dann über die MOSFET’s (da es nicht im Plan zu sehen ist, es sind IRLU 2905) ausgewählt werden.
Nun gut, ich hoffe mal man kann es so verstehen …

So sehen die Platinen dann geätzt und bestückt aus.

Natürlich darf auch die nötige Verpackung nicht fehlen und daher habe ich mir Bilderrahmen bestellt (übrigens die gleiche Art, die ich auch für die Word-Clock benutzt habe).
Vorne kann man die Drähte sehen, die später für die Auswahl der einzelnen Ebenen sind.

Und nun … der erste Test. Alles funktioniert wie ich es mir ausgedacht habe … zum Glück ;-).
Das die LEDs im Foto farblich nicht der Farbe Blau entsprechen liegt allein an der Aufnahme mit meiner Kamera.

Zeit für Impressionen vom LED-Cube.

Zum Abschluss mein kleines Testprogramm, das die Ebenen von unten nach oben wie in einem Schieberegister ansteuert.

.include "m32def.inc"		;ATMEGA32-Routinen einbinden

;--------------------Registerdefinitionen--------------------

.def temp0 = r16			;allgemeines Arbeitsregister
.def temp1 = r17			;allgemeines Arbeitsregister
 
;--------------------Ein+Ausgänge--------------------

;PortA:							 PortB:							
;	Pin0 =(A)= Bit0					Pin0 =(A)= unbenutzt
;	Pin1 =(A)= Bit1					Pin1 =(A)= unbenutzt
;	Pin2 =(A)= Bit2					Pin2 =(A)= unbenutzt
;	Pin3 =(A)= Bit3					Pin3 =(A)= unbenutzt
;	Pin4 =(A)= Bit4					Pin4 =(A)= unbenutzt
;	Pin5 =(A)= Bit5					Pin5 =(A)= unbenutzt
;	Pin6 =(A)= Bit6					Pin6 =(A)= unbenutzt
;	Pin7 =(A)= Bit7					Pin7 =(A)= unbenutzt

;PortC:							 PortD:
;	Pin0 =(A)= Spalte1				Pin0 =(A)= Layer1
;	Pin1 =(A)= Spalte2				Pin1 =(A)= Layer2
;	Pin2 =(A)= Spalte3				Pin2 =(A)= Layer3
;	Pin3 =(A)= Spalte4				Pin3 =(A)= Layer4
;	Pin4 =(A)= Spalte5				Pin4 =(A)= Layer5
;	Pin5 =(A)= Spalte6				Pin5 =(A)= Layer6
;	Pin6 =(A)= Spalte7				Pin6 =(A)= Layer7
;	Pin7 =(A)= Spalte8				Pin7 =(A)= Layer8

;--------------------Vorbereitungen--------------------
;Stackpointer initialisieren
			ldi temp0, LOW(RAMEND)	;LOW-Byte der obersten RAM-Adresse
			out SPL, temp0
			ldi temp0, HIGH(RAMEND)	;HIGH-Byte der obersten RAM-Adresse
			out SPH, temp0

;PortA-D
			ldi temp0, 0b11111111
			out DDRA, temp0			;PortA = Ausgang
			out DDRB, temp0			;PortB = Ausgang
			out DDRC, temp0			;PortC = Ausgang
			out DDRD, temp0			;PortD = Ausgang

;--------------------Hauptprgramm--------------------
;einmal zu Anfang ausführen:

			ldi temp0, 0xFF
			out PortC, temp0
			out	PortA, temp0
			ldi temp1, 0xFF

begin:		ldi temp0, 0x00

main:		out PortD, temp0		;temp0 in Layer ausgeben
			inc temp0				;temp0 um 1 erhöhen
			rcall timer
			cp temp0 , temp1		;vergleiche temp0 mit temp1
			breq begin				;wenn gleich springe zu "begin"
			rjmp main				;wenn ungleich springe zu "main" (Schleife)

;dauerhaft ausführen (Schleife):

;--------------------Timer--------------------

timer:
			ldi  R29, $5F
WGLOOP0:	ldi  R30, $17
WGLOOP1:	ldi  R31, $79
WGLOOP2:	dec  R31
			brne WGLOOP2
			dec  R30
			brne WGLOOP1
			dec  R29
			brne WGLOOP0

			ret					;Rücksprung ins Hauptprogramm

;--------------------Programmende--------------------
;kommt nie hier an
loop:
			rjmp loop			;springe zurück zu "loop"

Update

(05.09.10)

Wie angekündigt ein Bild von der fertig eingebauten Platine.
Sieht etwas wüst aus, ist es aber auch. Da der ganze Einbau nicht hoch sein durfte habe ich die Flachbandkabel direkt angelötet. Passt gerade so, aber wenn ich da noch mal was ändern muss oder sonst was machen will, wird das ’ne richtige Friemelarbeit.
Praktisch ist aber, das ich direkt mit den Klammern, die das Brettchen gegen den Rahmen pressen, die Platinen befestigen konnte. Also keine unschönen Schrauben oder Ähnliches die man von oben sehen könnte.

Update

(15.12.11)

Heute gibt es zwar kein neues Bild vom LED-Cube, dafür aber ein neues Programm.
Da ich seit nun doch schon längerer Zeit wieder Lust hatte etwas zu programmieren, habe ich einen neuen Modus für den LED-Cube geschrieben.
Und zwar einen Zufallsmodus. D.h. es gehen (mehr oder weniger) zufällig irgendwelche LEDs an und auch wieder aus.
Der vorherige Modus ist weiterhin funktionsfähig, muss aber „entkommentarisiert“ werden, damit er auch abgearbeitet wird.

.include "m32def.inc"		;ATMEGA32-Routinen einbinden

;--------------------Registerdefinitionen--------------------

.def temp0 = r16			;allgemeines Arbeitsregister
.def temp1 = r17			;allgemeines Arbeitsregister
.def temp2 = r18			;Register für Zufallszahl
.def temp3 = r19			;Register für Zufallszahl
.def random1 = r20			;Zufallszahl
.def random2 = r21			;Zufallszahl
 
;--------------------Ein+Ausgänge--------------------

;PortA:							 PortB:							
;	Pin0 =(A)= Bit0					Pin0 =(A)= unbenutzt
;	Pin1 =(A)= Bit1					Pin1 =(A)= unbenutzt
;	Pin2 =(A)= Bit2					Pin2 =(A)= unbenutzt
;	Pin3 =(A)= Bit3					Pin3 =(A)= unbenutzt
;	Pin4 =(A)= Bit4					Pin4 =(A)= unbenutzt
;	Pin5 =(A)= Bit5					Pin5 =(A)= unbenutzt
;	Pin6 =(A)= Bit6					Pin6 =(A)= unbenutzt
;	Pin7 =(A)= Bit7					Pin7 =(A)= unbenutzt

;PortC:							 PortD:
;	Pin0 =(A)= Spalte1				Pin0 =(A)= Layer1
;	Pin1 =(A)= Spalte2				Pin1 =(A)= Layer2
;	Pin2 =(A)= Spalte3				Pin2 =(A)= Layer3
;	Pin3 =(A)= Spalte4				Pin3 =(A)= Layer4
;	Pin4 =(A)= Spalte5				Pin4 =(A)= Layer5
;	Pin5 =(A)= Spalte6				Pin5 =(A)= Layer6
;	Pin6 =(A)= Spalte7				Pin6 =(A)= Layer7
;	Pin7 =(A)= Spalte8				Pin7 =(A)= Layer8

;--------------------Vorbereitungen--------------------
;Stackpointer initialisieren
			ldi temp0, LOW(RAMEND)	;LOW-Byte der obersten RAM-Adresse
			out SPL, temp0
			ldi temp0, HIGH(RAMEND)	;HIGH-Byte der obersten RAM-Adresse
			out SPH, temp0

;Eingangs- /Ausgangsdeklaration
			ldi temp0, 0b11111111
			out DDRA, temp0			;PortA = Ausgang
			out DDRB, temp0			;PortB = Ausgang
			out DDRC, temp0			;PortC = Ausgang
			out DDRD, temp0			;PortD = Ausgang

;Ursprungszustand des Würfels (alles aus)
			ldi temp0, 0xFF
			out PortC, temp0
			out	PortA, temp0

;--------------------Hauptprogramm--------------------
;Moduswahl

main:
			;jmp EbenenSchieben
			jmp Zufall

;--------------------Unterprogramme--------------------

Zufall:			;Zufallsmuster
			rcall random
			rcall timer
			out PortD, random1
			out PortC, random2
			out PortA, random1
			rjmp Zufall				;Schleife

EbenenSchieben:	;addiert immer um 1
			ldi temp1, 0xFF
	ES1:
			ldi temp0, 0x00			;nur einmal am Anfang ausführen
	ES2:
			out PortD, temp0		;temp0 in Layer ausgeben
			inc temp0				;temp0 um 1 erhöhen
			rcall timer
			cp temp0 , temp1		;vergleiche temp0 mit temp1
			breq ES1				;wenn gleich springe zu "ES1"
			rjmp ES2				;Schleife

;--------------------Timer--------------------
;Quelle: AVR DELAY LOOP GENERATOR V1.2  (C)2000 by Tjabo Kloppenburg
;bzw.: http://www.home.unix-ag.org/tjabo/avr/dlg_02/dlg02.php

;Eingestellt für 16MHz Takt und 0,025s

timer:
			ldi  R29, $F1
WGLOOP0:	ldi  R30, $0E
WGLOOP1:	ldi  R31, $9D
WGLOOP2:	dec  R31
			brne WGLOOP2
			dec  R30
			brne WGLOOP1
			dec  R29
			brne WGLOOP0
			ret

;--------------------Zufallszahl--------------------
;Quelle: http://www.mikrocontroller.net/topic/91659#785292
;Autor des Beitrags: Knut Ballhause (Firma: TravelRec.)

random:
			mov		temp2, random1	;exor feedback outputs for SR input
			andi	temp2, 0b00000001
			lsl		temp2
			lsl		temp2
			eor		temp2, random1
			andi	temp2, 0b00000100
			swap	temp2
			lsl		temp2
			mov		temp3, random2
			andi	temp3, 0b00001000
			swap	temp3
			eor		temp3, random2
			andi	temp3, 0b10000000
			eor		temp3, temp2
			rol		temp3
			rol		random1
			rol		random2
			ret

;--------------------Programmende--------------------
;kommt nie hier an
loop:
			rjmp	loop			;springe zurück zu "loop"

Ähnliche Beiträge

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert