找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1505|回复: 16
收起左侧

ADC滤波之滑动平均算法问题

[复制链接]
ID:322939 发表于 2021-12-3 17:06 | 显示全部楼层 |阅读模式
AD采集温度使用滑动平均算法滤波发现当加热时显示温度的数字变化不大与之实际温度相差很大,当实际温度在1百多度后,显示才几十度然后变化在1度左右变化就不动了。如果使用中位值平均法就没问题,请各位大佬帮看看是那里的问题。多谢先!
#define N 12

unigned int  value_buf[N];
unigned char i = 0;
unigned int  temp=0;
unigned int filter(void)
{
   unigned char count = 0;
   unigned int sum = 0;

    value_buf[i++] = get_ad();
    if(i == N) {
        i = 0;    //先进先出
    }
    for(count = 0; count < N; count++)
{
        sum += value_buf[count];
    }
    return (sum / N);
}
void display(void)
{
  temp=filter();//给数码 管分位显示
............
...........
}
回复

使用道具 举报

ID:313048 发表于 2021-12-3 18:07 | 显示全部楼层
看一下是否因为sum += value_buf[count];这个数据越界了的原因。你可以把sum定义为long int试试
回复

使用道具 举报

ID:624769 发表于 2021-12-3 19:18 | 显示全部楼层
你的 i 是全局变量,你确定没有其他地方(其他函数,其他for循环)用到 i 么?
回复

使用道具 举报

ID:401564 发表于 2021-12-3 20:50 | 显示全部楼层
NTC温度变化的速度并不快的,用不着什么复杂算法
1秒/4次,累加再平均,基本是没有问题的
非得要所谓的精度,那就用ADC中断方式,66次ADC结果相加,减去最大和最小,除以64
什么数组都不需要
回复

使用道具 举报

ID:322939 发表于 2021-12-4 08:59 | 显示全部楼层
AUG 发表于 2021-12-3 18:07
看一下是否因为sum += value_buf[count];这个数据越界了的原因。你可以把sum定义为long int试试

我试过将sum改int型也不行,只是显示数值比原来高一点
回复

使用道具 举报

ID:322939 发表于 2021-12-4 09:01 | 显示全部楼层
188610329 发表于 2021-12-3 19:18
你的 i 是全局变量,你确定没有其他地方(其他函数,其他for循环)用到 i 么?

在原程序 i我是放在局部变量,其它地方没用到的。
回复

使用道具 举报

ID:322939 发表于 2021-12-4 09:06 | 显示全部楼层
Y_G_G 发表于 2021-12-3 20:50
NTC温度变化的速度并不快的,用不着什么复杂算法
1秒/4次,累加再平均,基本是没有问题的
非得要所谓的精度, ...

我是用热电偶检测的,因为要检测500度的高温,NTC做不到的,热电偶它的信号反应很快,波动较大,只能用算法做了
回复

使用道具 举报

ID:322939 发表于 2021-12-4 09:07 | 显示全部楼层
搞到我怀疑这算法例程到底靠不靠谱了?
回复

使用道具 举报

ID:136119 发表于 2021-12-4 10:37 | 显示全部楼层
你看这个你能用不  建立数据队列 先进先出  每次进入一个数据 建立一个平均值
        #define ADDE_DataFlow  8        //建立数据流最大16

        typedef struct
        {
                u8 Sign;                      // 数据队列位置标号
                u16 DataFlow[ADDE_DataFlow];  //记录相关数据  
                u16 DataADC;                  //数据有效值
        } SAD_DataFlow ;
///////////////数据计数平均值///////////////
void DataFlowRecord(SAD_DataFlow* target ,u16 data)//记录数据
{
        u16 temp_val=0;
        u8 t ;       
        target -> DataFlow [target->Sign] = data;
        target -> Sign++;       
        if(target -> Sign >= ADDE_DataFlow)
        {target->Sign = 0;}               
        for(t=0;t<ADDE_DataFlow;t++)
        {temp_val += target->DataFlow[t];}
  target->DataADC = temp_val/ADDE_DataFlow;
}
回复

使用道具 举报

ID:139866 发表于 2021-12-4 11:36 | 显示全部楼层
最近在研究卡尔曼滤波器,建议楼主可以试试,效果还不错
回复

使用道具 举报

ID:322939 发表于 2021-12-4 11:45 | 显示全部楼层
yuyechenai 发表于 2021-12-4 10:37
你看这个你能用不  建立数据队列 先进先出  每次进入一个数据 建立一个平均值
        #define ADDE_DataFlow  8 ...

这位大佬这个(target->...)是什么意思啊?你用的是STM32的吧?
回复

使用道具 举报

ID:322939 发表于 2021-12-4 11:50 | 显示全部楼层
天ノ忆 发表于 2021-12-4 11:36
最近在研究卡尔曼滤波器,建议楼主可以试试,效果还不错

这算法也太复杂了,有时间再研究吧,多谢
回复

使用道具 举报

ID:624769 发表于 2021-12-4 12:00 来自手机 | 显示全部楼层
LAW1100 发表于 2021-12-4 09:01
在原程序 i我是放在局部变量,其它地方没用到的。

你源程序里放在局部的话,声明的时候不能在后面写=0。
回复

使用道具 举报

ID:136119 发表于 2021-12-4 12:04 | 显示全部楼层
看起来指针不是熟悉 ,这就是一个调用过程
SAD_DataFlow  AD_DataFlow;  //声明数据
unsigned int  M;                    /////////声明
DataFlowRecord(&AD_DataFlow ,ADC_DATA);  //ADC_DATA 这个是AD获取到的值
M=AD_DataFlow.DataADC      //获取你想要的值  首次经过 ADDE_DataFlow 轮调用数据就会稳定

回复

使用道具 举报

ID:160500 发表于 2021-12-4 12:33 | 显示全部楼层
看这一点程序看不出什么问题。你这种局部变量又想保持其值的建议使用静态变量,不容易出现其它地方误用的情况
回复

使用道具 举报

ID:401564 发表于 2021-12-4 12:41 | 显示全部楼层
LAW1100 发表于 2021-12-4 09:06
我是用热电偶检测的,因为要检测500度的高温,NTC做不到的,热电偶它的信号反应很快,波动较大,只能用算 ...

热电偶和NTC一样的了,它都是检测温度的
温度变化都是没有那么快的
难不成加热器件是从0摄氏度1uS就加热到了100摄氏度?
做温度检测控制,你至少有个温度计吧,你可以用温度计看一下,温度变化真的不大的
烙铁的PID控制都是秒级别的
所以,没有必要什么复杂算法,累加再平均就行了
如果是非得要什么复杂算法,那至少,你得先累加平均,验证主程序,所有的程序都对了之后,再去实现算法
回复

使用道具 举报

ID:322939 发表于 2021-12-5 17:02 | 显示全部楼层
多谢各位,我研究下,实在不行就用中位值滤波。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表