我一直想用一个简单的表达式把呼吸灯效果表达出来。搜索了一下,大家都是千篇一律。我看稍微有点想法的也是说用sin(x)函数实现,还有人说有matlab。我只是想说,对于一个2MHz的单片机,你们的要求太高了。
我只是追求用最简单,而且运算量不大的C代码实现。抛物线函数足够了,开口向下的,还要过原点(0,0),因为起始灯是熄灭的。
二元一次方程最适合。参数a,b,c的c=0,因为过了原点。又由于开口向下,a<0。这些是利用二元一次方程的特性可以看出来。
呼吸灯的亮度无非是控制占空比,通常是在timer控制器设置PWM输出方波信号占空比的分子和分母来实现不同的亮度。分母为最亮值,如果分子y为极限值分母,那么输出信号就为常高。所以是最亮。
说了点最基础的知识。再回到方程。方程有两个根x1,x2,一个是0,一个需要计算一下。
上面方框中的公式就是我们要写成代码的东东。可以看到我们只剩下一个参数需要调节,就是b,因为单片机一般是整数运算,所以我们的抛物线,并不是一个曲线,而是曲线上,一些不连续的点,这个参数b,就是用来调节这些不连续的点的美丽程度的。
在我的
STM8L开发板上,我利用内置的RTC定时触发亮度的变化,参考代码如下:
void RTC_callback()
{
static int16_t x=0;
#define b (int16_t) 3
uint16_t y;
y = (b*x)-((b*b*x*x)/(4*TIM2_PERIOD));
x++;
x=x%((4*TIM2_PERIOD)/b);
TIM2_SetCompare1(y);
}
另外可以看出b越大,你的X的取值范围就越小。这样你的不连续点就太少,导致LED亮度变化可能不那么平滑。