AD数据采集方案的心得分享

2019-12-19 18:10发布

本帖最后由 leicai05 于 2014-5-30 13:41 编辑

最近处理14位ad采集并显示的项目,在数据处理过程中的一点感悟给大家分享,给新手一点借鉴吧。
需求很简答,采集3路ad值并在12864液晶上显示即可。

1.       刚开始测试的时候,写完ad的驱动get_ad(ch),就拿来显示了,ok了。
2.       为了防止数据偶尔的波动,多采集N次,做个平均值吧
//求平均值
u16 get_average(u16* buf, u16 len)
{
u16 i;
u16 sum = 0;
for(i=0; i< len; i++)
{
        sum += buf;
}     
return (u16)(sum/len);
}这样处理后,效果好点,但是还是有波动。
3.       在想想办法把,每次采集20个数据,然后从小到大排序,丢弃最大的和最小的4个数据,然后对中间的12个数据求平均。
//排序
void rank_array(u16 *data, u8 len)
{
u8 i,j;
u16 temp;
for(i=0; i<len-1; i++)
{
        for(j=i+1; j<len; j++)
        {
               if(*(data+i) > *(data+j))
               {
                      temp = *(data+i);
                      *(data+i) = *(data+i);
                      *(data+j) = temp;                              
               }
        }     
}
}
这样处理完后,自己感觉还可以,装上机器后调试,发现采集ad值还是有变化,而且变化很灵敏,老板说这样变化太快,客户会觉得我们这个机器不稳定的…
4.   这怎么搞,没办法做一个平滑处理吧,给每路ad分配一个buf[N]空间,保存最近采集的N次数据,每次保存的ad值保存到buf[SP]中,SP在0~N-1之间变化,输出的有效值为buf中所有数据的平均值。N值取得越大,平滑的效果越明显,
u16 filter(u16 data)
{
       static u16 data_buf[N] = {0};       //保存N次采集的ad值
       static u8  data_sp = 0; //需要替换数据的下标
       static u8  data_len = 1; //记录当前数数的长度  

       u32 sum = 0;//求和
       u16 avr;//求平均
       u8 i;

       data_buf[data_sp] = data;//替换旧的值

       for(i=0; i<data_len; i++)
       {
              sum += data_buf;
       }
       avr = (u16)(sum/data_len);//递推平均值
      
       return avr;
}
这样处理后,效果很明显了,比较平滑了,可是老板测试的时候又说啦,这个效果还可以,但是启动和关闭的时候,变化太慢了,这个效果可以不行啊。。。
4.       做了平滑处理,能不慢吗?不过老板的需要总是有道理的,就在想啊,怎么样解决这个问题了。。。啊,有了,变化慢的时候平滑处理就行了,单变化快,急促的时候,就让输出及时更新就行了!怎么处理了?     
给每个ad设置一个变化差值,ADdet,当变化超过了这个ADdet值的时候,就把buf[N]中的数据给清空了,只保存这次采集到的AD值到buf中,重新开始做平滑处理。
//输出两个数据的差值
u16 absolute(u16 a, u16 b)
{
if(a > b) return a-b;
else return b-a;
}
//数据平滑处理
u16 filter(u16 data)
{
static u16 data_buf[N] = {0};       //保存N次采集的ad值
static u8  data_sp = 0; //需要替换数据的下标
static u8  data_len = 1; //记录当前数数的长度
static u16 old_avr = 0;//保存上次的平均值

u32 sum = 0;//求和
u16 avr;//求平均
u8 i;

if( absolute(old_avr, data) > ADdet)//这个数据是个异常
{
        data_len = 1;
        data_sp = 0;        
}

data_buf[data_sp] = data;//替换旧的值

for(i=0; i<data_len; i++)
{
        sum += data_buf;
}
avr = (u16)(sum/data_len);//递推平均值
old_avr = avr;

return avr;
}
修改后测试效果还是不错的,终于可以歇歇了。。。。
       但是后来又有其他的数据需要处理了,老板说,这个突变,你还不能马上更新,数据上       有个情况会导致数据突然变为0,而且是没规律的,这个突变还不能马上显示。。。。

       接着改问题吧。。。不过这个问题是工程中的特殊情况,解决方案就不写出来了。。。
       在改方案的过程中参考了网上的一些数据滤波的方法
http://blog.csdn.net/haozi_1989/article/details/6625404
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
35条回答
MetalSeed
1楼-- · 2019-12-22 16:20
滤波思路不错
MetalSeed
2楼-- · 2019-12-22 17:12
滤波思路不错
am391144374
3楼-- · 2019-12-22 21:37
 精彩回答 2  元偷偷看……
sensitiveplant
4楼-- · 2019-12-23 02:43
老板还说什么了?
sensitiveplant
5楼-- · 2019-12-23 08:28
老板还说什么了?
gujiamao_love
6楼-- · 2019-12-23 11:21
多谢分享。。

一周热门 更多>