Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

8x8x8 RGB-LED-Würfel

Komponenten und Verbrauchsmaterialien

RGB diffundierte gemeinsame Anode
× 512
DM13A LED-Treiber
× 12
74HC138 3 bis 8 Zeilen Dekodierung
× 1
IRF9640 P-Kanal-MOSFET
× 8
Arduino UNO
Sie können auch eine Steckbrettversion mit nur einem ATmega328, 16Mhz Quarz, 2 x 22pf Kondensatoren erstellen
× 1
Digilent 5V 2.5A Schaltnetzteil
× 1
Widerstand 10k Ohm
× 8
Widerstand 1k Ohm
× 8
Widerstand 100 Ohm
× 8

Apps und Onlinedienste

Arduino-IDE

Über dieses Projekt

Video

Erstellen

Dieser Build wurde von Kevin Darrah RGB-Würfel inspiriert.

Wenn man sich Kevins Figur ansieht, muss seine Geduld keine Grenzen haben – meine leider.

Ich beschloss, die 24 Schieberegister, 192 Transistoren und 640 Widerstände durch 12 DM13a-LED-Treiber zu ersetzen (etwa 1 US-Dollar bei eBay).

Der Würfel selbst wurde gebaut, wie Kevin im folgenden Video beschreibt:

Sobald der Würfel hergestellt war, erstellte ich eine Leiterplatte mit der Toner-Methode, um die DM13A-Treiberchips und den Würfel selbst zu halten. Anstatt die Kosten für eine kommerziell hergestellte Platine mit Durchkontaktierung zu bezahlen, beschloss ich, jede LED-Verbindung mit Drahtwickeldraht mit dem entsprechenden DM13A-Pin zu verdrahten. Die enthaltenen Eagle-Dateien enthalten die handverdrahtete Version sowie eine automatisch geroutete Version (ungetestet).

Die Mikroprozessor- und Anodenplatine enthält auch einen MSGEQ7 - Seven Band Graphic Equalizer und einen Mikrofonvorverstärker, mit denen ich in Zukunft experimentieren möchte. Im Moment werden sie nicht verwendet. Wenn Sie ein handelsübliches UNO- oder Nano-Board verwenden möchten, benötigen Sie lediglich den 74HC138 3- bis 8-Zeilen-Decoder und die 8 P-Kanal-MOSFETs und die dazugehörigen Widerstände. Sie können diese einfach auf einem Proto-Board verdrahten, wenn Sie möchten.

Das 5V 20W Netzteil wurde bei eBay gekauft. Ich habe das Gehäuse aus 40 mm x 9 mm Kiefer gefertigt.

Ich habe Kevins Cube-Software ein paar Animationen hinzugefügt, aber sie bleibt im Grunde unverändert.

Fazit

Sie sollten in der Lage sein, 600 x 5 mm Common Anode difused RGB LEDs von eBay für etwa 30 US-Dollar zu kaufen. Auch nach der Vereinfachung der Elektronik war der Bau des Würfels sehr zeitaufwendig, aber am Ende lohnend.

Code

  • Cube_8x8x8_V1.ino
