使用 WLED 制作节日彩灯

WLED 与 ws2812b 的组合既然如此好用(比如之前的项目),那么我们是不是可以做一个“大的”?其实很多时候一旦要“大”,问题就已经不大一样了。

悬挂

通常 LED 是安装在比较软的 PCB 上面,这不能固定整体的形状,而一粒一粒的 LED 比较刺眼,通过散射片可以将光线发散变得更为连续,显得更为专业。因此专业的安装需要使用铝条,上面留有槽嵌入散射片。常见的铝条有两种形状

  • U 型,这基本上就是一个槽,通常有较深的版本(大约 13mm,更贵 3+$/m),还有一个较浅的(大约 7mm,便宜 2.5$/m);开口方向与附着面是垂直的
  • V 型,这是个直角(常见的直角边为 16mm),中间通过一个斜边提供粘贴 LED 条的位置(便宜 2.5$/m),如果看到斜边的距离可能只有 5mm,但是往往会配置一个更为凸起的散射片;开口方向与附着面一般是 45 度夹角,更适合放在角落

如果我们想把这根条挂在屋檐边上的排水沟边上,选择 U 型铝条是一个更简单的选择。另外为了折衷价格(LED 的密度越高,价格越贵)与散射后光的一致性(密度越高,越容易一致),通常 60 LED/m + 加深的 U 型铝条是个不错的选择。更多的讨论参考 hook up 的这个视频

LED Diffusers

我最后还是决定赌一把买了个 V 型铝条,弧形的散射片稍微为散射提供了接近浅 U 型铝条的距离,另外 V 型的直角边比较容易钻孔让 power injection 的线缆更容易走(当然如果有拐角可以利用的话就不必要钻孔)。这样一来就出了个问题,怎么将这种铝条跟排水沟关联上?

排水沟侧面安装的铝条

我们大概的想法来自 thingiverse 上一些挂彩灯的钩子,当然挂绳子或者电线这种相对来说比较自由一些,只需要钩子就可以了,但是铝条就比较麻烦,我们参照铝条提供的一些连接件打印了

  • 两根铝条在同一直线上的连接卡子,它方便我们将两根铝条对齐,这样粘贴 LED 条的时候就不会有缝
  • 两根铝条存在 90 度的夹角,这里存在内 90 度和外 90 度两种,上图为外 90 度连接

更多的细节可以参看我上传到 thingiverse 上的模型

LED 的选择

市面上其实有很多不同类型的 LED,我们这里简单的介绍一些

  • 模拟信号的 LED,这类产品往往是不能单独控制每个 LED 的颜色、亮度的,设置颜色、亮度是对整个接入的灯带,因此比较适合做一些比较简单的颜色变换,通过颜色、明暗改变整体氛围。因此它非常的便宜,它们一般使用 RGB + 正极(4 pin)的连接,电压常见为 12/24 V直流。后来也有在此基础上增加白色光的 LED,也分 CW(冷色)/WW(暖色),这是可能会多一两个单独控制对应白色通道的
  • “数字”信号的 LED,其实更准确的称呼 addressable LED(可以给地址,因此每颗 LED 可以单独控制),也被称为 neopixel,由于每颗颜色、亮度都可以不一样,实现的特殊效果就会丰富许多,通过不同的排列方式(诸如带状,圆圈,矩阵)就可能获得更加有意思的效果,市面上最多的是 WS2812b 系列,而后有一些改进,但是如果考虑功耗、性价比, WS2812b(-eco) 绝对是独占鳌头。这个灯带往往只有电源正负极与一根数据线(3 pin),有些比较复杂的可能还有一个备份数据线路

可以参看 hook up 这个视频,这里有一份他总结的功耗分析

不同类型的 LED 灯带

WS2812b 之所以可以定位到每一个 LED 是因为它们之间存在一个很简单的协议,所有的数据(每颗需要 RGB 每个 8bit,因此一共 24bit 的数据,同时控制器需要知道一共有多少颗 LED)发送出来,接收到的 LED 很简单的“吃掉”自己的那份,将剩下的数据传递到后面即可。当然为了某些效果,LED 的连接可能并不是和逻辑方向一致,这我们需要通过软件将实际上 1-wire 分解成逻辑段落(segment),比如我们之前制作的 LED 灯,里面 5 段 LED,但是其连接是 zigzag 型,但是如果我们想要颜色从下往上渐变,由于这里的连接与逻辑冲突,我们需要将 1-5 个面中 2/4 面的方向反转过来。

