Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

Construa um Cubo LED RGB 8x8x8 com Arduino – Guia DIY

Componentes e Materiais

Componente Quantidade Observações
LED RGB Difuso Ânodo Comum 512
Driver LED DM13A 12
Decodificador 74HC138 3 para 8 linhas 1
MOSFET P-Channel IRF9640 8
Arduino UNO 1 Também pode criar versão breadboard com ATmega328, cristal 16MHz, 2x capacitores 22pf
Fonte Chaveada 5V 2,5A (Digilent) 1
Resistor 10k Ω 8
Resistor 1k Ω 8
Resistor 100 Ω 8

Software e Serviços Online

Sobre o Projeto

Vídeo

Vídeo da construção disponível.

Construção

Esta construção foi inspirada no cubo RGB de Kevin Darrah.

Construa um Cubo LED RGB 8x8x8 com Arduino – Guia DIY

Olhando a construção do Kevin, sua paciência não deve ter limites - infelizmente a minha tem.

Decidi substituir os 24 registradores de deslocamento, 192 transistores e 640 resistores por 12 drivers LED DM13A (cerca de $1 cada no eBay).

Construa um Cubo LED RGB 8x8x8 com Arduino – Guia DIY

O próprio cubo foi construído como Kevin descreve no seguinte vídeo:

Construa um Cubo LED RGB 8x8x8 com Arduino – Guia DIY

Uma vez feito o cubo, criei uma placa de circuito impresso usando o método do toner para acomodar os chips drivers DM13A e o próprio cubo. Em vez de pagar o custo de uma placa feita comercialmente com metalização de furos passantes, decidi conectar manualmente cada conexão de LED ao pino apropriado do DM13A usando wire-wrap wire. Os arquivos Eagle incluídos contêm a versão com fiação manual e uma versão auto-roteada (não testada).

Construa um Cubo LED RGB 8x8x8 com Arduino – Guia DIY
Construa um Cubo LED RGB 8x8x8 com Arduino – Guia DIY

O microprocessador e a placa de ânodo também acomodam um MSGEQ7 - Equalizador Gráfico de Sete Bandas e pré-amplificador de microfone que planejo experimentar no futuro. Por enquanto, não são usados. Se quiser usar uma placa UNO ou Nano comercial, tudo que precisa é o decodificador 74HC138 3-para-8 e os 8 MOSFETs P-Channel e resistores associados. Você pode apenas conectá-los em protoboard se quiser.

A fonte 5V 20W foi comprada no eBay. Fiz o gabinete de pinho aparelhado 40mm x 9mm.

Construa um Cubo LED RGB 8x8x8 com Arduino – Guia DIY

Adicionei algumas animações ao software do cubo do Kevin, mas basicamente permanece inalterado.

Conclusão

Você deve conseguir comprar 600 LEDs RGB 5mm Ânodo Comum difusos no eBay por cerca de $30. Mesmo simplificando a eletrônica, a construção do cubo foi muito demorada mas no final, recompensadora.

Código

Cube_8x8x8_V1.ino (C/C++)

/* Cubo LED RGB 8x8x8 por John Bradnam baseado no trabalho de Kevin Darrah
 * Última V12 04/17/2013
 * Release Notes:
 * V11 - Correção de bug no timing BAM
 *     - Movido configuração pino Blank para ISR para que pinos fiquem inativos até serem escritos
 * V12 - Operação bitwise para definir pinos LOW estava incorreta, deve ser PORTx &= ~(1<<pinNumber);
 * Disclaimer: Não sou construtor profissional de cubo LED, é assim que eu fiz, este é meu cubo
 */

#include <SPI.h> // Biblioteca SPI usada para clock de dados para registradores de deslocamento

