Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

Cube LED RVB 8x8x8

Composants et fournitures

Anode commune diffuse RVB
× 512
Pilote LED DM13A
× 12
74HC138 3 à 8 lignes de décodage
× 1
IRF9640 P-Channel MOSFET
× 8
Arduino UNO
Vous pouvez également créer une version de maquette avec juste un ATmega328, cristal 16Mhz, 2 x condensateurs 22pf
× 1
Alimentation à découpage Digilent 5V 2.5A
× 1
Résistance 10k ohm
× 8
Résistance 1k ohm
× 8
Résistance 100 ohm
× 8

Applications et services en ligne

Arduino IDE

À propos de ce projet

Vidéo

Construire

Cette construction a été inspirée par le cube Kevin Darrah RGB.

En regardant la carrure de Kevin, sa patience ne doit pas avoir de limites - malheureusement la mienne en a.

J'ai décidé de remplacer les 24 registres à décalage, 192 transistors et 640 résistances par 12 drivers LED DM13a (environ 1 $ US chacun sur eBay).

Le cube lui-même a été construit comme Kevin le décrit dans la vidéo suivante :

Une fois le cube fabriqué, j'ai créé une carte de circuit imprimé en utilisant la méthode Toner pour contenir les puces de pilote DM13A et le cube lui-même. Plutôt que de payer le coût d'une carte fabriquée dans le commerce avec un placage traversant, j'ai décidé de câbler chaque connexion LED à la broche DM13A appropriée à l'aide d'un fil enroulé. Les fichiers Eagle inclus contiennent la version câblée à la main ainsi qu'une version routée automatiquement (non testée).

Le microprocesseur et la carte d'anode contiennent également un MSGEQ7 - un égaliseur graphique à sept bandes et un préampli de microphone que je prévois d'expérimenter à l'avenir. À l'heure actuelle, ils ne sont pas utilisés. Si vous souhaitez utiliser une carte UNO ou Nano commerciale, tout ce dont vous avez besoin est le décodeur 74HC138 3 à 8 lignes et les MOSFET 8 canaux P et les résistances associées. Vous pouvez simplement les câbler sur une proto-carte si vous le souhaitez.

L'alimentation 5V 20W a été achetée sur eBay. J'ai fait le boîtier en pin habillé de 40 mm x 9 mm.

J'ai ajouté quelques animations au logiciel Kevin's Cube, mais elles restent pratiquement inchangées.

Conclusion

Vous devriez pouvoir acheter des LED RVB à anode commune 600 x 5 mm sur eBay pour environ 30 $ US. Même après avoir simplifié l'électronique, la construction du cube a pris beaucoup de temps mais au final, gratifiante.

Code

  • Cube_8x8x8_V1.ino