本来打算搞个 WS2811 的带子(不是完全每颗 LED 能单独控制,而是 3 LED)玩玩,主要是一开始以为 12V 高压线缆通过的电流可以减少,这样就不会头疼需要粗电缆,但实际上 WS2811 功耗更大,也并不便宜。

WS2812b 每颗的功耗最大是 60mA * 5V = 0.3W,那么根据购买的 LED 条的密度可以很容易计算出来每米的功耗与需要的最大电流,比如 60 LED/m 需要的最大电流为每米 3.6A,对应的功耗为 18W。有了这个可以根据项目使用的 LED 灯带长度计算出总功率,比如一个 5m 的项目需要最大到 18A 电流,90W 功率的电源。需要注意的是,这里估计的是极限的情况,通常我们根本不需要这么高的配置(后文聊)。

LED 条一般有三种防水规格:

  • IP30:无防水处理,背面有 3M 双面胶,适合室内的项目
  • IP65:使用硅胶处理正面,背面有 3M 双面胶,适合我们现在需要做的户外项目
  • IP67:灯带塞入了硅胶条,背面没有 3M 双面胶,适合水下项目

一旦扯上防水,最烦人的大概就是为了改变长度、或者 power injection 需要焊额外的线缆需要能接触到里面,IP65 的可以用剪子去掉硅胶,处理完后重新填充;IP67 更为复杂,需要重新注入硅胶密封硅胶条。

电力供应

我们首先需要知道 WS2812b 的 LED 其实是“并联”的:灯带上缘跟下缘分别对应的是电源的正负极,数据线从中间过。这有几个问题:

  • 理想情况下,所有 LED 都拿到了 5V 输入电压,所以只要电源能提供足够的电流,就应该可以点亮所有的 LED
  • 由于数据线是串联,一旦中间一颗 LED 损坏(没法吃掉自己的数据并将剩余数据传递出去),后面所有的 LED 都会熄灭
  • 修理坏掉的 LED 也比较容易,可以替换成新的,或者干脆将数据线短路,跳过这个 dead pixel 即可

但是实际操作中我们很容易看到一个现象:如果我们调节灯带为白色,最高亮度,随着 LED 灯带变长,一开始的颜色还比较准确,越到后面越偏色(偏橘黄,乃至变成红色),产生这个现象的原因其实是“压降”(voltage drop),RGB 三色 LED 的工作电压范围其实是不一样的,其中红色工作电压的下限(约为 3.3V)更低,当电压低于一定时另外两种颜色都无法工作只有红色可以点亮。

那么压降是如何产生的呢?其实这就是灯带正负极(PCB 上的铜箔)本身的电阻导致的,我们可以拿欧姆计测量一根较长的灯带的电阻,比如我手头一根 5M 60 LED/m 的灯带,正极之间的电阻有 1.2 欧(参考 22awg 的线,1km 电阻约为 53 欧,这个 PCB 的铜箔差不多 480 欧),考虑到这一共有 300 颗 LED,其实两颗之间的电阻仅仅有 0.004 欧,只是随着长度的增加,电阻积累起来就产生了可观的压降。

压降示意图

我们可以简单的算一下,如果每个 LED 按照 60mA 的工作电流,每一个电阻(根据上面的估计为 R = 4 mOhm)通过的电流是后面的 LED 电流的和,所以如果有 N 个 LED,第一对电阻承受了 N * 60mA * 2R,而下一对为 (N-1) * 60mA * 2R,以此类推产生的压降为 60 mA * R * (N-1) * N,如果我们看 1m 的灯带 N = 60,获得的压降为 ~0.85V,那当我们走个 2M,此时的压降已经有 1.7V,接近 3.3V 的最低工作电压了,需要注意的是电流大小正比于压降,如果工作电流减小到原先的一半(可能很多情况下的工作电流仅有这个最大值的 1/3 或更低),灯带就可以延长一倍才会产生同等的压降。作为横向比较,可以对比参考这篇文章测量的结果,它提到数值跟我们这里基于理论值与实际测量电阻非常接近(每颗 LED 的电流 60mA vs 50mA,总电流 7.2A vs. 4.7A 导致的压降为 1.7V vs. 1.4V),

The 120 LED 2 m strip drew 4.7 A and had a voltage drop of 1.4 V.

