儿时的灯
儿时的白炽灯还依稀地亮在脑海的夜里。沾满了灰尘有些发黑的玻璃泡里,“W” 状的灯丝挂在那里,昏黄而又无力。那时经常停电倒是其次,在不同时段里,随着用电负荷的变化,灯的亮度也在不断地变化着。所以那个时候调压器成了电视机的伴侣。
对发光二极管 LED 来说,是否也可用调节其两端电压的方式来改变它的亮度?很多年前我就是这么想的。
LED发光原理简介
这个问题要从 LED 的发光原理来分析。我们知道,二极管N区的自由电子会在电场的作用力下向 P 区移动与空穴复合。当电子从高能级的轨道向低能级的轨道跃迁时,会释放出光子。当能量足够大时便形成可见光。可见,发出什么颜色的光是由 LED 的材质和工艺决定的,而发出多亮的光则是由释放出多少光子决定的,它的直接因素是电流的大小。电场的强度可以影响通过 LED 的电流的大小,所以改变 LED 两端的电压是可以改变它的亮度的。不同的二极管有不同的工作电压范围,且动态范围较窄,不易控制。而且在恒定的电压下,温度的变化也会引起电流的变化。
常见的 LED 调光方式主要是恒流源调光和脉宽调制( Pulse Width Modulation ,缩写为 PWM )调光。恒流源调光在这里就不细说了。在这里我们采用更易控制的 PWM 调光方式。
脉宽调制
从字面意思不难理解,就是通过改变一个周期内脉冲方波的宽窄度(占空比)的一种调制方式。PWM 作为一种广泛使用的技术,已成为 MCU 定时器的标配工作模式之一。较为常见的做法是设置定时器的周期为恒定值,当计数寄存器与比较寄存器的值相等的时候使IO口输出的电平反向,这是单极性的一种形式。既然 PWM 的原理如此,LED 灯岂不是会不断亮灭交替?亮的时间随然会变化,但是亮度却不会改变的呀,为何说会改变亮度?
图1 占空比为 T1/T 的脉冲
视觉暂留
视觉暂留是一种现象,当眼睛看到的物体消失后,影像仍会残留一段时间( 1/24 秒)。其形成机理是眼睛的感光细胞的感光是靠一些感光色素来作用的,而感光色素是不能突变的。正是由于视觉暂留,我们看到的不会是亮灭亮灭的过程,而是亮与灭在一段时间内混合作用的结果,也就是从完全灭到完全亮中间的某个亮度值。从微观上来讲,在 LED 点亮的一小段时间内,摄入眼睛的光子的量平均值是相等的。但在包括了 LED 熄灭状态的更长一段时间内的平均值则是不同的。而微观上的这些差异我们的眼睛却是识别不出来的。
多大的频率下我们才能觉察不到闪烁?应该说个体的差异还是会有的。有的人能看出某些设备面板上扫描方式工作的数码管的闪烁,有的人则看不出,这是一个例证。所以我们用 PWM 调光时,频率要足够的大,不然也会出现这样的问题。下表是一个不同颜色的 LED 在不同点亮占空比下不闪烁时的数据表:
从表中来看,同样颜色的情况下,占空比居中时,LED 需要更大的亮灭频率才能感觉到不闪烁。由于观测所用的三种颜色的 LED 的导通亮度是不同的,表中颜色差异所对应的闪烁感觉临界点的不同或许是一种错觉。由于不同颜色的感光细胞不同,也许会存在些许差异。
PWM 频率要留有一定的余量,选用 100 Hz 即可。
硬件电路
硬件上直接使用 STM32 开发板驱动 RGB LED(共阳极)。MCU 使用 TIM2 四个 PWM 通道中的三个与 LED 相连,低电平点亮。
软件
软件方面使用库函数来完成串口和定时器的驱动。
mcu_tim2_pwm_init(72000000 / 256 / 100, 255); //100Hz
mcu_tim2_pwm_set_value(1, 0);
mcu_tim2_pwm_set_value(2, 0);
mcu_tim2_pwm_set_value(3, 0);
while (1) {
r = rData();
g = rData();
b = rData();
mcu_tim2_pwm_set_value(1, r);
mcu_tim2_pwm_set_value(2, g);
mcu_tim2_pwm_set_value(3, b);
}
运行效果
最后实测效果达到了预期,下图为静态和动态运行情况的照片。
结束语
如果用时空的方式来看改变光子释放量的过程,恒流源控制方法在每个时间切片都可以看做是一致的,因为电流是恒定的,静态的。而 PWM 的方式仅用某时刻的切片是无法以偏概全的,因为他是动态的。这让我想到了时域与频域的转换分析,同一个目的,在时域和频域都可以去分析出结果,只不过是繁简的不同了。放在浩瀚的宇宙中,时空间是不是也可以有捷径呢?