Cube_8x8x8_V1.inoC/C++
/* Le cube LED RVB 8x8x8 de John Bradnam basé sur le travail de Kevin DarrahLatestV12 17/04/2013Release Notes :V11- Correction d'un bug avec la synchronisation BAM- Déplacement de la configuration des broches vierges vers ISR afin que les broches soient mortes jusqu'à ce qu'elles soient écrites dans l'opération V12 bits à définir les broches LOW étaient incorrectes devraient être PORTx &=~(1<// Bibliothèque SPI utilisé pour synchroniser les données vers les registres à décalage#define LATCH_PIN 2 //peut utiliser n'importe quelle broche que vous souhaitez verrouiller les registres à décalage#define BLANK_PIN 4 // idem, peut utiliser n'importe quelle broche que vous voulez pour cela, assurez-vous simplement de tirer via a 1k à 5V#define DATA_PIN 11 // utilisé par SPI, doit être la broche 11#define CLOCK_PIN 13 // utilisé par SPI, doit être 13#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 //Nombre de colonnes, de lignes ou de niveaux dans le cube#define CUBE_MAX (CUBE_SIZE - 1) //Max cube dans dex#define LEDS_PER_LEVEL (CUBE_SIZE * CUBE_SIZE) //Nombre de LEDS par niveau//***variables***variables***variables***variables***variables***variables***variables***variables //Ces variables sont utilisées par le multiplexage et le code de modulation d'angle binaire//C'est ainsi que la luminosité de chaque LED est stockée, //Chaque LED n'a besoin que d'un "bit" pour savoir si elle doit être allumée ou éteinte, donc 64 octets donnent vous 512 bits =512 LED//Comme nous modulons les LED, en utilisant une résolution de 4 bits, chaque couleur a 4 tableaux contenant 64 bits chaque octet 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] ; la résolution augmentera plus[LEDS_PER_LEVEL] ; plus de votre précieux RAMint level=0 ; // garde une trace du niveau auquel nous déplaçons les données vers anodeLevel=0 ; // cela s'incrémente à travers les niveaux d'anodeint BAM_Bit , BAM_Counter=0; // Variables de modulation d'angle binaire pour garder une trace des chosesint animation =0; //Garde une trace de l'animation dans la boucle principale//****setup****setup****setup****setup****setup****setup****setup**** setup****setup****setup****setup****setup****setupvoid setup(){ SPI.setBitOrder(MSBFIRST);//Bit le plus significatif en premier SPI.setDataMode(SPI_MODE0) ; // Mode 0 Front montant des données, gardez l'horloge basse SPI.setClockDivider(SPI_CLOCK_DIV2);//Exécutez les données à 16MHz/2 - 8MHz //Serial.begin(115200); // si vous en avez besoin ? noInterrupts();// tue les interruptions jusqu'à ce que tout le monde soit configuré //Nous utilisons la minuterie 1 pour rafraîchir le cube TCCR1A =B00000000 ;//Register A tous les 0 puisque nous ne basculons aucune broche TCCR1B =B00001011 ;//bit 3 défini à placer en mode CTC, appellera une interruption sur une correspondance de compteur // les bits 0 et 1 sont définis pour diviser l'horloge par 64, donc 16MHz/64=250kHz TIMSK1 =B000000010;//bit 1 défini pour appeler l'interruption sur un OCR1A correspond à OCR1A=30 ; // vous pouvez jouer avec ça, mais je l'ai mis à 30, ce qui signifie ://notre horloge tourne à 250kHz, soit 1/250kHz =4us //avec OCR1A réglé sur 30, cela signifie que l'interruption sera appelée tous les ( 30+1)x4us=124us, // ce qui donne une fréquence de multiplexage d'environ 8 kHz // enfin configurer le pinMode de sorties (LATCH_PIN, OUTPUT); // Latch pinMode (DATA_PIN, OUTPUT); // MOSI DATA pinMode (CLOCK_PIN, SORTIE ); // 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 Switch pinMode(SWITCH_SEQ, INPUT);//SEQ/COLOR Switch //pinMode(BLANK_PIN, OUTPUT);//Output Enable important de le faire en dernier, donc les LED le font ne clignote pas au démarrage SPI.begin();//démarre les interruptions de la bibliothèque SPI ();//laisse le show commencer, cela permet au multiplexage de démarrer}//***start loop***start loop*** start loop***start loop***start loop***start loop***start loop***start loop***start loopvoid loop(){ //Chaque animation située dans une sous-routine // Pour contrôler un LED, vous simplement :// LED(niveau que vous voulez 0-CUBE_MAX, rangée que vous voulez 0-CUBE_MAX, colonne que vous voulez 0-CUBE_MAX, luminosité rouge 0-15, luminosité verte 0-15, luminosité bleue 0-15); if (digitalRead(SWITCH_PGM) ==HIGH) test_leds(); else { nettoyer (); animation =animation + 1 ; switch (animation) { cas 1 :rainVersionTwo(20); Pause; cas 2 :dossier (10); Pause; cas 3 :sinwaveTwo(15); Pause; cas 4:randomColor(10); Pause; cas 5 :wipe_out(10) ; Pause; cas 6 :rebondirVTwo(15); Pause; cas 7 :color_wheelTWO(10) ; Pause; cas 8 :harlem_shake(); Pause; cas 9 :ondulations(10) ; Pause; cas 10 :animation =0; Pause; } }}//****LED Routine****LED Routine****LED Routine****LED Routinevoid LED(int level, int row, int column, byte red, byte green, byte blue){ // C'est là que tout commence // Cette routine est la façon dont les LED sont mises à jour, avec les entrées pour l'emplacement de la LED et ses niveaux de luminosité RG et B // Tout d'abord, vérifiez et assurez-vous que rien n'a dépassé les limites, fixez simplement les choses à soit 0 ou 7 pour l'emplacement, et 0 ou 15 pour le niveau de luminosité =contrainte(niveau, 0, CUBE_MAX); ligne =contrainte (ligne, 0, CUBE_MAX); colonne =contrainte(colonne, 0, CUBE_MAX); rouge =contrainte(rouge, 0, 15); vert =contraindre (vert, 0, 15); bleu =contraindre (bleu, 0, 15); //Il y a des LED (CUBE_SIZE * CUBE_SIZE * CUBE_SIZE) dans le cube, donc lorsque nous écrivons au niveau 2, colonne 5, ligne 4, cela doit être traduit en un nombre de 0 à (CUBE_SIZE * CUBE_SIZE * CUBE_SIZE) - 1 //Les voyants du premier niveau sont les premiers dans la séquence, puis le 2ème niveau, puis le troisième, et ainsi de suite //Pour un cube 4 x 4 x 4 le (niveau * (4 * 4)) est ce qui indexe le point de départ du niveau, donc le niveau 0 correspond aux LED 0 - 15, le niveau 1 correspond aux LED 16 - 31, et ainsi de suite // si vous avez regardé le cube en bas et que vous n'avez regardé que le niveau inférieur // 00 01 02 03 // 04 05 06 07 / / 08 09 10 11 // 12 13 14 15 //Pour un cube 8 x 8 x 8 le (niveau * (8 * 8)) est ce qui indexe le point de départ du niveau, donc le niveau 0 sont les LED 0 - 63, niveau 1 sont des LED 64 - 127, et ainsi de suite // si vous avez regardé le cube en bas et que vous n'avez regardé que le niveau inférieur // 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 //Ensuite, si vous incrémentiez le niveau, le coin supérieur droit de la grille ci-dessus commencerait à (CUBE_SIZE * CUBE_SIZE) //La raison de cela est que vous n'ayez pas à mémoriser un nombre pour chaque LED, vous permettant d'utiliser le niveau, la ligne, la colonne // Maintenant, qu'en est-il de la division par 8 là-dedans ? //... eh bien, nous avons 8 bits par octet, et nous avons 64 octets en mémoire pour les 512 bits nécessaires pour chaque LED, donc // nous divisons le nombre que nous venons de trouver par 8, et en prenons l'entier, donc nous savons dans quel octet se trouve ce bit //confused? c'est ok, prenons un exemple, si nous voulions écrire sur la LED jusqu'à la dernière LED du cube, nous écririons un 7, 7, 7 // donnant (7*64)+(7*8)=7 =511, ce qui est juste, mais maintenant divisons-le par 8, 511/8 =63,875, et prenons l'entier ainsi, nous obtenons 63, // c'est le dernier octet du tableau, ce qui est juste puisque c'est le last LED // Obtenir le numéro de LED 0 - 511 int wholebyte =(level * LEDS_PER_LEVEL) + (row * CUBE_SIZE) + column; // Récupère l'index dans le tableau. Chaque emplacement indexé contient un octet ou 8 bits ; int quel octet =int (octet entier / 8); int quel bit =(octet entier &7); // Tout cela aura un sens en une seconde // Il s'agit d'une résolution de couleur de 4 bits, donc chaque couleur contient des tableaux x4 de 64 octets, explication ci-dessous :bitWrite(red0[whichbyte], whichbit, bitRead(red, 0)); bitWrite(red1[quel octet], quel bit, bitRead(rouge, 1)); bitWrite(red2[quel octet], quel bit, bitRead(rouge, 2)); bitWrite(red3[quel octet], quel bit, bitRead(rouge, 3)); bitWrite(green0[quel octet], quel bit, bitRead(vert, 0)); bitWrite(green1[quel octet], quel bit, bitRead(vert, 1)); bitWrite(green2[quel octet], quel bit, bitRead(vert, 2)); bitWrite(green3[quel octet], quel bit, bitRead(vert, 3)); bitWrite(blue0[quel octet], quel bit, bitRead(bleu, 0)); bitWrite(blue1[quel octet], quel bit, bitRead(bleu, 1)); bitWrite(blue2[quel octet], quel bit, bitRead(bleu, 2)); bitWrite(blue3[quel octet], quel bit, bitRead(bleu, 3)); // Êtes-vous maintenant plus confus? Vous ne devriez pas l'être ! Cela commence à avoir du sens maintenant. Remarquez comment chaque ligne est un bitWrite, c'est-à-dire //bitWrite(l'octet dans lequel vous voulez écrire, le bit de l'octet à écrire et le 0 ou 1 que vous voulez écrire) //Cela signifie que le "quel octet" est l'octet de 0 à 63 dans lequel le bit correspondant à la LED de 0 à 511 // a du sens maintenant, pourquoi avons-nous fait cela ? prendre une valeur de 0 à 511 et la convertir en une valeur de 0 à 63, puisque chaque LED représente un bit dans // un tableau de 64 octets. //Puis la ligne suivante est quel bit 'wholebyte-(8*whichbyte)' //Ceci prend simplement la valeur de la LED de 0-511 et la soustrait de l'octet, son bit était situé au temps 8 //Pensez-y, octet 63 contiendra des LED de 504 à 511, donc si vous avez pris 505-(8*63), vous obtenez un 1, ce qui signifie que // le numéro de LED 505 est situé dans le bit 1 de l'octet 63 dans le tableau // est-ce que ce? Non, vous devez toujours faire le bitRead de la luminosité 0-15 que vous essayez d'écrire, // si vous écrivez un 15 à RED, les 4 tableaux pour cette LED auront un 1 pour ce bit, ce qui signifie qu'il sera allumé 100% //C'est pourquoi les quatre tableaux lisent 0-4 de la valeur entrée pour ROUGE, VERT et BLEU //espérons que tout cela a un sens ?}//***MultiPlex BAM***MultiPlex BAM** *MultiPlex BAM***MultiPlex BAM***MultiPlex BAM***MultiPlex BAM***MultiPlex BAMISR(TIMER1_COMPA_vect){ //Cette routine est appelée en arrière-plan automatiquement à la fréquence définie par OCR1A //Dans ce code, je définis OCR1A à 30, donc cela s'appelle tous les 124us, donnant à chaque niveau du cube 124us de temps ON // Il y a 8 niveaux, nous avons donc une luminosité maximale de 1/8, car le niveau doit s'éteindre avant que le niveau suivant ne soit allumé //La fréquence du multiplexage est alors de 124us*8=992us, soit 1/992us=environ 1kHz PORTD |=1 <=CUBE_SIZE) { fx =CUBE_MAX; fxm =-1; } Pause; cas 1 :fy =fy + fym; if (fy <0) { fy =0; amy =1 ; } if (fy>=CUBE_SIZE) { fy =CUBE_MAX; fm =-1; } Pause; cas 2 :fz =fz + fzm; si (fz <0) { fz =0; fzm =1 ; } si (fz>=CUBE_SIZE) { fz =CUBE_MAX; fzm =-1; } Pause; } switch (random(3)) { cas 0 :ftx =ftx + ftxm; si (ftx <0) { ftx =0; ftxm =1 ; } si (ftx>=CUBE_SIZE) { ftx =CUBE_MAX; ftxm =-1; } Pause; cas 1 :fty =fty + ftym; if (fty <0) { fty =0; ftym =1 ; } if (fty>=CUBE_SIZE) { fty =CUBE_MAX; ftym =-1; } Pause; cas 2 :ftz =ftz + ftzm; si (ftz <0) { ftz =0; ftzm =1 ; } si (ftz>=CUBE_SIZE) { ftz =CUBE_MAX; ftzm =-1; } Pause; } } //pendant qu'il est propre();}//wipeout//****rainVersionTwo****rainVersionTwo****rainVersionTwo****rainVersionTwo****rainVersionTwovoid rainVersionTwo(int runtimeInSeconds){ int x[LEDS_PER_LEVEL ], y[LEDS_PER_LEVEL], z[LEDS_PER_LEVEL], ledcolor ; 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++; si (couleur led>=300) couleur led=0; for(int addr =0; addr

Schémas

eagle_files_WfqPEUP7Mp.zip

Processus de fabrication

  1. Alarme de soif d'usine
  2. Cube LED 5x5x5
  3. Horloge de mots italienne
  4. Compteur kWh Sigfox
  5. Mixeur de couleurs Arduino RVB
  6. Moniteur de température Bluetooth
  7. DMX RGB LED extérieur
  8. Une entrée analogique isolée pour Arduino
  9. Mesurez votre temps de réaction