Cube_8x8x8_V1.inoC/C++
/*Der 8x8x8 RGB LED Cubevon John Bradnambasierend auf der Arbeit von Kevin DarrahLatestV12 17.04.2013Release Notes:V11- Fehler mit BAM-Timing behoben- Blank Pin-Setup in ISR verschoben, sodass Pins tot sind, bis sie in V12bitwise Operation zum Setzen geschrieben werden Pins LOW war falschsollte PORTx sein &=~(1<// SPI Library Wird verwendet, um Daten in die Schieberegister zu takten #define LATCH_PIN 2 // kann jeden Pin verwenden, den Sie zum Latchen der Schieberegister verwenden möchten #define BLANK_PIN 4 // dasselbe, kann jeden gewünschten Pin dafür verwenden, stellen Sie nur sicher, dass Sie über a 1k bis 5V#define DATA_PIN 11 // verwendet von SPI, muss Pin 11 sein#define CLOCK_PIN 13 // verwendet von SPI, muss 13 sein#define LAYER_A 5 //74138 A Input#define LAYER_B 6 //74138 A Input# define LAYER_C 7 //74138 A Input#define SWITCH_PGM 10 //PB2#define SWITCH_SEQ 9 //PB1#define CUBE_SIZE 8 //Anzahl Spalten, Zeilen oder Ebenen im Würfel#define CUBE_MAX (CUBE_SIZE - 1) //Max Würfel in dex#define LEDS_PER_LEVEL (CUBE_SIZE * CUBE_SIZE) //Anzahl der LEDs pro Ebene//***Variablen***Variablen***Variablen***Variablen***Variablen***Variablen***Variablen***Variablen // Diese Variablen werden durch Multiplexing und Bit Angle Modulation Code verwendet // So wird die Helligkeit für jede LED gespeichert // Jede LED benötigt nur ein 'Bit' um zu wissen, ob sie EIN oder AUS sein soll, also 64 Bytes ergeben Sie 512 Bit =512 LEDs // Da wir die LEDs mit einer Auflösung von 4 Bit modulieren, hat jede Farbe 4 Arrays mit 64 Bit pro Byte red0[LEDS_PER_LEVEL], red1[LEDS_PER_LEVEL], red2[LEDS_PER_LEVEL], red3[LEDS_PER_LEVEL];byte blue0[LEDS_PER_LEVEL], blue1[LEDS_PER_LEVEL], blue2[LEDS_PER_LEVEL], blue3[LEDS_PER_LEVEL];byte green0[LEDS_PER_LEVEL], green1[LEDS_PER_LEVEL], green2[LEDS_PER_LEVEL], green3[LEDS_PER_LEVEL]; mehr von Ihrem wertvollen RAMint level=0; // behält den Überblick darüber, auf welchem ​​​​Level wir die Daten zuint anodeLevel=0 verschieben; // dies erhöht sich durch die Anodenlevelint BAM_Bit , BAM_Zähler=0; // Bit-Winkel-Modulation-Variablen, um die Dinge zu verfolgenint Animation =0; // Verfolgt die Animation in der Hauptschleife //****setup****setup****setup****setup****setup****setup****setup**** setup****setup****setup****setup****setup****setupvoid setup () { SPI.setBitOrder (MSBFIRST); // Höchstwertiges Bit zuerst SPI.setDataMode (SPI_MODE0); // Modus 0 Steigende Flanke der Daten, Takt niedrig halten SPI.setClockDivider (SPI_CLOCK_DIV2); // Daten mit 16 MHz / 2 - 8 MHz ausführen // Serial.begin (115200); // wenn Sie es brauchen? noInterrupts (); // Unterbrechungen beenden, bis alle eingerichtet sind // Wir verwenden Timer 1, um den Würfel zu aktualisieren TCCR1A =B00000000; // Register A alle Nullen, da wir keine Pins umschalten TCCR1B =B00001011; // Bit 3 gesetzt in den CTC-Modus zu versetzen, ruft einen Interrupt bei einer Zählerübereinstimmung auf // Bits 0 und 1 werden gesetzt, um den Takt durch 64 zu teilen, also 16MHz/64=250kHz TIMSK1 =B00000010; // Bit 1 wird gesetzt, um den Interrupt bei an . aufzurufen OCR1A-Übereinstimmung OCR1A=30; // Sie können damit spielen, aber ich habe es auf 30 gesetzt, was bedeutet://unsere Uhr läuft mit 250kHz, was 1/250kHz =4us ist //mit OCR1A auf 30, bedeutet dies, dass der Interrupt alle ( 30+1)x4us=124us, // was eine Multiplexfrequenz von ca. 8kHz ergibt // schließlich die Ausgänge einrichten pinMode (LATCH_PIN, OUTPUT); // Latch pinMode (DATA_PIN, OUTPUT); // MOSI DATA pinMode (CLOCK_PIN, OUTPUT); // SPI Clock pinMode (LAYER_A, OUTPUT); // 74138 A Input pinMode (LAYER_B, OUTPUT); // 74138 B Input pinMode (LAYER_C, OUTPUT); // 74138 C Input digitalWrite (LAYER_A, LOW); digitalWrite (LAYER_B, LOW); digitalWrite (LAYER_C, LOW); pinMode (SWITCH_PGM, INPUT); // PGM 1 / PGM 2 Schalter pinMode (SWITCH_SEQ, INPUT); // SEQ/COLOR Schalter // pinMode (BLANK_PIN, OUTPUT); // Output Enable wichtig, um dies zuletzt zu tun, damit LEDs es tun blinkt nicht beim Booten SPI.begin(); // Starten Sie die SPI-Bibliothek Interrupts (); // Lassen Sie die Show beginnen, dies lässt das Multiplexing starten}//***Startschleife***Startschleife*** Startschleife***Startschleife***Startschleife***Startschleife***Startschleife***Startschleife***Startschleifevoid loop(){ //Jede Animation befindet sich in einer Subroutine // Um ​​eine . zu steuern LED, Sie einfach:// LED (Ebene, die Sie wollen 0-CUBE_MAX, Zeile, die Sie wollen 0-CUBE_MAX, Spalte, die Sie wollen 0-CUBE_MAX, rote Helligkeit 0-15, grüne Helligkeit 0-15, blaue Helligkeit 0-15); if (digitalRead(SWITCH_PGM) ==HIGH) test_leds(); sonst { sauber(); Animation =Animation + 1; Schalter (Animation) { Fall 1:rainVersionTwo (20); brechen; Fall 2:Ordner (10); brechen; Fall 3:sinwaveTwo(15); brechen; Fall 4:randomColor(10); brechen; Fall 5:Wipe_out(10); brechen; Fall 6:bouncyvTwo(15); brechen; Fall 7:color_wheelTWO(10); brechen; Fall 8:harlem_shake(); brechen; Fall 9:Wellen (10); brechen; Fall 10:Animation =0; brechen; } }} //****LED-Routine****LED-Routine****LED-Routine****LED-Routinevoid LED (int level, int row, int column, byte red, byte green, byte blue){ // Hier fängt alles an // Diese Routine ist, wie LEDs aktualisiert werden, mit den Eingängen für die LED-Position und ihre RG- und B-Helligkeitsstufen // Überprüfen Sie zuerst und stellen Sie sicher, dass nichts die Grenzen überschreitet, klemmen Sie einfach die Dinge an entweder 0 oder 7 für den Standort und 0 oder 15 für das Helligkeitslevel =Constraint(level, 0, CUBE_MAX); Zeile =Einschränkung (Zeile, 0, CUBE_MAX); Spalte =Einschränkung (Spalte, 0, CUBE_MAX); rot =einschränken (rot, 0, 15); grün =einschränken (grün, 0, 15); blau =einschränken (blau, 0, 15); //Es gibt (CUBE_SIZE * CUBE_SIZE * CUBE_SIZE) LEDs im Würfel. Wenn wir also auf Ebene 2, Spalte 5, Zeile 4 schreiben, muss dies in eine Zahl von 0 bis (CUBE_SIZE * CUBE_SIZE * CUBE_SIZE) - 1 übersetzt werden // Die LEDs der ersten Ebene sind zuerst in der Reihenfolge, dann die zweite Ebene, dann die dritte usw. // Für einen 4 x 4 x 4 Würfel ist (Ebene * (4 * 4)) das, was den Startplatz der Ebene indiziert. Level 0 sind also die LEDs 0 - 15, Level 1 sind die LEDs 16 - 31 usw. // Wenn Sie auf den Würfel hinunterschauen und nur auf die unterste Ebene geschaut haben // 00 01 02 03 // 04 05 06 07 / / 08 09 10 11 // 12 13 14 15 // Für einen 8 x 8 x 8 Würfel ist (level * (8 * 8)) das, was den Startplatz des Levels indiziert, also Level 0 sind LEDs 0 - 63, Level 1 sind LEDs 64 - 127, und so weiter // wenn Sie auf den Würfel hinunterschauen und nur auf die unterste Ebene geschaut haben // 00 01 02 03 04 05 06 07 // 08 09 10 11 12 13 14 15 // 16 17 18 19 20 21 22 23 // 24 25 26 27 28 29 30 31 // 32 33 34 35 36 37 38 39 // 40 41 42 43 44 45 46 47 // 48 49 50 51 52 53 54 55 // 56 57 5 8 59 60 61 62 63 //Wenn Sie das Level erhöhen würden, würde die obere rechte Ecke des obigen Rasters bei (CUBE_SIZE * CUBE_SIZE) beginnen //Der Grund dafür ist, dass Sie sich keine Zahl merken müssen für jede LED, sodass Sie Level, Row, Column verwenden können // Nun, was ist mit der Division durch 8 darin? //...nun, wir haben 8 Bits pro Byte und wir haben 64 Bytes im Speicher für alle 512 Bits, die für jede LED benötigt werden, also // teilen wir die gerade gefundene Zahl durch 8 und nehmen die ganze Zahl davon, damit wir wissen, in welchem ​​Byte sich dieses Bit befindet // verwirrt? das ist in Ordnung, nehmen wir ein Beispiel, wenn wir die LED bis zur letzten LED im Würfel schreiben wollten, würden wir 7, 7, 7 // schreiben (7*64)+(7*8)=7 =511, was richtig ist, aber jetzt teilen wir es durch 8, 511/8 =63,875 und nehmen den Int davon so, dass wir 63 erhalten, // dies ist das letzte Byte im Array, was richtig ist, da dies das ist letzte LED // Holen Sie sich die LED-Nummer 0 - 511 int Wholebyte =(level * LEDS_PER_LEVEL) + (row * CUBE_SIZE) + column; // Hole den Index in das Array. Jede indizierte Stelle enthält ein Byte oder 8 Bits; int whatbyte =int (ganzebyte / 8); int whatbit =(Ganzbyte &7); //Dies wird in einer Sekunde alles sinnvoll sein //Dies ist eine 4-Bit-Farbauflösung, also enthält jede Farbe x4 64-Byte-Arrays, Erklärung unten:bitWrite(red0[whichbyte], whichbit, bitRead(red, 0)); bitWrite (red1 [welches Byte], welches Bit, bitRead (rot, 1)); bitWrite (red2 [welches Byte], welches Bit, bitRead (rot, 2)); bitWrite (red3 [welches Byte], welches Bit, bitRead (rot, 3)); bitWrite (grün0 [welches Byte], welches Bit, bitRead (grün, 0)); bitWrite(green1[whichbyte], whichbit, bitRead(green, 1)); bitWrite(green2[whichbyte], whichbit, bitRead(green, 2)); bitWrite(green3[whichbyte], whichbit, bitRead(green, 3)); bitWrite(blue0[whichbyte], whichbit, bitRead(blue, 0)); bitWrite(blue1[whichbyte], whichbit, bitRead(blue, 1)); bitWrite(blue2[whichbyte], whichbit, bitRead(blue, 2)); bitWrite(blue3[whichbyte], whichbit, bitRead(blue, 3)); //Bist du jetzt noch verwirrter? Sie sollten nicht sein! Es fängt jetzt an, Sinn zu machen. Beachten Sie, dass jede Zeile ein BitWrite ist, dh //bitWrite (das Byte, in das Sie schreiben möchten, das Bit des Bytes, das geschrieben werden soll, und die 0 oder 1, die Sie schreiben möchten) //Dies bedeutet, dass das 'Whatbyte' ist das Byte von 0-63, in dem das Bit der LED von 0-511 entspricht // Macht das jetzt Sinn, warum wir das gemacht haben? Nehmen Sie einen Wert von 0-511 und konvertieren Sie ihn in einen Wert von 0-63, da jede LED ein Bit in // einem Array von 64 Bytes darstellt. // Dann ist die nächste Zeile, welches Bit 'wholebyte-(8*whichbyte)' //Dies nimmt einfach den Wert der LED von 0-511 und subtrahiert ihn vom BYTE, dessen Bit sich in 8-mal befand //Denken Sie darüber nach, Byte 63 enthält LEDs von 504 bis 511. Wenn Sie also 505-(8*63) genommen haben, erhalten Sie eine 1, was bedeutet, dass //LED-Nummer 505 befindet sich in Bit 1 von Byte 63 im Array //ist das? es? Nein, Sie müssen immer noch das BitRead der Helligkeit 0-15 durchführen, die Sie schreiben möchten. // Wenn Sie eine 15 auf ROT schreiben, haben alle 4 Arrays für diese LED eine 1 für dieses Bit, was bedeutet, dass sie eingeschaltet ist 100% //Deshalb lesen die vier Arrays 0-4 des eingegebenen Wertes für ROT, GRÜN und BLAU //hoffentlich macht das alles Sinn?}//***MultiPlex BAM***MultiPlex BAM** *MultiPlex BAM***MultiPlex BAM***MultiPlex BAM***MultiPlex BAM***MultiPlex BAMISR(TIMER1_COMPA_vect){ //Diese Routine wird im Hintergrund automatisch mit der von OCR1A eingestelltenFrequenz aufgerufen //In diesem Code setze ich OCR1A bis 30, also wird dies alle 124us aufgerufen, was jedem Level im Würfel 124us der EIN-Zeit gibt // Es gibt 8 Level, also haben wir eine maximale Helligkeit von 1/8, da der Level ausgeschaltet werden muss, bevor der nächste Level ist eingeschaltet // Die Frequenz des Multiplexens beträgt dann 124us*8=992us oder 1/992us=ca. 1kHz PORTD |=1 <=CUBE_SIZE) {fx =CUBE_MAX; fxm =-1; } brechen; Fall 1:fy =fy + fym; wenn (fy <0) {fy =0; fym =1; } if (fy>=CUBE_SIZE) {fy =CUBE_MAX; fym =-1; } brechen; Fall 2:fz =fz + fzm; wenn (fz <0) {fz =0; fzm =1; } if (fz>=CUBE_SIZE) {fz =CUBE_MAX; fzm =-1; } brechen; } Schalter (zufällig (3)) { Fall 0:ftx =ftx + ftxm; wenn (ftx <0) {ftx =0; ftxm =1; } if (ftx>=CUBE_SIZE) {ftx =CUBE_MAX; ftxm =-1; } brechen; Fall 1:fty =fty + ftym; wenn (fty <0) {fty =0; ftym =1; } if (fty>=CUBE_SIZE) {fty =CUBE_MAX; ftym =-1; } brechen; Fall 2:ftz =ftz + ftzm; wenn (ftz <0) {ftz =0; ftzm =1; } if (ftz>=CUBE_SIZE) {ftz =CUBE_MAX; ftzm =-1; } brechen; } } //während clean();}//wipeout//****rainVersionTwo****rainVersionTwo****rainVersionTwo****rainVersionTwo****rainVersionTwovoid rainVersionTwo(int runtimeInSeconds){ int x[LEDS_PER_LEVEL ], y[LEDS_PER_LEVEL], z[LEDS_PER_LEVEL], LED-Farbe; int xx[LEDS_PER_LEVEL], yy[LEDS_PER_LEVEL], zz[LEDS_PER_LEVEL], xold[LEDS_PER_LEVEL], yold[LEDS_PER_LEVEL], zold[LEDS_PER_LEVEL]; for(int addr =0; addr =200 &&ledcolor <300) { for(int addr =0; addr =300 &&ledcolor <400) { } if(ledcolor>=500 &&ledcolor <600) { } ledcolor++; if (ledcolor>=300) ledcolor=0; for(int addr =0; addr  

Schaltpläne

eagle_files_WfqPEUP7Mp.zip

Herstellungsprozess

  1. Pflanzenalarm bei Durstalarm
  2. 5x5x5 LED-Würfel
  3. italienische Wordclock
  4. Sigfox-kWh-Zähler
  5. Arduino RGB-Farbmischer
  6. Bluetooth-Temperaturüberwachung
  7. DMX RGB LED im Freien
  8. Gestengesteuerte Sperre
  9. Ein isolierter Analogeingang für Arduino
  10. Messen Sie Ihre Reaktionszeit