前言
最近做一个光源,通过电位器控制PWM灯的亮度。
- 实现方法:通过ADC采集电压0 -- 4096,映射到占空比 0 -- 1000,去调节亮度。
遇到问题:
- ADC采集电位器电压 0--4096 他不是稳采集到的值会有波动,10以内,特别是在灯光暗的情况下会闪的很厉害,解决方法 限幅滤波,当值变化超过一定数值时才发生变化。
- 灯光变化不够线性,就是暗的地方调节感觉变化十分的明显,亮的地方调节变化就不够明显。
原因:
LED驱动是恒流的,而PWM调节的是恒流时间与断流时间的比值,所以占空比和光通量的输出应该是线性的。虽然,光通量是可以随时间线性变化,但是人眼对光的感受却不是线性的。一般表现形式为,在弱光情况下,很小的光通量能让人眼感觉光变化很大,在强光情况下,很大的光通量变化,人眼的感觉也不大。
解决方案:
要想实现人眼感光的线性变化,那么将实际光通量控制为非线性变化,即控制PWM非线性变化。
但是这个非线性变化如何如变化,这是个问题。
查阅资料
公式中,L是亮度(lightness),Y是流明(luminance)
这个公式可以直接写在单片机中,但是浪费资源。找到python代码可以生成表
INPUT_SIZE = 255//亮度等级
OUTPUT_SIZE = 255//PWM输入值
INT_TYPE = 'const unsigned char'
TABLE_NAME = 'cie';
def cie1931(L):
L = L * 100.0
if L <= 8:
return(L/902.3)
else:
return((L+16.0)/116.0)**3
x = range(0, int(INPUT_SIZE+1))
y = [round(cie1931(float(L) / INPUT_SIZE) * OUTPUT_SIZE) for L in x]
f = open('cie1931.h', 'w')
f.write('// CIE1931 correction table\n')
f.write('// Autiomatically generated\n\n')
f.write('%s %s[%d] = {\n' % (INT_TYPE, TABLE_NAME,INPUT_SIZE+1))
f.write('\t')
for i,L in enumerate(y):
f.write('%d, '% int(L))
if i % 10 == 9:
f.write('\n\t')
f.write('\n};\n\n')
运行可以生成,一个*.h文件,PWM控制用这个数组就差不多符合人眼线性了。