亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
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 ohm
× 8
电阻 1k ohm
× 8
电阻 100 ohm
× 8

应用和在线服务

Arduino IDE

关于这个项目

视频

构建

此版本的灵感来自 Kevin Darrah RGB 立方体。

看看凯文的身材,他的耐心一定是无止境的——不幸的是我的耐心。

我决定用 12 个 DM13a LED 驱动器(在 eBay 上每个约 1 美元)替换 24 个移位寄存器、192 个晶体管和 640 个电阻器。

立方体本身是按照凯文在以下视频中描述的那样构建的:

制作立方体后,我使用墨粉方法制作了一块印刷电路板,以固定 DM13A 驱动器芯片和立方体本身。与其支付带有通孔电镀的商用板的成本,我决定使用绕线将每个 LED 连接手工连接到适当的 DM13A 引脚。包含的 Eagle 文件包含手动接线版本以及自动路由版本(未经测试)。

微处理器和阳极板还有一个 MSGEQ7 - 七频段图形均衡器和麦克风前置放大器,我计划在未来进行实验。现在,它们没有被使用。如果您想使用商用 UNO 或 Nano 板,您只需要 74HC138 3 至 8 线解码器和 8 个 P 沟道 MOSFET 和相关电阻。如果您愿意,您可以将它们连接到一些原型板上。

5V 20W 电源是在易趣上购买的。我用 40 毫米 x 9 毫米的松木制作了箱子。

我在 Kevin 的魔方软件中添加了一些动画,但基本保持不变。

结论

您应该能够以大约 30 美元的价格从 eBay 购买 600 x 5mm 共阳极扩散 RGB LED。即使在简化了电子设备之后,立方体的构建也非常耗时,但最终还是值得的。

代码

  • Cube_8x8x8_V1.ino
