산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

8x8x8 RGB LED 큐브

구성품 및 소모품

RGB 확산 공통 양극
× 512
DM13A LED 드라이버
× 12
74HC138 3-8줄 디코딩
× 1
IRF9640 P-채널 MOSFET
× 8
Arduino UNO
ATmega328, 16Mhz 크리스탈, 2 x 22pf 커패시터만으로 브레드보드 버전을 만들 수도 있습니다.
× 1
Digilent 5V 2.5A 스위칭 전원 공급 장치
× 1
저항 10k 옴
× 8
저항 1k 옴
× 8
저항 100옴
× 8

앱 및 온라인 서비스

Arduino IDE

이 프로젝트 정보

동영상

빌드

이 빌드는 Kevin Darrah RGB 큐브에서 영감을 받았습니다.

Kevin의 빌드를 보면 그의 인내심은 끝이 없을 것입니다. 불행히도 제 인내심은 그렇습니다.

저는 24개의 시프트 레지스터, 192개의 트랜지스터 및 640개의 저항을 12개의 DM13a LED 드라이버로 교체하기로 결정했습니다(eBay에서 각각 US $1).

큐브 자체는 Kevin이 다음 비디오에서 설명한 대로 제작되었습니다.

큐브가 만들어지면 DM13A 드라이버 칩과 큐브 자체를 고정하기 위해 토너 방식을 사용하여 인쇄 회로 기판을 만들었습니다. 스루홀 도금으로 시판되는 보드 비용을 지불하는 대신 와이어 랩 와이어를 사용하여 각 LED 연결을 적절한 DM13A 핀에 직접 배선하기로 결정했습니다. 포함된 Eagle 파일에는 수동 유선 버전과 자동 라우팅 버전(테스트되지 않음)이 포함되어 있습니다.

마이크로 프로세서와 양극 보드에는 MSGEQ7 - Seven Band Graphic Equalizer와 마이크 프리앰프도 탑재되어 있습니다. 지금은 사용되지 않습니다. 상용 UNO 또는 나노 보드를 사용하려면 74HC138 3-8 라인 디코더와 8 P-채널 MOSFET 및 관련 저항만 있으면 됩니다. 원하는 경우 일부 프로토보드에 배선할 수 있습니다.

5V 20W 전원 공급 장치는 eBay에서 구입했습니다. 케이스는 40mm x 9mm 옷을 입힌 소나무로 만들었습니다.

Kevin의 큐브 소프트웨어에 몇 가지 애니메이션을 추가했지만 기본적으로 변경되지 않습니다.

결론

eBay에서 약 30달러에 600 x 5mm 공통 양극 확산 RGB LED를 구입할 수 있습니다. 전자 제품을 단순화한 후에도 큐브를 만드는 데 시간이 많이 걸렸지만 결국 보람이 있었습니다.

<섹션 클래스="섹션 컨테이너 섹션 축소 가능" id="코드">

코드

