MENU

【歪门邪道】浅谈RGB的各种实现

September 10, 2017 • 瞎折腾

今天我是要来耍一波流氓了——我一直觉得只谈理论不搞实践的都是耍流氓,可是无可奈何人到高三就有些身心俱乏,实在是不想懒得在大雨天中翻箱倒柜找单片机面包板RGB灯条什么的搞个最小系统来实验,可另一方面又不想让这个站就这么荒废一年,所以,今天还是从理论上说一说几种RGB的实现方式吧。

前言

也不知道从什么时候开始,PC组装行业就开始时兴RGB了,不知道各位喜不喜欢,反正我是不喜欢。电脑硬件不怎么样,打开电源灯倒是挺亮——当然,如果谁要是有雅兴去装个什么8路丽台M6000那我也无话可说.但是一个键盘——还不是什么樱桃轴青轴的上好机械硬盘,就一淘宝10块钱包邮的——加上RGB价格都能翻十番,还有各种机箱什么的,但凡是和RGB挂钩的,貌似都不便宜,而且还有效拉低了性价比。

如上所述,其价值或许就在于电脑的硬件,从主板到显卡是自身支持RGB的,并且能够很方便的在使用过程中调整。但是个人而言,且不说不喜欢忽闪忽闪的灯,就光是成本我觉得也有些不值。机箱RGB只是作为本文的一个引入话题,但本文并不会教你怎么给自己的机箱加一个便宜好用的RGB,我只是想说一说我想到的和目前网上主流的RGB实现方式。至于怎么给自己的机箱加RGB,知道我也不说2333

灯条

灯条是RGB的核心组件,当然你也可以用一个个共阳极三色LED连一块,但是现在市面上已经有很成熟的产品了,买来就好了。相比国外,国内能够买到的通常就是裸条,就是只有灯泡和限流电阻。通常来说上面的灯泡有两种:一种是一个灯泡上有RGB(红绿蓝)三种颜色,接线有4根——公用的Vcc和三种颜色对应的GND;另一种我还没有见到,也没买到,是RGBW,一个灯泡上除了上述的三种颜色之外还有一个单独的白光,这样当你需要白光的时候就不用同时点亮3个灯了。

而对应裸条的,就是我常在youtube上看到国外大佬使用的带有主控芯片的灯条,这种灯条是在裸条的基础上增加了负责驱动的主控,相比直接调整对应颜色的引脚电压,这种灯条可以直接按照主控芯片的数据手册将颜色信息发给它,剩下的事情你就不用管了。

本文所讨论的RGB是基于上述前者之RGB裸条的,我买这个灯条的时候大概在2015年前后,对应我的第一篇制作文少鹿岛灯的文章

实现

PWM

在上面提到的这篇文章中,我试用了类似PWM技术的方式。PWM是通过在单位时间内调整高低电平的比例来完成,如下图所示:

TIM截图20170910124415.png

其中$T$代表周期,其倒数就是频率,$\alpha$代表空白的时间,则占空比为$\frac{\alpha}{T}$。直观的来看电路输出是一个方波,最大值是高电平(Vcc),最小值是低电平(GND),丝毫没有起到调整电压改变亮度的作用,但是由于单片机或其他芯片的处理速度很快,因此可以用如下公式表示输出电压:

$$V = \frac{T-\alpha}{T}$$

但是对于三路甚至四路PWM,这样的单片机不太好找。我知道的最多只有2路PWM,因此我是手动实现的PWM。其流程图大致如下:

TIM截图20170910133437.png

通过每隔一段时间触发一次定时器来完成工作。每次触发的时候首先会检测当前触发了多少次,因为颜色代码的RGB上限是255,所以这里设定的最大数值是256,即0-255是有效操作。一旦到达256次,程序会清空计数器以开启新一次的循环,同时会给三种颜色对应的R、G、B三个变量装载新的数值。而如果不是256次,那么程序将依次检查RGB三个颜色对应的变量。如果红色对应的变量R变成0了,那么本次就关闭红色通道,如果不是0,那么就打开红色的通道并给R减去一,剩下的绿色蓝色相同,进行完一次之后再给总的次数加1。

