1. 最原始的算法:
u16 moving_average(u16 in)
{
static u16 d[16] = {0,0};
u32 sum = 0;
for(u8 i = 15; i > 0; i--)
{
d[i] = d[i-1];
sum += d[i];
}
d[0] = in;
sum += d[0];
return sum >> 4; // 1/16
}
2. 优化的: 使用当前需要替换的元素index来更换新的数据, 避免耗时的逐次移动
#define MG_LEN 64
typedef struct
{
u16 d[MG_LEN];
u8 seq;
}MAG;
MAG mag;
void mov_avg_rst(void)
{
u8 i;
mag.seq = 0;
for(i = 0; i < MG_LEN; i++)
mag.d[i] = 0;
}
u16 move_avg64(u16 in)
{
u8 i;
u32 sum;
mag.d[mag.seq] = in; //new data in
sum = 0;
for(i = 0; i < MG_LEN; i++)
sum += mag.d[i];
mag.seq++;
if(mag.seq >= MG_LEN)
{
mag.seq = 0;
}
return (u16)(sum >> 6); //div 64
}
3. 不需要数组来存放历史数据, 用一个总和sum来存储. 很次用时先减去sum/64, 然后加入新的数据到sum, 返回新的sum/64
u16 moveAverage(u16 in)
{
static u32 sum = 0;
sum = sum + in - (sum >> 6);
return sum >> 6; // 1/64
}
4. 趋势判断法, 适合趋势明显的曲线变化, 比如充电的电流是稳定下降的, 先获取到13个连续的数值, 得到平均值和平均变化趋势值(两点间差值), 然后推算出接下一点会是什么数值, 达到过滤出不符合趋势变化的噪声的目的
#define TREAND_LEN 12 //must be an even number
u16 trend(u16 new)
{
static u16 d[TREAND_LEN] = {0,0};
s32 sum = 0;
s32 delta = 0;
for(u8 i = (TREAND_LEN-1); i > 0; i--)
{
sum += d[i];
delta += (d[i] - d[i-1]);
d[i] = d[i-1];
}
sum += (d[0] + new);
sum /= (TREAND_LEN+1);
delta += (d[0] - new);
d[0] = new;
delta = ((TREAND_LEN+2)/2 * delta) / TREAND_LEN;
// delta = (7 * delta) / 12;
if(sum > delta)
return sum - delta;
else
return 0;
}
1465

被折叠的 条评论
为什么被折叠?