from pololu.com

那么如何解决压降产生的问题?很显然,我们如果能把电源“直接”接入到后面的电路,这里我们需要注意的是因为实际的线缆(这里需要从电源连接到接入点,很可能有好几米)依然有电阻,我们的连接其实等价于下图

power injection 示意图

从某个角度来看新接入的导线把灯带的“等效”电阻降低了,因此可以分出一部分电流通过导线进入后面的 LED,具体这个 injection 可以帮助多少 LED,我们需要精细的计算,很显然如果导线电阻无限大,就没有电流通过;如果没有电阻,两侧 LED 数目相同的话则可以分担一半的电流。但是如果考虑效率,这个电阻率应该要比 PCB 上的铜箔小不少才会有用。可以参考前面讨论的

  • 22 awg 的线缆每公里 ~53 ohm
  • 16 awg 的线缆每公里 ~13 ohm

其实无论哪种都可以在我们这个项目中很好的完成 power injection,如果有担心线缆产生的压降,可以从主电源接驳 16 awg 的线缆到铝条附近,再换用 22 awg 的线缆进入铝条。

数据线

一颗 ESP8266 驱动灯带的时候需要使用 GPIO2 (D4 pin,参看这个 layout)作为数据的输出,我们知道它自身的工作电压其实是 3.3V,而不是为其供电的 USB 提供的 5V(内部进行了降压),但是往往开发板保留了 5V 的输出,这样一来偷懒的时候我们可以直接从开发板取电供给灯带,然后将 D4 与数据线连接,通常情况下如此简易的连接并不会产生任何的问题。但是我们需要知道,这里 WS2812b 的数据线其实要求的是 5V 的输入(参看这个 spec 第三页,数据线的电压为电源线电压的 0.7 倍,考虑到输入电压有一定的范围,对应的数据线电压应该至少有 ~3.5V),而不是 3.3V(参看这里)。

简化版连接方式

这意味着,我们做一些玩具项目的时候可以忽略这其中的不匹配,数据线很短,产生的压降不足以干扰对 LED 的控制。但是同时也告诉我们,一旦规模变大,数据线的长度不再是一个可以忽略的因素(如超过 1m),想要稳定的控制灯带,我们需要将输出的 3.3V 信号转换成为与电源一样的 5V 信号才能避免压降导致的控制问题。因此比较好的商业 LED 控制器里面一定还会增加一个 level shifter(电平转换器),比如常见的 4 通道双向转换 TXB0104。这样一来,新的连接如下

使用电平转换器解决数据线压降问题

这里我们也把灯带专用的电源分离了出来,往往 LED 控制器本身不需要很大的电流,比如常见的开发版使用自己的 USB 供电即可。不过如果想节省一点,也可以直接从大电源上接两根线连接到 Vin / GND 上作为 ESP8266 的输入电流。值得注意的是一般采用这类搞法,GND 需要共线保证低电平的起点一致。另外通常电平转换会有一个配套的限流电阻,这样保证短路情况下限流电阻控制通过芯片的电流不会过大。

但是这并不是一个唯一的解决方案,LED Head 提供了一个不大一样的方案,它同时考虑了低电平的电压差异(WS2812b 数据线的低电平大约在 1.5V),这样一来只要将控制器这边的 GND + GPIO 整体电压升高 0.7V 左右就可以保证驱动灯带数据线的电压相对于灯带的 GND 的差异接近 4.4V,而 GPIO 的低电平依然在 1.5V 以下。因此就避免了使用 level shifter。这个时候需要区分控制器的 GND 与电源 GND(也是灯带的 GND)。

不使用电平转换的连接方式

这里使用的元件都是非常便宜的,接在电源上给控制器供电的是两粒 zener diode(稳压二极管,每个可以导致 0.7V 的压降,价格在 0.01$/个)以及一个电容(稳压),比起 level shifter 来说可能是个更为经济简便的策略。

通过稳压二极管获得合理的输出电压

其实还有第三种方法,一般称为 sacrificial LED,牺牲掉一个 WS2812b,这个其实有点像是把 WS2812b 当作是一个 level shifter 用,因为 LED 本身接电(5V),进来的 ~3.3V 电压刚刚好能触发,这时输出的电平就是 5V 了,我们只需要在软件上做一个小小的调整,比如原先是 N 个 LED,现在设置成为 N+1 个,然后把第一个 LED 跳过(关掉它或者显示 0/0/0)就行了。这个方法的好处是

  • 无需购买新的片子(成本和学习成本都更低),通常只需要从边角上剪下来一个就可以用了
  • 可以在(数据)线路上多处接入 LED,如果数据线特别长,我个人感觉一般一个 LED 支持个 5m 的距离没啥问题