假设每次执行完256次触发所用的时间为$T$,那么$\frac{1}{T}$就是刷新率,理论上刷新率不应当低于30Hz,而每次触发之间的空闲时间间隔中你可以让程序做一些其他事情,比如更改RGB的数值来完成颜色的改变、呼吸。这里值得注意的是要防止一种尴尬的情况,就是你的程序正在修改RGB的纸,已经修改了R和G的值,正要改变B的值时,中断来了,一次256循环做完了,中断程序来读取新的RGB数值了,可你的程序还没有把B更新,这时候就GG了。为了避免这个问题,应该提前算好更新数值这些操作所用的时间,或者增加一个标志位,在更新数值的时候阻止中断程序读取数值,但是这样可能会造成闪屏或其他意想不到的问题。

PWM改进版

我在百度上查的资料和我自己实现的基本如上,但是我在想能否让各个颜色分布的均匀一些。在上述实现方法中,总会有一段时间是几个灯同时亮而最后剩下一个数值较大的灯最后熄灭,比如上面的蓝色灯。这个想法的示意图如下:

TIM截图20170910140110.png

看起来很简单,只是将上面堆在一起的高电平输出打碎、分散到整个256次循环中。但是其算法复杂度我没有实现过,但是我估计对于单片机来说可能有点压力山大。

我设想的实现方法如下:

数学

假定一个颜色的数值为$x , x \in [0,255], x \in {\cal Z}$,那么在256次循环内应该有$x$次为高电平,如果$x\%2 = 0$,即$x$为偶数时,每个高低电平的持续时间为$\frac{128}{x}$,同时设某段输出电平序号为$k , k$的初始值为0,那么每次$k\%2 \neq 0$时则输出高电平,条件不成立时输出低电平。

$x\%2 \neq 0$时,即$x$为奇数时,则每个高低电平的持续时间为$\frac{255}{2x}$,其余条件不变。

统计概率学

如果程序有生成随机数的功能,那个可以用这个功能来随机输出随机布尔值。若为真则在该次循环内点亮,为假则熄灭。每次为真都给对应的变量(事先装在好数值)-1,如果$255 - k$等于前述的变量,那么从该次循环开始一直点亮,直到256次循环完成。理论上讲真和假的概率相同,因此在很大的样本上应该呈现出随机并均匀分布的状态。

DAC

如果说上述方法有什么用处,那就像是再说给音响用的线缆的插头镀金能提高音质一样,在刷新率较高的时候:没用,在刷新率较低的时候,刷新率都低了,你觉得你的程序还能腾出闲工夫来搞什么随机、运算之类的嘛?要我说,如果真的要相对完美的弄出RGB,那就应该上DAC,毕竟输出是电压的模拟量,比如要使额定电压为5v的红色LED亮度减半,那么输出就是真真切切的2.5V,而不是在T周期内一半是5v一般是0v的方波。但是有一点遗憾的就是响应速度快一点的DAC芯片都比较贵,而且多半是音响用的DAC,而且各种芯片的性能和解码方式都不同,因此要根据数据手册来。

总结

关于文中提到的三种方法,我只尝试过第一种,至于改进版的PWM内的数学运算是否符合逻辑,还请各位读者前来指证,我实在是不太擅长计算这个。另外如果有什么好的实现方法,也欢迎各位留个评论什么的。


知识共享许可协议
【歪门邪道】浅谈RGB的各种实现天空 Blond 采用 知识共享 署名 - 非商业性使用 - 相同方式共享 4.0 国际 许可协议进行许可。
本许可协议授权之外的使用权限可以从 https://skyblond.info/about.html 处获得。

Last Modified: March 31, 2023
Archives QR Code
QR Code for this page
Tipping QR Code