热胶 LED 矩阵灯
组件和用品
| × | 128 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 64 |
必要的工具和机器
|
应用和在线服务
|
关于这个项目
该灯基于 jbumstead 称为“光纤”LED 矩阵的类似灯。使用 OpenSCAD,目标是用廉价的 WS2812B RGB 灯条替换 jbumstead 设计中使用的 12 毫米漫射数字 RGB LED,并使 LED 和电子设备的容器尽可能薄,从而可以使用更便宜的 7 毫米胶棒。
打印案例
唯一需要支撑的部分是“Hot Glue Matrix - Bottom.stl”。我使用了 0.2 毫米的层高和 15% 的填充。我发现通过在打印后使用 19/64" 钻头增加孔尺寸可以更容易地将胶棒插入各自的孔中。
组装灯泡部分
1. 将WS2812B LED灯条剪成16条,每条8个LED。
2. 您不能将 LED 灯条直接在顶部或底部模板上连接在一起,因为它们颠倒放置在每个模板上。将 8 条带粘贴到平面上,每条带的中心距相邻条带 15 毫米。排列条带,使每个替代条带面向相反的方向。
确保 DIN 位于左上角。如上图所示连接条带。我使用绕线,但您可以使用任何细绝缘铜线。接线后,将三根长多股线添加到 GND、DIN 和 +5V。这些电线将穿过一个孔并与底部的 GND、DOUT 和 +5V 连接。现在将三根电线穿过“热胶矩阵 - 支架顶部”表格上的孔,并小心地将条带倒置放入各自的通道中。条带应该平放。如果不是,请检查条带是否正确。他们只走一种方式。电线也有通道。 LED 灯条就位后,使用 Blue Painters 胶带将其固定到位。
3. 以类似的方式连接底板。 DOUT 在右上角。将三根长多股线添加到 VCC、DIN 和 GND,然后将条带倒置在表格上。这些电线将连接到 PCB。
4.在所有胶棒都到位之前,不要从顶部连接电线。
添加胶棒
这将需要一些耐心。首先,您需要对胶棒进行分类。您从 eBay 获得的 7 毫米胶棒长约 100 米。我发现它们有点不同。我的一包是 30 根,所以我有 90 根棍子来找到 64 根相似长度的棍子。此外,我需要在打印后使用 19/64" 钻头增加孔尺寸,使其更容易装入孔中。
我还用了一根透明的吸管,把连接上下条带的三根线放进去。
从一端开始逐行添加胶水,然后一直到另一端。一旦它们都到位,测量每个角的顶部和底部之间的距离。它们都应该完全相同。如果没有,相应地调整胶棒的深度。对对齐感到满意后,从每个角落取下胶棒,然后用少量强力胶将它们放回原位。 (不要在 LED 上涂强力胶)。这应该使结构非常健壮。
连接顶部和底部条带
小心地提起靠近孔的底部条带,修剪三根电线并将它们焊接到位。 +5V至+5V,DIN(顶部)至DOUT(底部),GND至GND。
制作PCB
如果您希望获得商业制造的电路板或像我一样自己制作电路板,我已经包含了 Eagle 文件。我使用碳粉方法制作了我的电路板。如果您愿意,您可以只使用一块原型板,因为原理图非常简单且易于接线。 4 个安装孔应使用 2.5 毫米钻头和 3 毫米丝锥创建的螺纹钻出。使用 6mm M3 螺丝将电路板固定到位。
重要提示:将直流稳压器的输出设置为 5V,然后再将其固定到电路板上。
最终布线
如下图接线滑动电位器、按钮开关、电源开关和直流电源插座:
将 LED 灯条的电线连接到 PCB。
软件
包含的软件运行一系列测试动画。该按钮循环显示可用的动画。电位器调节动画的速度。
代码
- GlueMatrixTest.ino
- 按钮.h
- Button.cpp
GlueMatrixTest.inoC/C++
#include#ifdef __AVR__ #include #endif#include "Button.h"#define PIN_LED 2#define PIN_SWITCH 3#define PIN_POT A0#define LEDS 128// 参数1 =条带中的像素数// 参数 2 =Arduino 引脚编号(大多数有效)// 参数 3 =像素类型标志,根据需要相加:// NEO_KHZ800 800 KHz 比特流(大多数 NeoPixel 产品 w/WS2812 LED)/ / NEO_KHZ400 400 KHz(经典的“v1”(不是 v2)FLORA 像素,WS2811 驱动程序)// NEO_GRB 像素连接到 GRB 比特流(大多数 NeoPixel 产品)// NEO_RGB 像素连接到 RGB 比特流(v1 FLORA 像素,而不是 v2) // NEO_RGBW 像素为 RGBW 比特流接线(NeoPixel RGBW 产品)Adafruit_NeoPixel strip =Adafruit_NeoPixel(LEDS, PIN_LED, NEO_GRB + NEO_KHZ800);Button mode =Button(PIN_SWITCH);bool modePressed =false;//底部的物理 LED 映射LED阵列//LED底部(从顶部向后看)//064 049 048 033 032 017 016 001//063 050 047 034 031 018 015 002//062 051 046 035 0301 035 0301 / / 061 052 045 036 029 020 013 004 060 // 053 044 037 028 021 012 005 059 // 054 043 038 027 022 011 006 058 // 055 042 039 026 023 010 007 057 // 056 041 040 025 024 009 008 / /(从顶部看)//LED 顶部(从顶部看)//065 080 081 096 097 112 113 128//066 079 082 095 098 111 114 127//067 078 083 0916 // 16 077 084 093 100 109 116 125 069 // 076 085 092 101 108 117 124 070 // 075 086 091 102 107 118 123 071 // 074 087 090 103 106 119 122 072 // 073 088 089 104 105 120 121 //(从顶部向前看)const uint8_t botLED[] PROGMEM ={ 64,49,48,33,32,17,16,1, 63,50,47,34,31,18,15,2, 62,51,46 ,35,30,19,14,3,61,52,45,36,29,20,13,4,60,53,44,37,28,21,12,5,59,54,43,38 ,27,22,11,6, 58,55,42,39,26,23,10,7, 57,56,41,40,25,24,9,8,};const uint8_t topLED[] PROGMEM ={65,80,81,96,97,112,113,128,66,79,82,95,98,111,114,127,67,78,83,94,99,110,115,126,68,77,84,93,100,109,116,125,69,76,85,92,101,108,117,124,70,75 ,86,91,102,107,118,123, 71,74,87,90,103,106,119,122, 72,73,88,89,104,105,120,1 21};//当前值的存储int red =128;int green =128;int blue =128;int pattern =1;//重要提示:为了降低NeoPixel烧毁风险,在//像素电源引线上添加1000 uF电容,添加第一个像素的数据输入上的 300 - 500 欧姆电阻器 // 并最小化 Arduino 和第一个像素之间的距离。避免在带电电路上连接//...如果必须,请先连接 GND。void setup() { Serial.begin(115200); pinMode(PIN_LED,输出); pinMode(PIN_SWITCH,输入); pinMode(PIN_POT,输入); //像素条Serial.println("Setup()"); strip.begin();带.show(); // 将所有像素初始化为“关闭” //按钮回调 //mode.Background(ButtonBackground); //为MODE引脚上的引脚更改设置ISR Button::PinChangeSetup(PIN_SWITCH);}void loop() { if (modePressed) { pattern =(pattern % 8) + 1;带.clear(); } modePressed =false; Serial.print("模式"); Serial.print(pattern, DEC); Serial.println(); switch (pattern) { case 1:colorWipe(strip.Color(255, 0, 0));休息; // 红色情况 2:colorWipe(strip.Color(0, 255, 0));休息; // 绿色情况 3:colorWipe(strip.Color(0, 0, 255));休息; // 蓝色案例 4:theatreChase(strip.Color(127, 127, 127));休息; // 白色案例 5:rainbow();休息;案例 6:rainbowDifference();休息;情况 7:rainbowCycle();休息;案例 8:rainbowCycleDifference();休息;案例 9:theatreChaseRainbow();休息; } if (!modePressed) { modePressed =mode.Pressed(); }}//模式按钮中断以跳出循环等//PCINT1处理A0到A5ISR(PCINT2_vect)引脚的引脚变化{ modePressed =modePressed | (mode.State() ==LOW);}void ButtonBackground(void){}// 用一个 colorvoid 一个接一个地填充点 colorWipe(uint32_t c) { int total =strip.numPixels() / 2; for(uint16_t i=0; i 0 &&!modePressed; i--) { uint8_t botIndex =pgm_read_byte(&botLED[i]) - 1; strip.setPixelColor(botIndex, 0); uint8_t topIndex =pgm_read_byte(&topLED[i]) - 1; strip.setPixelColor(topIndex, 0);带.show();延迟(地图(模拟读取(PIN_POT),0, 1024, 100, 0)); }}void Rainbow() { int total =strip.numPixels() / 2; for(uint16_t j=0; j <256 &&!modePressed; j++) { for(uint16_t i=0; i Button.hC 头文件
/*Class:ButtonAuthor:John Bradnam ([email protected]) 目的:处理按钮的Arduino库*/#pragma once#include "Arduino.h"#define DEBOUNCE_DELAY 5//重复速度#define REPEAT_START_SPEED 500# define REPEAT_INCREASE_SPEED 50#define REPEAT_MAX_SPEED 50class Button{ public://简单的构造函数Button(int Pin); //在等待或重复循环中调用的后台函数 void Background(void (*pBackgroundFunction)()); //按下按钮时调用的重复函数 void Repeat(void (*pRepeatFunction)()); //测试按钮是否被按下和释放 //如果有则调用repeat函数 bool Pressed(); //返回按钮状态(HIGH或LOW)-LOW =Pressed int State(); //引脚更改中断设置 //D8 到 D13 的 ISR (PCINT0_vect) 引脚更改中断 //A0 到 A5 的 ISR (PCINT1_vect) 引脚更改中断 //D0 到 D7 的 ISR (PCINT2_vect) 引脚更改中断 static void PinChangeSetup(byte别针);私人:int _pin;无效(*_repeatCallback)(无效); void (*_backgroundCallback)(void);};Button.cppC/C++
#include "Button.h"Button::Button(int pin){ _pin =pin; pinMode(_pin, INPUT);}//设置函数在延迟或重复循环中调用void Button::Background(void (*pBackgroundFunction)()){ _backgroundCallback =pBackgroundFunction;}//设置函数在重复系统需要时调用void Button ::Repeat(void (*pRepeatFunction)()){ _repeatCallback =pRepeatFunction;}static void Button::PinChangeSetup(byte pin) { *digitalPinToPCMSK(pin) |=bit (digitalPinToPCMSKbit(pin)); // 启用引脚 PCIFR |=位 (digitalPinToPCICRbit(pin)); // 清除任何未完成的中断 PCICR |=位 (digitalPinToPCICRbit(pin)); // 为组启用中断 }// 测试按钮是否被按下和释放 // 如果按钮被按下和释放则返回 true // 如果提供重复回调,则在按下键时调用回调bool Button::Pressed( ){ 布尔按下 =假; if (digitalRead(_pin) ==LOW) { unsigned long wait =millis() + DEBOUNCE_DELAY;而 (millis() <等待) { 如果 (_backgroundCallback !=NULL) { _backgroundCallback(); } } if (digitalRead(_pin) ==LOW) { //设置为重复循环 if (_repeatCallback !=NULL) { _repeatCallback(); } 无符号长速度 =REPEAT_START_SPEED;无符号长时间 =毫秒()+ 速度; while (digitalRead(_pin) ==LOW) { if (_backgroundCallback !=NULL) { _backgroundCallback(); } if (_repeatCallback !=NULL &&millis()>=time) { _repeatCallback(); unsigned long fast =speed - REPEAT_INCREASE_SPEED;如果(更快>=REPEAT_MAX_SPEED){ 速度 =更快;时间 =毫秒()+ 速度;按下 =真; } } return press;}//返回当前按钮状态int Button::State(){ return digitalRead(_pin);}
定制零件和外壳
用于 3D 打印的 STL 文件 stl_files_vSNeOCJWDn.zip示意图
Eagle 格式的原理图和 PCB eagle_files_D8oAM5ngf5.zip制造工艺