#define LATCH_PIN 2  // pode usar qualquer pino para travar registradores
#define BLANK_PIN 4  // qualquer pino, certifique-se de pull-up via 1k para 5V
#define DATA_PIN 11  // usado por SPI, deve ser pino 11
#define CLOCK_PIN 13 // usado por SPI, deve ser 13
#define LAYER_A 5    // Entrada A do 74138
#define LAYER_B 6    // Entrada B do 74138
#define LAYER_C 7    // Entrada C do 74138
#define SWITCH_PGM 10 // PB2
#define SWITCH_SEQ 9  // PB1
#define CUBE_SIZE 8  // Número de colunas, linhas ou níveis no cubo
#define CUBE_MAX (CUBE_SIZE - 1) // Índice máximo do cubo
#define LEDS_PER_LEVEL (CUBE_SIZE * CUBE_SIZE) // Número de LEDs por nível

//***variáveis***variáveis***variáveis***variáveis***variáveis***variáveis***variáveis***variáveis
// Estas variáveis são usadas pelo multiplexing e código de Modulação de Ângulo de Bit (BAM)
// É assim que o brilho de cada LED é armazenado,
// Cada LED só precisa de um 'bit' para saber se deve estar LIGADO ou DESLIGADO, então 64 Bytes dão 512 bits = 512 LEDs
// Como estamos modulando os LEDs, usando resolução de 4 bits, cada cor tem 4 arrays contendo 64 bits cada
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];

// note como mais resolução consumirá mais da sua preciosa RAM
int level = 0;        // acompanha qual nível estamos enviando dados
int anodeLevel = 0;   // incrementa através dos níveis de ânodo
int BAM_Bit, BAM_Counter = 0; // Variáveis BAM para acompanhar coisas
int animation = 0;    // Acompanha animação no loop principal

