降采样后的AD值与原先AD值差别较大,如何解决

fengboning   2010-6-17 22:25 楼主
大家好,小弟最近在做一个关于ADC的滑动平均的算法,遇到问题,还请指教。

先说下正常情况,将ADC数据传送到终端的步骤如下:
ADC连续转换模式,每转换一个ADC数据,就触发一次中断。随后交给UART送到终端。

但后来发现,当ADC的转换频率为8KHZ时,ADC传给CPU的数据,UART来不急发送,因此导致数据会遗漏。

现在我们的应用,需要ADC转换速率仍然要高,还是8KHZ。
因此,想到了滑动平均算法,在送到UART之前,将8KHZ降采样到1KHZ,即将8K数据压缩到1K数据,rate=8,
即每转换8K的数据,传给UART的数据只有1K。

但是现在出现一个问题:
(1)当转换频率为8KHZ时,实际传给UART的数据是1KHZ,得出24bitAD的值  ;譬如 259876
然后我又测试了一下不用滑动平均算法时的,  1KHZ转换频率的AD值,  发现他们相差很大  134596
(两者在终端上显示的ADC数据数量很接近,只是AD值相差很多)

(2)但当转换频率降低后,譬如选取400HZ,实际UART频率是50HZ, 得出的AD值为   267589
不用滑动平均算法,转换频率50HZ,                        得出的AD值为   275906
(两者在终端上显示的ADC数据数量很接近)

我就有疑惑,为何当转换频率大时,采用算法和不采用算法,它们的AD值会相差那么大?  
两者在终端下AD值的数据量很接近,至少说明这个算法应该没什么大问题,难道还是因为我程序里计算AD值的算法有问题?

还请各位不吝赐教,小弟多谢

回复评论 (12)

现在通过一些对程序的修改。有两个问题请教:

(1)当我把降采样的算法放在main函数中时,AD转换频率为4KHZ时,会造成AD数据来不及发到终端。

而把降采样的算法放在ISR函数中时,却能够做到数据不遗漏。

         难道因为算法在main函数中,ISR程序中触发AD中断的速度过快,而导致来不及将AD的值传给UART?


(2)发现当AD转换频率为4KHZ时(因为RATE=8,即实际AD传输速度为500HZ时),能够将AD的24bit值传到终

端。但是AD的24bit值会随着时间的增加而缓慢减小。  时间一长,数据会和刚开始的数据相差很多

          请问这是不是算法里面还有问题?


(3)当设置AD转换频率为8KHZ时,只能发送3组数据到终端,然后就停止了。

     难道是频率太快,导致ISR中的阻塞?

还请各位不吝赐教,谢谢。

   

点赞  2010-6-20 14:23
会不会还是频率低了的原因啊
点赞  2010-6-20 16:35
引用: 引用 2 楼 cbyibby 的回复:
会不会还是频率低了的原因啊


4KHZ的话,能够传输,8KHZ的话只有一组数据就停止了。

应该是频率太高,才导致这样,频率低的话解释不通啊。。
点赞  2010-6-20 19:28
你的UART设置的波特率是多少?
点赞  2010-6-21 09:21
引用: 引用 4 楼 veabol 的回复:

你的UART设置的波特率是多少?


你好,我的波特率设置最高的,是256000
点赞  2010-6-23 19:32
始终没有提到你的"滑动平均的算法",如果是“滑窗”那么只要头8个(滑窗宽度)后数据率是不变的,即滑窗不会降低数据率
点赞  2010-6-23 19:44
引用: 引用 6 楼 schlafenhamster 的回复:
始终没有提到你的"滑动平均的算法",如果是“滑窗”那么只要头8个(滑窗宽度)后数据率是不变的,即滑窗不会降低数据率


窗口的宽度为24个,我用了3个窗。窗与窗之间的重合是16个系数。所以总的系数宽度为40个

每当完成24次Vi*F(窗的系数)后,就循环。
这样三个窗在一次循环后,得到三个SUM,也就是原本24个数据,现在只有3个数据。、
然后再将SUM除以窗的24个系数之和,就是得到的值。