Cube_8x8x8_V1.inoC/C++
/*The 8x8x8 RGB LED Cubeby John Bradnam 基于 Kevin DarrahLatestV12 04/17/2013 发布说明:V11-修复了 BAM 时序错误-将空白引脚设置移动到 ISR,因此引脚在写入 V12 按位操作以设置之前无效pin LOW 不正确应该是 PORTx &=~(1<// SPI 库用于将数据输出到移位寄存器#define LATCH_PIN 2 //可以使用任何你想锁存移位寄存器的引脚#define BLANK_PIN 4 // 同样,可以使用你想要的任何引脚,只要确保你通过a 1k to 5V#define DATA_PIN 11 // SPI 使用,必须是 pin 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字节给出you 512 bits=512 LEDs//由于我们调制LEDs,使用4位分辨率,每种颜色有4个数组,每字节64位red0[LEDS_PER_LEVEL], red1[LEDS_PER_LEVEL], red2[LEDS_PER_LEVEL], red3[LEDS_PER_LEVEL]; 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], green_3[LEVELS] 怎么吃分辨率more of yourprecious RAMint level=0;//跟踪我们将数据转移到哪个级别int anodeLevel=0;//这通过阳极级别递增int BAM_Bit , BAM_Counter=0; // 位角调制变量以跟踪事物int 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 的复用频率 //最后设置了 Outputs pinMode(LATCH_PIN, OUTPUT);//Latch pinMode(DATA_PIN, OUTPUT);//MOSI DATA pinMode(CLOCK_PIN, OUTPUT);//SPI时钟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,低);数字写入(LAYER_C,低); pinMode(SWITCH_PGM, INPUT);//PGM 1 / PGM 2 Switch pinMode(SWITCH_SEQ, INPUT);//SEQ/COLOR Switch //pinMode(BLANK_PIN, OUTPUT);//输出使能很重要,最后做这件事,所以 LED 做not flash on boot up SPI.begin();//启动SPI库interrupts();//让节目开始,这让多路复用开始}//***start loop***start loop*** start loop***start loop***start loop***start loop***start loop***start loop***start loopvoid loop(){ //每个动画位于一个子例程中 // 控制一个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; switch (animation) { case 1:rainVersionTwo(20);休息;案例2:文件夹(10);休息;情况 3:sinwaveTwo(15);休息;情况 4:随机颜色(10);休息;情况 5:wipe_out(10);休息;情况 6:bouncyvTwo(15);休息;情况 7:color_wheelTWO(10);休息;案例 8:harlem_shake();休息;案例9:涟漪(10);休息;情况 10:动画 =0;休息; } }}//****LED Routine****LED Routine****LED Routine****LED Routinevoid LED(int level, int row, int column, byte red, byte green, byte blue){ //这就是一切的开始 //这个例程是如何更新 LED,包括 LED 位置及其 RG 和 B 亮度级别的输入 // 首先,检查并确保没有超出限制,只需将东西夹在位置为 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 的立方体, (level * (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 5 5 5 5 5 5 5 7 5 8 59 60 61 62 63 //然后,如果你增加级别,上面网格的右上角将从(CUBE_SIZE * CUBE_SIZE)开始 //这样做的原因是你不必记住一个数字对于每个 LED,允许您使用级别、行、列 //现在,在那里除以 8 怎么样? //...好吧,我们每个字节有 8 位,每个 LED 所需的所有 512 位在内存中有 64 个字节,所以 // 我们将刚刚找到的数字除以 8,然后取其整数,所以我们知道哪个字节,那个位位于 //confused?没关系,让我们举个例子,如果我们想将 LED 写入立方体中的最后一个 LED,我们会写一个 7, 7, 7 // 给 (7*64)+(7*8)=7 =511,这是对的,但是现在让我们将它除以 8,511/8 =63.875,然后取它的整数,我们得到 63,//这是数组中的最后一个字节,这是正确的,因为这是last LED // 获取 LED 编号 0 - 511 int wholebyte =(level * LEDS_PER_LEVEL) + (row * CUBE_SIZE) + column; // 获取数组中的索引。每个索引位置保存一个字节或 8 位; int whichbyte =int(wholebyte / 8); int whichbit =(wholebyte &7); //这一切都会在一秒钟内有意义 //这是4位颜色分辨率,因此每种颜色包含x4个64字节数组,解释如下: 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)); //你现在更困惑了吗?你不应该!现在开始变得有意义了。注意每一行是一个bitWrite,也就是,//bitWrite(你想写的字节,要写的字节的位,以及你想写的0或1) //这意味着'whichbyte'是 0-63 的字节,其中对应于 0-511 的 LED 的位//现在为什么我们这样做有意义?取 0-511 之间的值并将其转换为 0-63 之间的值,因为每个 LED 表示 //64 字节数组中的一个位。 //然后下一行是哪一位'wholebyte-(8*whichbyte)' //这只是简单地将LED的值0-511从BYTE中减去它的位在时间8中的位置 //想想看,字节63 将包含从 504 到 511 的 LED,所以如果你取 505-(8*63),你会得到一个 1,这意味着,//LED 编号 505 位于数组中字节 63 的第 1 位 //就是它?不,您仍然必须执行您尝试写入的亮度 0-15 的 bitRead,//如果您将 15 写入 RED,则该 LED 的所有 4 个阵列都将为该位设置为 1,这意味着它将亮起100% //这就是为什么四个数组读取为 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调用一次,给立方体中每一级124us的ON时间 //有8级,所以我们有1/8的最大亮度,因为在下一级之前必须关闭该级开启 //复用的频率则为124us*8=992us,或1/992us=约1kHz PORTD |=1 <=CUBE_SIZE) { fx =CUBE_MAX; fxm =-1; } 休息;情况一:fy =fy + fym;如果 (fy <0) { fy =0; fym =1; } if (fy>=CUBE_SIZE) { fy =CUBE_MAX; fym =-1; } 休息;情况2:fz =fz + fzm;如果(fz <0){ fz =0; fzm =1; } if (fz>=CUBE_SIZE) { fz =CUBE_MAX; fzm =-1; } 休息; } switch (random(3)) { case 0:ftx =ftx + ftxm;如果(ftx <0){ ftx =0; ftxm =1; } if (ftx>=CUBE_SIZE) { ftx =CUBE_MAX; ftxm =-1; } 休息;情况1:fty =fty + ftym;如果(fty <0){ fty =0; ftym =1; } if (fty>=CUBE_SIZE) { fty =CUBE_MAX; ftym =-1; } 休息;情况2:ftz =ftz + ftzm;如果 (ftz <0) { ftz =0; ftzm =1; } if (ftz>=CUBE_SIZE) { ftz =CUBE_MAX; ftzm =-1; } 休息; } } //while clean();}//wipeout//****rainVersionTwo****rainVersionTwo****rainVersionTwo****rainVersionTwo****rainVersionTwovoidrainVersionTwo(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++;如果(ledcolor>=300)ledcolor=0; for(int addr =0; addr  

示意图

eagle_files_WfqPEUP7Mp.zip

制造工艺

  1. 干渴警报植物警报
  2. 5x5x5 LED 立方体
  3. 意大利字时钟
  4. Sigfox kWh Meter
  5. Arduino RGB 混色器
  6. 蓝牙温度监视器
  7. DMX RGB LED 户外
  8. 手势控制锁
  9. 伴侣 IC
  10. USB MIDI 适配器
  11. Arduino 的隔离模拟输入
  12. 测量你的反应时间