通过PWM调节占空比让灯的亮度更加线性

Posted on 2024-05-31 11:49  shydragon  阅读(406)  评论(0编辑  收藏  举报

前言

最近做一个光源,通过电位器控制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控制用这个数组就差不多符合人眼线性了。