原本输入24个值,最终输出3个值。这样RATE=8,达到了降采样的效果。
不知道我表达得是否清楚。还请指点,谢谢。
点赞  2010-6-24 10:40
你的算法不是"滑动平均的算法",只是"平均算法",滑窗的算法是“加进减出”,刚开始窗口内没东西不能输出数据,窗口宽度后,数据率就是输入数据率。
你的算法是把窗口填满后输出一个数据然后重来。
你的算法会使信号的带宽减小,不知道你的信号有多快?
点赞  2010-6-24 18:49
相差大小是一个问题,先要明确哪一种是接近实际值的才重要。
点赞  2010-6-24 21:21
引用: 引用 8 楼 schlafenhamster 的回复:

你的算法不是"滑动平均的算法",只是"平均算法",滑窗的算法是“加进减出”,刚开始窗口内没东西不能输出数据,窗口宽度后,数据率就是输入数据率。
你的算法是把窗口填满后输出一个数据然后重来。
你的算法会使信号的带宽减小,不知道你的信号有多快?


你好,可能我对自己的算法没有表达清楚。

我现在的算法中,一个窗的宽度有24个系数。并且一共有3个窗,每个窗之间相差8个系数
那么第一个窗就是b1={a1,a2......a24}  第二个窗就是b2={a9,a10...a32} 第三个窗就是b3={a17,a18...a40}
所以总的窗就是b={a1,a2...a40}

输入数据的序号用i表示,p表示24个系数中的第几个系数,则p=i%24
算法的大致程序如下

for(i=0; ; i++)
{

if(i%24==0)
    p=24;
else
    p=i%24;

sum0=sum0+Vin(i)*(b[0]+p)
sum1=sum1+Vin(i)*(b[8]+p)
sum2=sum2+Vin(i)*(b[16]+p)

if (p == 8)     
{Out =Sum2;                                                
Sum2 = 0;}

elseif (p ==16)
  {Out = Sum1;
  Sum1 = 0;}

elseif p == 24
  {Out =  Sum0
   Sum0 = 0;}

}

看这个算法,大致意思就是p对输入数据的序号i进行取模,p=i%24,即24是一个循环。每当p=8,16,24时,
都会得到一个sum,并且这个sum是24个Vin(i)*系数之和。     所以每当输入24个数据之后,都会得到三个SUM,最后把这三个SUM都除以24个系数之和,就得到了3个数据。

得出的结论就是每输入24个数据,就会得到3个数据,不知道这个算不算是“滑动平均”还是只是“平均”,谢谢。



点赞  2010-6-26 21:49
引用: 引用 9 楼 jennyvenus 的回复:

相差大小是一个问题,先要明确哪一种是接近实际值的才重要。


恩,谢谢大侠的提醒。我也觉得先要确定哪个才是真正的值。这样才能有目的地去发现问题所在。

后来一个同事告诉我。可以先用序号值,即输入值从1一直到某个数(例如5000)来代替AD转换值(这样比较容易看到结果),将这个数据流文件放到MATLAB中进行验证,后来得到5000/8个数据;并且每个数据都有具体的值。

后来我再在KEIL中,将自己写的C语言算法,融合这5000个数据,设置AD转换速率为2KHZ时,通过UART,确实能够得到和MATLAB中仿真时一样的值。每个值之间相差8,那就至少说明这个算法时正确的。

但是又碰到两个问题。

(1)当把AD转换频率设置为4KHZ时。数据显示到一半就会卡住,可能是几个,可能是几十个就会卡住。

(2)当AD转换频率设置为8KHZ时,显示的数据个数是5000/8个,但是值与值之间的差值只是4,从这点,我又担心是不是自己的算法程序还有问题。。。。

还请各位不吝赐教,多谢。
点赞  2010-6-26 21:59
现在当AD转换频率设置为2KHZ时,数据能够正常显示。

当AD设置为4KHZ时,有时正常显示,有时发送了一些数据后就没数据了。但是程序一直在运行,没有自动停止。

我不太清楚,是不是频率变快以后,程序中的算法有时就来不及处理了,还是其他什么原因。



点赞  2010-6-30 23:01
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复