Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

8x8x8 RGB LED-kubus

Componenten en benodigdheden

RGB diffuse gemeenschappelijke anode
× 512
DM13A LED-stuurprogramma
× 12
74HC138 3 tot 8 regels decoderen
× 1
IRF9640 P-Channel MOSFET
× 8
Arduino UNO
Je kunt ook een breadboard-versie maken met alleen een ATmega328, 16Mhz-kristal, 2 x 22pf-condensatoren
× 1
Digilent 5V 2.5A schakelende voeding
× 1
Weerstand 10k ohm
× 8
Weerstand 1k ohm
× 8
Weerstand 100 ohm
× 8

Apps en online services

Arduino IDE

Over dit project

Video

Bouw

Deze build is geïnspireerd op de Kevin Darrah RGB-kubus.

Kijkend naar Kevins bouw, kent zijn geduld geen grenzen - helaas de mijne wel.

Ik besloot de 24 schuifregisters, 192 transistors en 640 weerstanden te vervangen door 12 DM13a LED-drivers (ongeveer $1 US per stuk op eBay).

De kubus zelf is gebouwd zoals Kevin beschrijft in de volgende video:

Nadat de kubus was gemaakt, heb ik een printplaat gemaakt met behulp van de Toner-methode om de DM13A-stuurprogrammachips en de kubus zelf vast te houden. In plaats van de kosten te betalen van een commercieel gemaakt bord met doorlopende beplating, besloot ik om elke LED-verbinding met de hand te bedraden op de juiste DM13A-pin met behulp van wire-wrap-draad. De meegeleverde Eagle-bestanden bevatten zowel de handbedrade versie als een automatisch gerouteerde versie (niet getest).

Het microprocessor- en anodebord bevat ook een MSGEQ7 - Seven Band Graphic Equalizer en microfoonvoorversterker waarmee ik in de toekomst wil gaan experimenteren. Op dit moment worden ze niet gebruikt. Als je een commercieel UNO- of Nano-bord wilt gebruiken, heb je alleen de 74HC138 3 tot 8 lijndecoder en de 8 P-kanaal MOSFET's en bijbehorende weerstanden nodig. Je kunt deze desgewenst gewoon op een proto-board aansluiten.

De 5V 20W voeding is gekocht op eBay. Ik maakte de kast van 40 mm x 9 mm gekleed grenen.

Ik heb een paar animaties toegevoegd aan Kevin's kubussoftware, maar deze blijft in principe ongewijzigd.

Conclusie

Je zou 600 x 5 mm Common Anode difused RGB-LED's van eBay moeten kunnen kopen voor ongeveer $ 30 US. Zelfs na het vereenvoudigen van de elektronica, was het bouwen van de kubus erg tijdrovend, maar uiteindelijk de moeite waard.

Code

  • Cube_8x8x8_V1.ino