<울>
  • Cube_8x8x8_V1.ino
  • Cube_8x8x8_V1.inoC/C++
    /*The 8x8x8 RGB LED Cubeby John Bradnambased on work by Kevin DarrahLatestV12 04/17/2013Release Notes:V11- BAM 타이밍 관련 버그 수정- 빈 핀 설정을 ISR로 이동하여 핀이 쓰기 전까지 핀이 작동하지 않도록 설정합니다. 핀 LOW가 잘못되었습니다.PORTx &=~(1<// SPI 라이브러리 시프트 레지스터로 데이터를 클럭하는 데 사용#define LATCH_PIN 2 //시프트 레지스터를 래치하려는 핀을 사용할 수 있음#define BLANK_PIN 4 // 동일, 원하는 핀을 사용할 수 있습니다. a 1k ~ 5V#define DATA_PIN 11 // SPI에서 사용, 핀 11이어야 함#define CLOCK_PIN 13 // SPI에서 사용, 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 //큐브의 열, 행 또는 레벨 수#define CUBE_MAX (CUBE_SIZE - 1) //최대 큐브 입력 dex#define LEDS_PER_LEVEL (CUBE_SIZE * CUBE_SIZE) //레벨당 LED 수//***변수***변수***변수***변수***변수***변수***변수***변수 //이 변수는 다중화 및 비트 각도 변조 코드에 의해 사용됩니다.//이것이 모든 LED의 밝기가 저장되는 방식입니다. //각 LED는 ON 또는 OFF여야 하는지 알기 위해 '비트'만 필요하므로 64바이트는 다음을 제공합니다. 512비트=512 LED // 4비트 해상도를 사용하여 LED를 변조하므로 각 색상에는 64비트를 포함하는 4개의 어레이가 있습니다. 각 바이트 red0[LEDS_PER_LEVEL], red1[LEDS_PER_LEVEL], red2[LEDS_PER_LEVEL], red3[LEDS_PER_LEVEL]; 파랑0[LEDS_PER_LEVEL], 파랑1[LEDS_PER_LEVEL], 파랑2[LEDS_PER_LEVEL], 파랑3[LEDS_PER_LEVEL];바이트 녹색0[LEDS_PER_LEVEL], 녹색1[LEDS_PER_LEVEL], 녹색2[LEDS_PER_LEVEL], 녹색3[LEDS_PER_LEVEL 이상] 더 많은 소중한 RAMint level=0;//데이터를 anodeLevel=0으로 이동하는 수준을 추적합니다. //이는 양극 수준을 통해 증가합니다int BAM_Bit , BAM_카운터=0; // thingsint를 추적하기 위한 비트 각도 변조 변수 animation =0; //메인 루프에서 애니메이션 추적//****setup****setup****setup****setup****setup****setup****setup**** setup****setup****setup****setup****setup****setupvoid setup(){ SPI.setBitOrder(MSBFIRST);//최상위 비트 우선 SPI.setDataMode(SPI_MODE0); // 모드 0 데이터의 상승 에지, 클럭을 낮게 유지 SPI.setClockDivider(SPI_CLOCK_DIV2);//16MHz/2 - 8MHz에서 데이터 실행 //Serial.begin(115200);// 필요한 경우? noInterrupts();// 모든 사람이 설정될 때까지 인터럽트 종료 // 큐브를 새로 고치기 위해 타이머 1을 사용 TCCR1A =B00000000;//핀을 토글하지 않기 때문에 A를 모두 0으로 등록 TCCR1B =B00001011;//비트 3 설정 CTC 모드에 배치하려면 카운터 일치에서 인터럽트를 호출합니다. //비트 0과 1은 클록을 64로 나누도록 설정되므로 16MHz/64=250kHz TIMSK1 =B00000010;//비트 1은 다음에서 인터럽트를 호출하도록 설정됩니다. OCR1A 일치 OCR1A=30; // 이것으로 플레이할 수 있지만 30으로 설정합니다. 즉, //우리의 클럭은 250kHz에서 실행되며, 이는 1/250kHz =4us입니다. //OCR1A를 30으로 설정하면 인터럽트가 호출될 간격( 30+1)x4us=124us, // 약 8kHz의 다중 주파수를 제공합니다. //마지막으로 출력 설정 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); 디지털 쓰기(LAYER_B, LOW); 디지털 쓰기(LAYER_C, LOW); pinMode(SWITCH_PGM, INPUT);//PGM 1 / PGM 2 Switch pinMode(SWITCH_SEQ, INPUT);//SEQ/COLOR Switch //pinMode(BLANK_PIN, OUTPUT);//Output 이 작업을 마지막으로 하는 것이 중요하므로 LED가 작동하도록 합니다. 부팅 시 깜박이지 않음 SPI.begin();//SPI 라이브러리를 시작합니다 interrupts();//쇼를 시작하게 하면 멀티플렉싱이 시작됩니다.}//***루프 시작****루프 시작*** 루프 시작***루프 시작***루프 시작***루프 시작***루프 시작***루프 시작***루프 시작 루프(){ //서브 루틴에 있는 각 애니메이션 // 제어 LED, 간단히:// LED(원하는 레벨 0-CUBE_MAX, 원하는 행 0-CUBE_MAX, 원하는 열 0-CUBE_MAX, 빨간색 밝기 0-15, 녹색 밝기 0-15, 파란색 밝기 0-15); if (digitalRead(SWITCH_PGM) ==HIGH) test_leds(); 그렇지 않으면 { 클린(); 애니메이션 =애니메이션 + 1; 스위치(애니메이션) { 경우 1:rainVersionTwo(20); 부서지다; 사례 2:폴더(10); 부서지다; 사례 3:sinwaveTwo(15); 부서지다; 사례 4:randomColor(10); 부서지다; 사례 5:Wipe_out(10); 부서지다; 사례 6:bouncyvTwo(15); 부서지다; 사례 7:color_wheelTWO(10); 부서지다; 사례 8:harlem_shake(); 부서지다; 사례 9:잔물결(10); 부서지다; 사례 10:애니메이션 =0; 부서지다; } }}//****LED 루틴****LED 루틴****LED 루틴****LED 루틴 무효 LED(int 수준, int 행, int 열, 바이트 빨간색, 바이트 녹색, 바이트 파란색){ //여기서 모든 것이 시작됩니다. //이 루틴은 LED 위치와 RG 및 B 밝기 레벨에 대한 입력으로 LED를 업데이트하는 방법입니다. // 먼저, 제한을 초과한 것이 없는지 확인하고 다음에서 고정합니다. 위치에 대해 0 또는 7, 밝기 레벨에 대해 0 또는 15 =constrain(level, 0, CUBE_MAX); 행 =제약(행, 0, CUBE_MAX); 열 =제약(열, 0, CUBE_MAX); 빨간색 =제약(빨간색, 0, 15); 녹색 =제약(녹색, 0, 15); 파란색 =제약(파란색, 0, 15); //큐브에 (CUBE_SIZE * CUBE_SIZE * CUBE_SIZE) LED가 있으므로 레벨 2, 열 5, 행 4에 쓸 때 0에서 (CUBE_SIZE * CUBE_SIZE * CUBE_SIZE) - 1 사이의 숫자로 변환되어야 합니다. //첫 번째 레벨 LED는 시퀀스의 첫 번째, 두 번째 레벨, 세 번째, 이런 식으로 //4 x 4 x 4 큐브의 경우 (level * (4 * 4))는 레벨의 시작 위치를 나타내는 것입니다. 그래서 레벨 0은 LED 0 - 15이고, 레벨 1은 LED 16 - 31입니다. // 큐브를 내려다보고 맨 아래 레벨만 본 경우 // 00 01 02 03 // 04 05 06 07 / / 08 09 10 11 // 12 13 14 15 //8 x 8 x 8 큐브의 경우 (레벨 * (8 * 8))은 레벨의 시작 위치를 나타내는 것이므로 레벨 0은 LED 0 - 63, 레벨 1입니다. LED는 64 - 127입니다. // 큐브를 내려다보고 맨 아래 수준만 본 경우 // 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 // 5 5 208 5 8 59 60 61 62 63 //그런 다음 레벨을 올리면 위 그리드의 오른쪽 상단이 (CUBE_SIZE * CUBE_SIZE)에서 시작됩니다. //이렇게 하는 이유는 숫자를 외울 필요가 없기 때문입니다. 각 LED에 대해 레벨, 행, 열을 사용할 수 있습니다. //이제 8로 나누는 것은 어떻습니까? //...글쎄, 바이트당 8비트가 있고 각 LED에 필요한 모든 512비트에 대해 메모리에 64바이트가 있으므로 //방금 찾은 숫자를 8로 나누고 그 정수를 취합니다. 그래서 우리는 어떤 바이트가 있는지 알고 있습니다. 그 비트는 // 혼란스럽습니까? 좋습니다. 예를 들어 큐브의 마지막 LED에 LED를 쓰려면 7, 7, 7 // 제공하는 (7*64)+(7*8)=7 =511, 맞습니다. 하지만 이제 8로 나누어 511/8 =63.875, 정수를 취하여 63을 얻습니다. // 이것은 배열의 마지막 바이트입니다. 마지막 LED // LED 번호 0 - 511 가져오기 int wholebyte =(레벨 * LEDS_PER_LEVEL) + (행 * CUBE_SIZE) + 열; // 배열에 인덱스를 가져옵니다. 각 인덱싱된 위치는 1바이트 또는 8비트를 보유합니다. int whichbyte =int(전체 바이트 / 8); int whichbit =(전체 바이트 &7); //이것은 모두 몇 초 안에 이해가 될 것입니다. //이것은 4비트 색상 해상도이므로 각 색상에는 x4 64바이트 배열이 포함됩니다. 설명은 아래에 있습니다. bitWrite(red0[whatbyte], whichbit, bitRead(red, 0)); bitWrite(red1[ whichbyte], whichbit, bitRead(red, 1)); bitWrite(red2[whatbyte], whichbit, bitRead(red, 2)); bitWrite(red3[ whichbyte], whichbit, bitRead(red, 3)); bitWrite(녹색0[어느바이트], 어느비트, bitRead(녹색, 0)); bitWrite(녹색1[어떤바이트], 어느비트, bitRead(녹색, 1)); bitWrite(green2[ whichbyte], whichbit, bitRead(녹색, 2)); bitWrite(그린3[어디바이트], 어느비트, bitRead(그린, 3)); bitWrite(blue0[whatbyte], whichbit, bitRead(blue, 0)); bitWrite(blue1[whatbyte], whichbit, bitRead(blue, 1)); bitWrite(blue2[whatbyte], whichbit, bitRead(blue, 2)); bitWrite(blue3[whatbyte], whichbit, bitRead(blue, 3)); //이제 더 혼란스럽습니까? 당신은 해서는 안됩니다! 이제 이해가 되기 시작했습니다. 각 줄이 어떻게 bitWrite인지, 즉 //bitWrite(쓰려는 바이트, 쓸 바이트의 비트, 쓰려는 0 또는 1) //이것은 'whatbyte' 0-511의 LED에 해당하는 비트가 있는 0-63의 바이트입니다. //이제 말이 되는 이유는 무엇입니까? 각 LED는 64바이트 배열의 비트를 // 나타내기 때문에 0-511의 값을 가져와 0-63의 값으로 변환합니다. //그런 다음 다음 줄은 'wholebyte-(8*whichbyte)' 비트입니다. // 이것은 단순히 LED의 값 0-511을 가져와서 BYTE에서 해당 비트를 8번의 시간에 뺀 것입니다. //생각해 보세요, 바이트 63은 504에서 511까지의 LED를 포함하므로 505-(8*63)를 취하면 1을 얻습니다. 즉, //LED 번호 505는 배열에서 바이트 63의 비트 1에 있습니다. 그것? 아니요, 여전히 쓰려는 밝기 0-15의 bitRead를 수행해야 합니다. // RED에 15를 쓴 경우 해당 LED에 대한 모든 4개의 어레이는 해당 비트에 대해 1을 가지므로 켜질 것입니다. 100% // 이것이 4개의 배열이 RED, GREEN 및 BLUE에 대해 입력된 값의 0-4를 읽는 이유입니다. //이 모든 것이 이해가 되기를 바랍니다.}//***MultiPlex BAM****MultiPlex BAM** *MultiPlex BAM***MultiPlex BAM***MultiPlex BAM***MultiPlex BAM***MultiPlex BAMISR(TIMER1_COMPA_vect){ //이 루틴은 OCR1A에서 설정한 주파수에서 백그라운드에서 자동으로 호출됩니다. //이 코드에서는 OCR1A에서 30으로, 그래서 이것은 124us마다 호출되어 큐브의 각 레벨에 ON 시간 124us를 제공합니다. // 8개의 레벨이 있으므로 다음 레벨이 시작되기 전에 레벨이 꺼져야 하므로 최대 밝기는 1/8입니다. 켜짐 // 다중화의 주파수는 124us*8=992us 또는 1/992us=약 1kHz입니다. PORTD |=1 <=CUBE_SIZE) { fx =CUBE_MAX; fxm =-1; } 부서지다; 사례 1:fy =fy + fym; if (fy <0) { fy =0; fym =1; } if (fy>=CUBE_SIZE) { fy =CUBE_MAX; fym =-1; } 부서지다; 사례 2:fz =fz + fzm; if (fz <0) { fz =0; fzm =1; } if (fz>=CUBE_SIZE) { fz =CUBE_MAX; fzm =-1; } 부서지다; } 스위치(random(3)) { 경우 0:ftx =ftx + ftxm; if (ftx <0) { ftx =0; ftxm =1; } if (ftx>=CUBE_SIZE) { ftx =CUBE_MAX; ftxm =-1; } 부서지다; 사례 1:fty =fty + ftym; if (fty <0) { fty =0; ftym =1; } if (fty>=CUBE_SIZE) { fty =CUBE_MAX; ftym =-1; } 부서지다; 사례 2:ftz =ftz + ftzm; if (ftz <0) { ftz =0; ftzm =1; } if (ftz>=CUBE_SIZE) { ftz =CUBE_MAX; ftzm =-1; } 부서지다; } } //청소하는 동안();}//wipeout//****rainVersionTwo****rainVersionTwo****rainVersionTwo****rainVersionTwo****rainVersionTwovoid rainVersionTwo(int runtimeInSeconds){ int x[LEDS_PER_LEVEL ], y[LEDS_PER_LEVEL], z[LEDS_PER_LEVEL], led색상; 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   

    회로도

    eagle_files_WfqPEUP7Mp.zip

    제조공정

    1. 갈증 경보 식물 알람
    2. 5x5x5 LED 큐브
    3. 이탈리아어 단어 시계
    4. Sigfox kWh 미터
    5. Arduino RGB 컬러 믹서
    6. 블루투스 온도 모니터
    7. DMX RGB LED 실외용
    8. 제스처 제어 잠금
    9. Arduino용 절연 아날로그 입력
    10. 반응 시간 측정