5

我最近一直在玩 LED,由 8 位微控制器驱动。有时有必要使用脉冲宽度调制的纯软件实现来控制 LED 亮度 - 即快速打开和关闭灯,改变时间的比率。这很有效,直到我降低到大约 5% 的亮度,此时频闪开始看起来令人不舒服的闪烁。

将 PWM 实现为一个循环,它逐步遍历从 0 到 255 的每个数字,设置该时刻的灯打开或关闭。设置为 20 值的灯将在前 20 个循环中打开,然后关闭。

我正在寻找一个很好的函数,它将围绕这些数字进行洗牌,所以不是循环通过 0、1、2、3... 我的循环可以从可能性池中半随机地采样。随着时间的推移,总亮度是相同的,但是亮度值为 20 的灯可能会在 256 个循环中打开和关闭十几次,而不是仅点亮一次然后在大部分循环中关闭。即使循环运行速度稍慢,这也会减少闪烁效果。

当使用每个 8 位数字调用时,一个好的抖动函数需要返回 8 位范围内的每个数字。因此,它也不需要产生重复的数字——不是随机的,只是随机的。最好不要将相似的数字按顺序排列在一起——每个数字之间的差异应该很大——我认为理想情况下约为 64-127。

这些限制也很有趣——它是一个时间紧迫的应用程序。加法、减法和按位运算需要 1 个任意时间单位,乘法需要 2 个单位,除法需要 4 个单位。浮点数是不可能的,中间数字中使用的每 8 位的倍数的成本大约翻倍。查找表是可能的,但会使用设备总内存容量的大约一半 - 因此快速算法最适合可重用性,但当有空间进行预计算时,高质量的慢速算法也非常有用。

感谢您帮助我提出任何想法或沉思。:)

4

2 回答 2

5

不是 100% 确定我理解正确,但基本上我认为任何不除以 256 的数字都会生成数字组 0..255,如果你只是继续将它添加到自身以 256 为模 。抽象代数类的一些闪回。 ..

像这样:

s = {}

n = 157
for i in range(0, 256):
   s[n] = True
   print n
   n += 157
   n %= 256

print "check: has to be 256: ", len(s) 

编辑:用更大的发电机替换小型发电机,使分布更加“随机”。

于 2012-04-06T03:26:58.440 回答
5

示例:在 8 位寄存器中使用相位累加器进行 5 位抖动,其中占空比 = 1 到 31 [% = 占空比 / (1 << 位)]。

// Easier to do in assembly, where there is access to the carry flag
unsigned bits = 5;  // states = 1 << bits
unsigned carry = 7; // keep carry bit within an 8 bit register, limits bits
unsigned frq = ((1 << carry) * duty) / (1 << bits); // More than 8 bit intermediate value
unsigned phs = 0;
for (i = 0; i < (1 << bits); i++) {
    phs += frq;  // Carry is high bit
    output((phs >> carry) & 1);  // Output carry
    phs &= (1 << carry) - 1;  // Discard carry
}

抖动模式如下所示:

00: 00000000000000000000000000000000
01: 00000000000000000000000000000001
02: 00000000000000010000000000000001
03: 00000000001000000000010000000001
04: 00000001000000010000000100000001
05: 00000010000010000001000001000001
06: 00000100001000010000010000100001
07: 00001000010001000010001000010001
08: 00010001000100010001000100010001
09: 00010001001000100100010010001001
10: 00010010010010010001001001001001
11: 00100100100100100100100100100101
12: 00100101001001010010010100100101
13: 00101001010010100101001010010101
14: 00101010010101010010101001010101
15: 00101010101010100101010101010101
16: 01010101010101010101010101010101
17: 01010101010101011010101010101011
18: 01010101101010110101010110101011
19: 01010110101101011010110101101011
20: 01011011010110110101101101011011
21: 01011011011011011011011011011011
22: 01101101101101110110110110110111
23: 01101110110111011011101101110111
24: 01110111011101110111011101110111
25: 01110111101110111101110111101111
26: 01111011110111110111101111011111
27: 01111101111101111110111110111111
28: 01111111011111110111111101111111
29: 01111111110111111111101111111111
30: 01111111111111110111111111111111
31: 01111111111111111111111111111111

如果您没有足够宽的整数(或者在没有乘法或除法的情况下在汇编程序中),则可能需要一次一位地在循环中计算 frq 。

可选地,可以预先计算抖动模式并将其编码为查找表中的常数。

只有 2 的幂的模式没有噪音;除非您进行音频或射频合成,否则这无关紧要。否则其他模式有小鸟。在输出一次模式后打乱模式位的顺序会增加噪音,但会消除小鸟。可以使用具有长重复周期且不添加或删除位(1 和 0 的数量保持不变,只是它们的顺序发生变化)的 LFSR 函数来执行此操作。

请注意,要以 60 Hz 帧速率输出完整模式,需要 60 Hz * (1 << bits) = 1.92 kHz 的抖动频率。可能可以在没有闪烁的情况下为 LED 提供低得多的抖动频率,例如 (1 << bits) = 32 Hz。实验!

于 2016-03-08T05:09:06.927 回答