当然它不是一个一般性的解决方案,很多其他需要电平转换的地方这个策略不见得方便。

实际操作

WLED 作为当仁不让的 WS2812b 的控制器其实还有一个隐秘的功能,那就是电流限制,有了它我们可以不做任何 power injection 就能点亮一根 10m 60 LED/m 的灯带。那么它又是怎么一回事?其实也很简单,如果我们只有 1.2A 的电源(比如一个 USB 充电器),一个 LED 就只能分到 2mA 的电流,但是我们可以点亮 600 个 LED 啦!因此 wled 只需要根据电流限制作为额外的约束来分配亮度即可。很显然这种情况下,电源提供电流的大小决定了全亮情况下灯带的亮度。

那么我们可以结合 power injection 与 WLED 的电流限制功能,很方便的完成我们的项目了:

  • 估算灯带的最大功率:我大约有 18m+ 的灯带需要安装,依照 18m 算的话共 1080 颗 LED,大约需要 65A 的最大电流,最大功耗到了 324W,确实很费电啊
  • 但是我并不见得需要购买一个如此大功率的电源,比如我可以仅提供区区 20A 电流,区区 100W,也就个费电的白炽灯
  • 我把电流缩减到了原先的 1/3,这导致 power injection 的距离可以从原先 2m 变成 6m,因此灯带上有 3-5 个 power injection 的位置基本就够用了

那么数据线应该如何布置?实际上电源以及控制器在室内(车库里),对应的数据线与电源线是一起走到户外的,但是这里有个问题,power injection 是可以随意的发生在灯带的任意位置(因为 LED 是并联在灯带上的),唯一的约束就是供电是不是均衡,但加上控制器的电流限制功能,这个的选择的灵活程度就会大大提高。可是如果理解清楚 WS2812b 数据线的工作方式(一般的灯带上都标注了数据的方向,这是因为 LED 的输入输出方向是固定的,它并不会反向传递),我们就知道大概有这么几个选择:

  • 一个简化的操作当然是把数据线走到灯带的一侧,灯带安装的时候数据线从这一侧走向另一侧即可;如果电源距离这一侧较远,我们就需要多走一根线,而且不像 power injection 可以在中间接入,这个必须从灯带的一头接入
  • 如果我们想从中间把数据线接入,就需要把灯带从中间剪开,安装时灯带的数据线方向是从中间到两边,但是因为这是一根数据线,产生的信号会被两侧的 LED 对称的处理传输,这意味着我们要么从“正中间”接入获得完全对称的效果,要么不是正中间就会有一侧有丢失的部分。即便这样某些效果(比如从一侧点亮 LED 并移动到另一侧)由于镜像对称关系也是不能实现的。
  • 更为理想的中间接入的方式应该使用两根线,这意味着我们需要对两根灯带分开控制(同时也可以允许两侧的 LED 数目并不完全一样)而不是依赖其对称关系

事实上 WLED 从 0.12 版本之后就加入了多灯带的支持,由此导致的变化包括

  • 从控制器出来除了原先 D4(GPIO2),我们还需要 TX(GPIO1)接到数据线(因此一共四根电源线,两根数据线连接室内室外)
  • 一共 1080 颗 LED,可以尝试对半分或者一边稍微多一些(不超过 800 颗),这个可以依据实际屋檐长度来确定合理的接入点
  • WLED 配置中我们需要填上对应连接的 LED 数目,并通过 segment 将其中一段反转过来这样就能将两者从逻辑上衔接

其他的想法

这么折腾了一次,了解清楚了安装一个较大规模 LED 项目的点点滴滴,这时候回过头来看,也许选择一些成熟的 WLED 模块会是一个更为省事的做法。众多 youtuber 站台的 QuinLED 的售价大概是 40$,但是因为使用的 ESP32 可以扩展到 4 条灯带的控制,也不必纠结其中这些复杂的细节了,买来配置一下,接上线就可以了。

使用 WLED 制作节日彩灯

一个有关“使用 WLED 制作节日彩灯”的想法

留下评论