历史上的今天
今天是:2025年04月01日(星期二)
2020年04月01日 | 单片机ADC采样算法----递推平均值采样法
2020-04-01 来源:eefocus
在上一篇文章单片机ADC采样算法---平均值采样法中分析了平均值采样法的使用,上篇文章中的平均值采样法是连续采样100个数据,然后求平均值,这种方法存在一个问题,就是采集100个值之后,下一次又重新采集100个新的值,这两次采集的值是不连续的,相当于每次都是独立的采集来100个值,然后求平均值。这样计算出来的值有可能看不出来数据的变化趋势。希望在求平均值的时候每次读取到一个新的值,就将最早读取的旧值丢弃一个,相当于水管中的流水一样,有新的水流进来,就让最早进来的水流出去。这样采集到的数据就是连续变化的。这样通过采样值就能看出来采样数据是否发生了波动。
算法如下:
#define N 100
unsigned int filter4( void )
{
static unsigned int value_buf[N];
static unsigned int i = 0;
unsigned int count;
int sum = 0;
value_buf[i++] = ReadVol_CH3();
if( i == N )
{
i = 0;
}
for( count = 0; count < N; count++ )
{
sum += value_buf[count];
}
return ( unsigned int )( sum / N );
}
通过数组将采样的数据存储起来,若数组存满之后,数组下标直接跳转到数组头,覆盖最早采样的数据。然后再计算平均值 。但是用数组存储的话会浪费单片机大量的存储空间,如果采样的数据比较多,单片机的空间有可能不够用。所以为了节省单片机的空间,这里不用数组存储,而是用另一种方法来实现 。
改进后的算法如下:
#define CNT 100
u16 get_ave( void )
{
static u8 count = 0;
static u32 S = 0; //累加和
static u16 C = 0; //本次采样值
static u16 A = 0; //平均值
C = ReadVol_CH3();
if( count == 0 )
{
A = C;
S = A * CNT;
count = 1;
}
S = S - A + C; //加上本次采样值,减去上次平均值
A = S / N; //计算本次平均值
return A;
}
不用数组存储的话就不知道最早采样的值是多少,这里用上次采样的平均值代替最早的采样值。A代表上次采样的平均值,C代表本次采样的值,S代表100次数据的累加和,每次采样到新数据时,就用累加和减去上一次的平均值,然后再加上本次采样的值,计算出本次采样新的平均值。
这样S就相当于连续100个数据的累加和,每次有新的数据进来之后,先减去旧的数据,再加上新的数据。这样计算出来的平均值就是连续的。下来测试一下优化算法。

这是函数发生器产的一个100HZ的正弦波,最小值是0V,最大值是4V,平均值是2.02V。单片机通过串口将采样回来的平均值发送出来,用串口波形显示软件,将采样值的波形显示出来。

通过串口波形软件可以看出,采样回来的值是波动的,说明优化后的采样算法更能实时的反应出来采样波形的波动情况。
在波形显示软件右下角可以看到,采样回来的值最小是419,最大是427,单片机ADC是10位分辨率 2^10=1024,所以采样的平均电压为 419/1024*5=2.0458984375V 427/1024*5=2.0849609375V 采样的平均值在2.04和2.08V之间波动。和示波器测出来的平均值2.02V有一点误差,误差最大值为0.06V左右,上一篇平均值采样法的最大误差为0.02V。
改进后的平均值采样算法和上一篇单片机ADC采样算法---平均值采样法采样的值相比,误差增大了,但是相对于平均值采样法来看,采样的值能更快速的反应出采样数据的变化情况。
史海拾趣
|
本帖最后由 jameswangsynnex 于 2015-3-3 19:58 编辑 由于中国政府自6月起无预警地再度针对山寨机业者展开查税动作,让整个山寨机产业链顿时失去动能,订单全面熄火,连带造成联发科6月接单量大幅衰退,相较于4月时手机芯片客户抢不到货、抱怨声连 ...… 查看全部问答> |
|
我找了几个ce5.0下的coredll.dll发现里面都没有导出lineXXX函数 ppc或者wm下有吧 指令集是armv4i 如果各位谁有麻烦给我一份 谁有这个平台下的串口源码… 查看全部问答> |
|
各位好,大家用过R8C系列的单片机么? 小弟有几个问题想请教下: 在下使用R8C系列单片机,做串口通信,现一个问题困饶我好久了: 在程序中定义的全局变量,我只有一个地方修改他的值,但是他的值总是莫名其妙的改变,我在程序中确认只有一处修改啊! 大 ...… 查看全部问答> |
|
要求: 1、类似于qq连连看,是单击版的,有个朋友想找我做,问下大家,要是做的话预算多少rmb,还有需要多久 一个开发+一个美工。(上次发帖的写的) 2、加入3d元素,就是玩的过程中,背景图会呈现出宝石发出的动态的光线,动态的云彩,消掉后会 ...… 查看全部问答> |
|
在组件里添加组件“Include_VX_TRADITIONAL_SCHEDULER\"后,内核采用的内核调度策略为传统的调度策略。 在kernel program guide里有如下描述: The vxworks traditional scheduler provide priority_based preemptive scheduling as well as the ...… 查看全部问答> |
|
操作系统为Wince, 编程语言EVC. 为Edit 控件关联了int型的变量,并设定了其有效范围是 1 到 5000,在输入的数值在此范围之外时,系统自动弹出了错误提示对话框。但为什么提示信息都是乱码呀? 我自己用messagebox显示的对话框可以正常显示中文呀!… 查看全部问答> |