//****setup****setup****setup****setup****setup****setup****setup****setup****setup****setup****setup****setup****setup
void setup() {
  SPI.setBitOrder(MSBFIRST); // Most Significant Bit First
  SPI.setDataMode(SPI_MODE0); // Modo 0 Borda de subida do dado, clock baixo
  SPI.setClockDivider(SPI_CLOCK_DIV2); // Dados a 16MHz/2 - 8MHz
  
  noInterrupts(); // mata interrupções até todos estarem configurados
  
  // Usamos Timer 1 para atualizar o cubo
  TCCR1A = B00000000; // Registrador A todos 0's já que não estamos toggleando pinos
  TCCR1B = B00001011; // bit 3 para modo CTC, chamará interrupção em match de contador
                      // bits 0 e 1 dividem clock por 64, então 16MHz/64=250kHz
  TIMSK1 = B00000010; // bit 1 para chamar interrupção em match OCR1A
  OCR1A = 30; // brinque com isso, mas configurei para 30, o que significa:
              // nosso clock roda a 250kHz, que é 1/250kHz = 4us
              // com OCR1A=30, interrupção chamada a cada (30+1)x4us=124us,
              // frequência de multiplex de ~8kHz
  
  // finalmente configure as Saídas
  pinMode(LATCH_PIN, OUTPUT);
  pinMode(DATA_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(LAYER_A, OUTPUT);
  pinMode(LAYER_B, OUTPUT);
  pinMode(LAYER_C, OUTPUT);
  digitalWrite(LAYER_A, LOW);
  digitalWrite(LAYER_B, LOW);
  digitalWrite(LAYER_C, LOW);
  pinMode(SWITCH_PGM, INPUT);
  pinMode(SWITCH_SEQ, INPUT);
  // pinMode(BLANK_PIN, OUTPUT); // importante fazer por último, para LEDs não piscarem no boot
  SPI.begin(); // inicia biblioteca SPI
  interrupts(); // deixa o show começar, isso inicia o multiplexing
}

//***início loop***início loop***início loop***início loop***início loop***início loop***início loop***início loop***início loop
void loop() {
  // Cada animação localizada em sub-rotina
  // Para controlar um LED, simplesmente:
  // LED(nível 0-CUBE_MAX, linha 0-CUBE_MAX, coluna 0-CUBE_MAX, brilho vermelho 0-15, verde 0-15, azul 0-15);
  
  if (digitalRead(SWITCH_PGM) == HIGH) test_leds();
  else {
    clean();
    animation = animation + 1;
    switch (animation) {
      case 1: rainVersionTwo(20); break;
      case 2: folder(10); break;
      case 3: sinwaveTwo(15); break;
      case 4: randomColor(10); break;
      case 5: wipe_out(10); break;
      case 6: bouncyvTwo(15); break;
      case 7: color_wheelTWO(10); break;
      case 8: harlem_shake(); break;
      case 9: ripples(10); break;
      case 10: animation = 0; break;
    }
  }
}

//****Rotina LED****Rotina LED****Rotina LED****Rotina LED****Rotina LED****Rotina LED****Rotina LED****Rotina LED
void LED(int level, int row, int column, byte red, byte green, byte blue) {
  // Verifica limites
  level = constrain(level, 0, CUBE_MAX);
  row = constrain(row, 0, CUBE_MAX);
  column = constrain(column, 0, CUBE_MAX);
  red = constrain(red, 0, 15);
  green = constrain(green, 0, 15);
  blue = constrain(blue, 0, 15);
  
  // Obtém número do LED 0-511
  int wholebyte = (level * LEDS_PER_LEVEL) + (row * CUBE_SIZE) + column;
  // Índice no array. Cada posição guarda 1 byte = 8 bits
  int whichbyte = int(wholebyte / 8);
  int whichbit = (wholebyte & 7);
  
  // Resolução de cor 4 bits, cada cor contém 4 arrays de 64 bytes
  bitWrite(red0[whichbyte], whichbit, bitRead(red, 0));
  bitWrite(red1[whichbyte], whichbit, bitRead(red, 1));
  bitWrite(red2[whichbyte], whichbit, bitRead(red, 2));
  bitWrite(red3[whichbyte], whichbit, bitRead(red, 3));
  bitWrite(green0[whichbyte], whichbit, bitRead(green, 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));
}

//***MultiPlex BAM***MultiPlex BAM***MultiPlex BAM***MultiPlex BAM***MultiPlex BAM***MultiPlex BAM***MultiPlex BAM
ISR(TIMER1_COMPA_vect) {
  // Chamado automaticamente em background na frequência definida por OCR1A
  // Neste código, OCR1A=30, chamado a cada 124us, dando a cada nível 124us de tempo ON
  // São 8 níveis, então brilho máximo de 1/8, pois nível deve desligar antes do próximo ligar
  // Frequência de multiplex = 124us*8=992us, ou 1/992us = ~1kHz
  
  PORTD |= 1 << BLANK_PIN; // Primeiro desliga todos LEDs, escrevendo 1 no pino blank
  
  // BAM de 4 bits. 8 níveis, quando '1' escrito no brilho da cor,
  // cada nível tem chance de acender por 1 ciclo, BAM_Bit acompanha qual bit modulamos dos 4 bits
  // BAM_Counter é contagem de ciclos, incrementa a cada nível aceso
  if (BAM_Counter == (CUBE_SIZE * 1)) BAM_Bit++;
  else if (BAM_Counter == (CUBE_SIZE * 3)) BAM_Bit++;
  else if (BAM_Counter == (CUBE_SIZE * 7)) BAM_Bit++;
  BAM_Counter++;
  
  int bytes_per_level = LEDS_PER_LEVEL / 8;
  int shift_max = level + bytes_per_level;
  
  switch (BAM_Bit) {
    case 0:
      for (int shift_out = level; shift_out < shift_max; shift_out++) SPI.transfer(blue0[shift_out]);
      for (int shift_out = level; shift_out < shift_max; shift_out++) SPI.transfer(green0[shift_out]);
      for (int shift_out = level; shift_out < shift_max; shift_out++) SPI.transfer(red0[shift_out]);
      break;
    case 1:
      for (int shift_out = level; shift_out < shift_max; shift_out++) SPI.transfer(blue1[shift_out]);
      for (int shift_out = level; shift_out < shift_max; shift_out++) SPI.transfer(green1[shift_out]);
      for (int shift_out = level; shift_out < shift_max; shift_out++) SPI.transfer(red1[shift_out]);
      break;
    case 2:
      for (int shift_out = level; shift_out < shift_max; shift_out++) SPI.transfer(blue2[shift_out]);
      for (int shift_out = level; shift_out < shift_max; shift_out++) SPI.transfer(green2[shift_out]);
      for (int shift_out = level; shift_out < shift_max; shift_out++) SPI.transfer(red2[shift_out]);
      break;
    case 3:
      for (int shift_out = level; shift_out < shift_max; shift_out++) SPI.transfer(blue3[shift_out]);
      for (int shift_out = level; shift_out < shift_max; shift_out++) SPI.transfer(green3[shift_out]);
      for (int shift_out = level; shift_out < shift_max; shift_out++) SPI.transfer(red3[shift_out]);
      // Reset BAM_Counter
      if (BAM_Counter == (CUBE_SIZE * 15)) {
        BAM_Counter = 0;
        BAM_Bit = 0;
      }
      break;
  }
  
  // Envia nível de ânodo
  digitalWrite(LAYER_A, bitRead(anodeLevel, 0));
  digitalWrite(LAYER_B, bitRead(anodeLevel, 1));
  digitalWrite(LAYER_C, bitRead(anodeLevel, 2));
  
  PORTD |= 1 << LATCH_PIN;  // Latch HIGH
  PORTD &= ~(1 << LATCH_PIN); // Latch LOW
  PORTD &= ~(1 << BLANK_PIN); // Blank LOW para ligar LEDs com novos dados
  
  anodeLevel = (anodeLevel + 1) & (CUBE_MAX);
  level = (level + bytes_per_level) & (LEDS_PER_LEVEL - 1);
  
  pinMode(BLANK_PIN, OUTPUT); // movido aqui para saídas ficarem desligadas até primeira chamada
}

//****Animações****Animações****Animações****Animações****Animações****Animações****Animações****Animações
// (Código das animações truncado por tamanho - download completo no GitHub)

// Teste de LEDs
void test_leds() {
  clean(); delay(1000);
  fill(15, 0, 0); delay(1000);
  fill(0, 15, 0); delay(1000);
  fill(0, 0, 15); delay(1000);
}

// Outras animações: wipe_out, rainVersionTwo, folder, sinwaveTwo, randomColor, bouncyvTwo, color_wheelTWO, harlem_shake, ripples
// Código completo disponível para download.

Esquemáticos

Construa um Cubo LED RGB 8x8x8 com Arduino – Guia DIY Construa um Cubo LED RGB 8x8x8 com Arduino – Guia DIY eagle_files_WfqPEUP7Mp.zip

Processo de manufatura

  1. Alerta Inteligente de Sede para Plantas – Sensor DIY para Hidratação Ideal
  2. Construa um Cubo de LED 5x5x5 Impressionante com Arduino Mega
  3. Relógio de Palavras em Italiano com Arduino Nano, NeoPixel, LCD e RTC
  4. Medidor kWh Confiável com Sigfox e Arduino MKR Fox 1200
  5. Misturador de Cores RGB com Arduino – Projeto DIY para Iniciantes
  6. Monitor de Temperatura com Bluetooth usando Arduino Nano
  7. Projetores LED RGB Externos com DMX – Alta Performance e Custo Acessível
  8. Fechadura por Gestos Sem Toque: Acesso Seguro com APDS-9960 e Arduino
  9. Circuito de Entrada Analógica Isolada para Arduino
  10. Teste de Tempo de Reação Preciso com Arduino UNO