Cube_8x8x8_V1.inoC/C++
/*De 8x8x8 RGB LED-kubus door John Bradnam gebaseerd op werk van Kevin Darrah Nieuwste V12 17-04-2013 Release-opmerkingen:V11 - Bug opgelost met BAM-timing - Lege pin-instelling naar ISR verplaatst, zodat pinnen dood zijn totdat ze naar V12bitwise-bewerking worden geschreven om in te stellen pins LOW was incorrect, zou PORTx moeten zijn &=~(1<// SPI Library gebruikt om gegevens naar de schuifregisters te klokken #define LATCH_PIN 2 //kan elke pin gebruiken die u wilt vergrendelen de schuifregisters #define BLANK_PIN 4 // hetzelfde, kan elke gewenste pin hiervoor gebruiken, zorg ervoor dat u omhoog trekt via a 1k tot 5V#define DATA_PIN 11 // gebruikt door SPI, moet pin 11 zijn#define CLOCK_PIN 13 // gebruikt door SPI, moet 13#define LAYER_A 5 //74138 A Input#define LAYER_B 6 //74138 A Input# definieer LAYER_C 7 //74138 A Input#define SWITCH_PGM 10 //PB2#define SWITCH_SEQ 9 //PB1#define CUBE_SIZE 8 //Aantal kolommen, rijen of niveaus in kubus#define CUBE_MAX (CUBE_SIZE - 1) //Maximum kubus in dex#define LEDS_PER_LEVEL (CUBE_SIZE * CUBE_SIZE) //Aantal LEDS per niveau//***variabelen***variabelen***variabelen***variabelen***variabelen***variabelen***variabelen***variabelen //Deze variabelen worden gebruikt door multiplexing en Bit Angle Modulation Code//Dit is hoe de helderheid voor elke LED wordt opgeslagen, //Elke LED heeft slechts een 'bit' nodig om te weten of deze AAN of UIT moet zijn, dus 64 bytes geeft u 512 bits =512 LED's// Aangezien we de LED's moduleren, met een resolutie van 4 bits, heeft elke kleur 4 arrays met elk 64 bits 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] meer meer van je kostbare RAMint-niveau =0;//houdt bij welk niveau we gegevens verschuiven naar anodeLevel=0;//dit wordt verhoogd door de anode-niveaus in BAM_Bit , BAM_Teller=0; // Variabelen voor bithoekmodulatie om dingen bij te houden. animatie =0; //Houdt animatie bij in de hoofdlus//****setup****setup****setup****setup****setup****setup****setup**** setup****setup****setup****setup****setup****setupvoid setup(){ SPI.setBitOrder(MSBFIRST);//Meest significante bit eerst SPI.setDataMode(SPI_MODE0); // Mode 0 Stijgende rand van gegevens, houd de klok laag SPI.setClockDivider (SPI_CLOCK_DIV2);// Voer de gegevens uit op 16 MHz/2 - 8 MHz //Serial.begin (115200);// als je het nodig hebt? noInterrupts();// kill interrupts totdat iedereen is ingesteld //We gebruiken Timer 1 om de kubus te vernieuwen TCCR1A =B00000000;//Register A alle nullen omdat we geen pinnen wisselen TCCR1B =B00001011;//bit 3 set om in CTC-modus te plaatsen, roept een interrupt op een teller match op // bits 0 en 1 zijn ingesteld om de klok te delen door 64, dus 16 MHz/64 =250 kHz TIMSK1 =B00000010;//bit 1 ingesteld om de interrupt op een OCR1A komt overeen met OCR1A=30; // je kunt hiermee spelen, maar ik heb het ingesteld op 30, wat betekent://onze klok loopt op 250kHz, wat 1/250kHz =4us is //met OCR1A ingesteld op 30, dit betekent dat de interrupt elke ( 30+1)x4us=124us, // wat een multiplexfrequentie van ongeveer 8kHz geeft //eindelijk de uitgangen 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, LAAG); digitalWrite (LAYER_C, LAAG); pinMode(SWITCH_PGM, INPUT);//PGM 1 / PGM 2 Switch pinMode(SWITCH_SEQ, INPUT);//SEQ/COLOR Switch //pinMode(BLANK_PIN, OUTPUT);//Output Belangrijk inschakelen om dit als laatste te doen, dus LED's doen knippert niet bij opstarten SPI.begin();//start de SPI-bibliotheek interrupts();//laat de show beginnen, hierdoor kan het multiplexen starten}//***start loop***start loop*** start loop***start loop***start loop***start loop***start loop***start loop***start loopvoid loop(){ //Elke animatie in een subroutine // Om een LED, u eenvoudig:// LED (niveau dat u wilt 0-CUBE_MAX, rij die u wilt 0-CUBE_MAX, kolom die u wilt 0-CUBE_MAX, rode helderheid 0-15, groene helderheid 0-15, blauwe helderheid 0-15); if (digitalRead(SWITCH_PGM) ==HOOG) test_leds(); anders { schoon(); animatie =animatie + 1; switch (animatie) { case 1:rainVersionTwo(20); pauze; geval 2:map(10); pauze; geval 3:sinwaveTwo (15); pauze; geval 4:willekeurige kleur (10); pauze; geval 5:wipe_out(10); pauze; geval 6:bouncyvTwo(15); pauze; geval 7:color_wheelTWO(10); pauze; geval 8:harlem_shake(); pauze; geval 9:rimpelingen (10); pauze; geval 10:animatie =0; pauze; } }}//****LED-routine****LED-routine****LED-routine****LED-routinevoid-LED (int niveau, int rij, int kolom, byte rood, byte groen, byte blauw){ //Dit is waar het allemaal begint // Deze routine is hoe LED's worden bijgewerkt, met de ingangen voor de LED-locatie en de RG- en B-helderheidsniveaus // Controleer eerst en zorg ervoor dat niets de limieten overschrijdt, klem gewoon dingen vast op ofwel 0 of 7 voor locatie, en 0 of 15 voor helderheidsniveau =constrain(level, 0, CUBE_MAX); rij =beperking (rij, 0, CUBE_MAX); kolom =beperking (kolom, 0, CUBE_MAX); rood =beperking (rood, 0, 15); groen =beperken (groen, 0, 15); blauw =beperking (blauw, 0, 15); //Er zijn (CUBE_SIZE * CUBE_SIZE * CUBE_SIZE) LED's in de kubus, dus als we schrijven naar niveau 2, kolom 5, rij 4, moet dat worden vertaald in een getal van 0 tot (CUBE_SIZE * CUBE_SIZE * CUBE_SIZE) - 1 // De LED's van het eerste niveau zijn eerst in de reeks, dan het 2e niveau, dan het derde, enzovoort // Voor een kubus van 4 x 4 x 4 is het (niveau * (4 * 4)) wat de startplaats van het niveau aangeeft, dus niveau 0 zijn LED's 0 - 15, niveau 1 zijn LED's 16 - 31, enzovoort // als je naar beneden keek op de kubus en alleen naar het onderste niveau keek // 00 01 02 03 // 04 05 06 07 / / 08 09 10 11 // 12 13 14 15 //Voor een kubus van 8 x 8 x 8 is het (niveau * (8 * 8)) wat de startplaats van het niveau aangeeft, dus niveau 0 zijn LED's 0 - 63, niveau 1 zijn LED's 64 - 127, enzovoort // als je naar beneden keek op de kubus en alleen naar het onderste niveau keek // 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 //Als je het niveau zou verhogen, zou de rechterbovenhoek van het bovenstaande raster beginnen bij (CUBE_SIZE * CUBE_SIZE) // De reden hiervoor is dat je geen nummer hoeft te onthouden voor elke LED, zodat u niveau, rij, kolom kunt gebruiken // Nu, hoe zit het met de verdeling door 8 daar? //... nou, we hebben 8 bits per byte, en we hebben 64 bytes in het geheugen voor alle 512 bits die nodig zijn voor elke LED, dus // we delen het getal dat we zojuist hebben gevonden door 8, en nemen het gehele getal ervan, zodat we weten welke byte, dat bit zich bevindt //confused? dat is goed, laten we een voorbeeld nemen, als we naar de LED naar de laatste LED in de kubus wilden schrijven, zouden we een 7, 7, 7 // geven (7*64)+(7*8)=7 =511, wat juist is, maar laten we het nu delen door 8, 511/8 =63.875, en de int ervan nemen, zodat we 63 krijgen, //dit is de laatste byte in de array, wat juist is omdat dit de laatste LED // Verkrijg het LED-nummer 0 - 511 int helebyte =(niveau * LEDS_PER_LEVEL) + (rij * CUBE_SIZE) + kolom; // Haal de index in de array. Elke geïndexeerde locatie bevat één byte of 8 bits; int welkebyte =int(helebyte/8); int whobit =(hele byte &7); //Dit wordt allemaal in een oogwenk duidelijk //Dit is een 4-bits kleurresolutie, dus elke kleur bevat x4 64-byte-arrays, uitleg hieronder:bitWrite(red0[whichbyte], whichbit, bitRead(red, 0)); bitWrite(red1[welkebyte], whichbit, bitRead(red, 1)); bitWrite(red2[welkebyte], whichbit, bitRead(rood, 2)); bitWrite (red3 [welke byte], welke bit, bitRead (rood, 3)); bitWrite(green0[welkebyte], whichbit, bitRead(green, 0)); bitWrite(groen1[welkebyte],welkebit, bitRead(groen, 1)); bitWrite(groen2[welkebyte],welkebit, bitRead(groen, 2)); bitWrite(groen3[welkebyte],welkebit, bitRead(groen, 3)); bitWrite(blue0[welkebyte], whichbit, bitRead(blue, 0)); bitWrite(blue1[welkebyte], whichbit, bitRead(blue, 1)); bitWrite(blue2[welkebyte], whichbit, bitRead(blue, 2)); bitWrite(blue3[welkebyte], whichbit, bitRead(blue, 3)); //Ben je nu meer in de war? Dat zou je niet moeten zijn! Het begint nu zin ​​te krijgen. Merk op hoe elke regel een bitWrite is, namelijk //bitWrite (de byte waarnaar u wilt schrijven, het bit van de byte waarnaar u wilt schrijven en de 0 of 1 die u wilt schrijven) //Dit betekent dat de 'welkebyte' is de byte van 0-63 waarin de bit overeenkomt met de LED van 0-511 //Is het nu logisch waarom we dat deden? een waarde van 0-511 nemen en deze converteren naar een waarde van 0-63, aangezien elke LED een bit vertegenwoordigt in //een array van 64 bytes. //Dan is de volgende regel welke bit 'wholebyte-(8*whichbyte)' //Dit is simpelweg de waarde van de LED van 0-511 nemen en deze aftrekken van de BYTE, de bit bevond zich in tijden 8 //Denk erover na, byte 63 zal LED's bevatten van 504 tot 511, dus als u 505- (8*63) nam, krijgt u een 1, wat betekent dat //LED-nummer 505 zich in bit 1 van byte 63 in de array bevindt //is dat het? Nee, je moet nog steeds de bitRead doen van de helderheid 0-15 die je probeert te schrijven, // als je een 15 naar ROOD schreef, zouden alle 4 arrays voor die LED een 1 hebben voor dat bit, wat betekent dat het aan staat 100% //Dit is de reden waarom de vier arrays 0-4 lezen van de ingevoerde waarde voor ROOD, GROEN en BLAUW //hopelijk is dit allemaal logisch?}//***MultiPlex BAM***MultiPlex BAM** *MultiPlex BAM***MultiPlex BAM***MultiPlex BAM***MultiPlex BAM***MultiPlex BAMISR(TIMER1_COMPA_vect){ //Deze routine wordt automatisch op de achtergrond aangeroepen op de frequentie die is ingesteld door OCR1A //In deze code stel ik OCR1A tot 30, dus dit wordt elke 124us genoemd, wat elk niveau in de kubus 124us van AAN-tijd geeft // Er zijn 8 niveaus, dus we hebben een maximale helderheid van 1/8, omdat het niveau moet uitschakelen voordat het volgende niveau is ingeschakeld //De frequentie van het multiplexen is dan 124us*8=992us, of 1/992us=ongeveer 1kHz PORTD |=1 <=CUBE_SIZE) { fx =CUBE_MAX; fxm =-1; } pauze; geval 1:fy =fy + fym; if (fy <0) { fy =0; fym =1; } if (fy>=CUBE_SIZE) { fy =CUBE_MAX; fym =-1; } pauze; geval 2:fz =fz + fzm; als (fz <0) { fz =0; fzm =1; } if (fz>=CUBE_SIZE) { fz =CUBE_MAX; fzm =-1; } pauze; } schakelaar (willekeurig (3)) { geval 0:ftx =ftx + ftxm; als (ftx <0) { ftx =0; ftxm =1; } if (ftx>=CUBE_SIZE) { ftx =CUBE_MAX; ftxm =-1; } pauze; geval 1:fty =fty + ftym; if (fty <0) {fty =0; ftym =1; } if (fty>=CUBE_SIZE) {fty =CUBE_MAX; ftym =-1; } pauze; geval 2:ftz =ftz + ftzm; als (ftz <0) { ftz =0; ftzm =1; } if (ftz>=CUBE_SIZE) { ftz =CUBE_MAX; ftzm =-1; } pauze; } } //while clean();}//wipeout//****rainVersionTwo****rainVersionTwo****rainVersionTwo****rainVersionTwo****rainVersionTwovoid rainVersionTwo(int runtimeInSeconds){ int x[LEDS_PER_LEVEL ], y[LEDS_PER_LEVEL], z[LEDS_PER_LEVEL], ledkleur; 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   

Schema's

eagle_files_WfqPEUP7Mp.zip

Productieproces

  1. Dorstalarm plantalarm
  2. 5x5x5 LED-kubus
  3. Italiaanse Word Clock
  4. Sigfox kWh-meter
  5. Arduino RGB-kleurenmixer
  6. Bluetooth-temperatuurmeter
  7. DMX RGB LED buiten
  8. Gebarengestuurd slot
  9. The Companion IC
  10. Een geïsoleerde analoge ingang voor Arduino
  11. Meet je reactietijd