【问题标题】:calculating moving average for long period计算长期移动平均线
【发布时间】:2012-12-21 20:58:19
【问题描述】:

我目前使用以下函数来计算每个 200ms 发生的温度读数的移动平均值。

uint16_t ntc_average(uint16_t adcdata)
{ 

    static uint8_t      first = 1;
    static uint16_t t1,t2,t3,t4,t5;

    if(first == 1)
    {
        first = 0;
        t1 = t2 = t3 = t4 = t5 = adcdata;
    }

    t5 = t4;
    t4 = t3;
    t3 = t2;
    t2 = t1;
    t1 = adcdata;
    adcdata = (t1+t2+t3+t4+t5)/5;

    return(adcdata);
}

但是,5 个点是不够的,我可能需要更长的缓冲区才能更平滑。例如,每 10-20 个读数一次或两次,该值可能会向上或向下下降一个点,我需要对其进行平滑处理。增加 tn 变量似乎很难看……我想我可能需要 t1-t50。

谁能建议C 中的另一个函数,我可以用它来平滑温度读数?请注意,这些值是无符号整数,而不是浮点数。

【问题讨论】:

  • 循环缓冲区怎么样?
  • 我正在寻找一些不使用太多缓冲区的算法。对于循环缓冲区,我需要使用内存。由于我正在研究具有微小内存的微型 MCU,因此减少内存使用会很棒。

标签: c average smoothing


【解决方案1】:

您无需进行算术平均即可进行平滑处理。例如,您无需丢弃从移动窗口中掉出的特定样本,而是可以在每次迭代时丢弃平均值本身。

newAverage = (oldAverage * (windowSize - 1) + newSample) / windowSize;

它可能对您的系统足够好,也可能不够好,但值得一试。

【讨论】:

  • 看起来可行。那么,如果我将 windowSize 设置为 5,为什么我没有得到与我的函数相同的波动?
  • 功能不太一样。你的是一个真正的平均值。这是一个指数衰减滤波器。两者都提供平滑处理,但您对每个样本的权重均等,而这个对最近的样本赋予更多权重。
【解决方案2】:

为此通常使用一个简单的过滤器:

ave = ave * (1-a) + samp * a;

其中a 是一个介于 0.0 和 1.0 之间的小常数


在s0.15定点:

int32 bigAverage; 
int16 ave;
int16 sample;
int16 alpha = 32768L*(0.1) //your constant here
int16 oneLessAlpha = 32768L-alpha;

//... in loop ...
bigAverage = (bigAverage>>15)*oneLessAlpha;
bigAverage += sample*alpha;
ave = bigAverage>>15;

为了保持更好的精度,你做的累加很长。

【讨论】:

  • 我看过这个,但不确定如何将其转换为整数数学,因为想避免浮点数学。
  • @Pablo,我认为这与我的答案相同。我的答案中的windowSize 就是这个答案中的1/a
  • @Carl Norum:对不起,让我试试
  • 我相信这段代码有错误。一个简单的方法是,如果您假设 bigAverage 的目的是包含额外的精度,那么在每次迭代中丢弃额外的精度 (bigAverage >>15) 是没有意义的。相反,在将样本添加到 bigAverage 时将样本向左移动(样本
猜你喜欢
  • 2014-11-18
  • 2021-05-30
  • 1970-01-01
  • 2014-12-24
  • 1970-01-01
相关资源
最近更新 更多