搜索
bottom↓
回复: 35

多次采样求平均

[复制链接]

出0入0汤圆

发表于 2014-8-23 09:05:11 | 显示全部楼层 |阅读模式
使用51内核的SOC单片机V9401,使用库函数读取电流有效值,送显示,有1%的跳差,想多次采样求平均,提高稳定度,现做想1秒读取一次,读3次然后做个平均,但是程序有点问题,显示不正常了,原来读取直接送显示,正常的while(1)
        {               
                CLRWDT();       
                ReadMeterPara(0x10d9); //秒平均电流有效值
                temp1=u32PMdatal;
                                                if(time_1s)
                                                {
                                                         time_1s=0;
                                                         ReadMeterPara(0x10d9);         
                                                         value_buf[0] = u32PMdatal;
                                                         if(time_2s)
                                                         {
                                                                 time_2s=0;
                                                                ReadMeterPara(0x10d9);
                                                                value_buf[1] = u32PMdatal;
                                                                if(time_3s)
                                                                {
                                                                        time_3s=0;
                                                                        ReadMeterPara(0x10d9);
                                                                        value_buf[2] = u32PMdatal;
                                                                        temp1=(value_buf[0]+value_buf[1]+value_buf[2])/3;
                                                                }
                                                         }
                                                 }       
                        dislay_jisuan();
                if(Time_FLAG)
                {
                        Time_FLAG=0;                       
                    display();                                                                       
             }
        }                       
}


void Interrupt_Timer0 (void) interrupt 1 using 2
{

    TF0=0;
        Time_FLAG=1;
        TL0 =0x33;      //1ms
    TH0 =0xF3;
                coun++;
        if(coun==150)
        {
                coun=0;
                time_1s=1;
                if(coun==150)
                {
                        coun=0;
                        time_2s=1;
                        if(coun==150)
                        {
                                coun=0;
                                time_3s=1;
                        }
                }
        }
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2014-8-23 09:20:28 | 显示全部楼层
你是一个小兵。你这time_1s 2s 3s逻辑很是有问题。没你这样用有,如果time_1s是一秒,那么你数据temp1就是150*150秒更新一次。

出0入0汤圆

 楼主| 发表于 2014-8-23 09:23:46 | 显示全部楼层
那应该如何操作呢,我想1秒读取一次秒平均

出0入0汤圆

发表于 2014-8-23 09:24:23 | 显示全部楼层
这个没2s 3s的事

出0入0汤圆

 楼主| 发表于 2014-8-23 09:26:21 | 显示全部楼层

间隔1秒读取一次的

出0入0汤圆

 楼主| 发表于 2014-8-23 09:26:38 | 显示全部楼层
tam2907 发表于 2014-8-23 09:20
你是一个小兵。你这time_1s 2s 3s逻辑很是有问题。没你这样用有,如果time_1s是一秒,那么你数据temp1就是1 ...

那应该如何操作呢,我想间隔1秒读取一次秒平均

出0入0汤圆

发表于 2014-8-23 09:34:01 | 显示全部楼层
  if(coun==150)
         {
                 coun=0;   //0
                 time_1s=1;
                 if(coun==150)  //前面已经等于0了。这里不可能等于150。下面也是一样
                 {
                         coun=0;                                   
                         time_2s=1;
                         if(coun==150)   
                       {
                                 coun=0;
                                 time_3s=1;
                         }
                 }
         }

出0入0汤圆

发表于 2014-8-23 09:35:36 | 显示全部楼层
加个变量 cnt
中断里 time_1s =1

主程序
if(time_1s)
  {
  time_1s=0;   ReadMeterPara(0x10d9);     value_buf[cnt] = u32PMdatal;  if(cnt>=2){cnt=0;  temp1=(value_buf[0]+value_buf[1]+value_buf[2])/3; }
}

出0入0汤圆

发表于 2014-8-23 09:36:07 | 显示全部楼层
time_2s、time_3s那些都不要

if(time_1s)
{
time_1s=0;
ReadMeterPara(0x10d9);         
value_buf[2]=value_buf[1];//FIFO
value_buf[1]=value_buf[0];
value_buf[0] = u32PMdatal;
temp1=(value_buf[0]+value_buf[1]+value_buf[2])/3;

出0入0汤圆

发表于 2014-8-23 09:38:27 | 显示全部楼层
中断里面的time_1s =1 ,后面的代码是不是永远不会执行,应该把coun=0去掉,然后300,然后450,这样

出0入0汤圆

 楼主| 发表于 2014-8-23 09:44:28 | 显示全部楼层
好的啊,学习了呢,我修改下试试

出0入0汤圆

 楼主| 发表于 2014-8-23 09:50:41 | 显示全部楼层
lcw_swust 发表于 2014-8-23 09:36
time_2s、time_3s那些都不要

if(time_1s)

学习了呢,我再修改下

出0入0汤圆

 楼主| 发表于 2014-8-23 09:52:29 | 显示全部楼层
lcw_swust 发表于 2014-8-23 09:36
time_2s、time_3s那些都不要

if(time_1s)

因为秒平均,单片机是1秒更新一次,这样是不是相当于3秒才更新一次显示呢

出0入0汤圆

 楼主| 发表于 2014-8-23 09:58:18 | 显示全部楼层
还有一个问题,这样相当于3秒更新一次显示,  一开始上电也要读一次秒平均有效值ReadMeterPara(0x10d9);直接送显示,

出0入0汤圆

 楼主| 发表于 2014-8-23 10:01:58 | 显示全部楼层
  一开始上电也要读一次秒平均有效值ReadMeterPara(0x10d9);直接送显示,,,,,应该将第一次显示ReadMeterPara(0x10d9); //秒平均电流有效值               temp1=u32PMdatal;,               放在WHILE()  {}循环的   之前吗,WHILE()循环放了读3次求平均,还有显示刷新这些      

出0入0汤圆

 楼主| 发表于 2014-8-23 10:11:25 | 显示全部楼层
czg1411 发表于 2014-8-23 09:34
if(coun==150)
         {
                 coun=0;   //0

一开始也要直接读取平均送显示一次,应该放在MAIN主函数里,还是应该放在WHILE循环里的呢

出0入0汤圆

发表于 2014-8-23 10:46:52 | 显示全部楼层
放MAIN主函数WHILE循环前。代码更简单。
和3次平均和放一起模块化做的更好。


出0入0汤圆

 楼主| 发表于 2014-8-23 10:53:20 | 显示全部楼层
czg1411 发表于 2014-8-23 10:46
放MAIN主函数WHILE循环前。代码更简单。
和3次平均和放一起模块化做的更好。

好的啊,要是和3次平均和放一起,放在WHILE循环里,应该如何处理好呢,关键是就第一次上电显示一次,后面就用采样3次求平均的办法了呢

出0入0汤圆

 楼主| 发表于 2014-8-23 10:55:33 | 显示全部楼层
lcw_swust 发表于 2014-8-23 09:36
time_2s、time_3s那些都不要

if(time_1s)

一开始上电也要直接读取采样值送显示一次,应该放在MAIN主函数里,还是应该放在WHILE循环里的呢,要是放在WHILE循环里,应该如何做呢,

出0入0汤圆

发表于 2014-8-23 10:55:42 | 显示全部楼层
//time_1s 初值等于1  
if(time_1s)
{
        time_1s=0;   
        ReadMeterPara(0x10d9);     
        if(cnt==0)   //第一次
        {
                temp1=u32PMdatal;
                cnt=1;               
        }
        value_buf[cnt-1]=u32PMdatal;  
        if(cnt>=3)   //三次平均
        {
                temp1=(value_buf[0]+value_buf[1]+value_buf[2])/3;
                cnt=1;
        }
        else
        {
                cnt++;
        }
}

出0入0汤圆

 楼主| 发表于 2014-8-23 10:56:00 | 显示全部楼层
tam2907 发表于 2014-8-23 09:35
加个变量 cnt
中断里 time_1s =1

一开始上电也要直接读取采样值送显示一次,应该放在MAIN主函数里,还是应该放在WHILE循环里的呢,要是放在WHILE循环里,应该如何做呢,

出0入0汤圆

发表于 2014-8-23 10:58:16 | 显示全部楼层
小白
51这种低端的,最好做优化,像3次这种不科学。最好是2的N次,如 2,4,8,16............

出0入0汤圆

 楼主| 发表于 2014-8-23 10:58:30 | 显示全部楼层
czg1411 发表于 2014-8-23 10:55
//time_1s 初值等于1  
if(time_1s)
{

好的啊,向您学习下,我C语言基础太差了,回去恶补下,多写写子程序

出0入0汤圆

 楼主| 发表于 2014-8-23 11:00:55 | 显示全部楼层
babysnail 发表于 2014-8-23 10:58
小白
51这种低端的,最好做优化,像3次这种不科学。最好是2的N次,如 2,4,8,16............ ...

关键是3次的话,已经是3秒更新一次了,2N次,会不会,显示更新上延迟太久了呢

出0入0汤圆

 楼主| 发表于 2014-8-23 11:01:48 | 显示全部楼层
babysnail 发表于 2014-8-23 10:58
小白
51这种低端的,最好做优化,像3次这种不科学。最好是2的N次,如 2,4,8,16............ ...

那我改成4次吧

出0入0汤圆

发表于 2014-8-23 11:08:11 | 显示全部楼层
三国小兵 发表于 2014-8-23 11:00
关键是3次的话,已经是3秒更新一次了,2N次,会不会,显示更新上延迟太久了呢 ...

举个特殊的例子吧, /256 ,就是把低字节直接去了,根本不用运算

出0入0汤圆

发表于 2014-8-23 11:11:46 | 显示全部楼层
三国小兵 发表于 2014-8-23 10:11
一开始也要直接读取平均送显示一次,应该放在MAIN主函数里,还是应该放在WHILE循环里的呢 ...

自己多想想,多试试。
上电时,可以把第一次读的数复制到整个数组的每个元素,这样取平均值就没影响了。

出0入0汤圆

 楼主| 发表于 2014-8-23 11:13:15 | 显示全部楼层
lcw_swust 发表于 2014-8-23 11:11
自己多想想,多试试。
上电时,可以把第一次读的数复制到整个数组的每个元素,这样取平均值就没影响了。 ...

好的,自己再琢磨下

出0入0汤圆

 楼主| 发表于 2014-8-23 11:13:51 | 显示全部楼层
babysnail 发表于 2014-8-23 11:08
举个特殊的例子吧, /256 ,就是把低字节直接去了,根本不用运算

好的啊

出0入0汤圆

发表于 2014-8-23 11:18:25 | 显示全部楼层
没仔细看程序。  不知道你的变量定义是多少位的?  是否累加的时候溢出了?

出0入0汤圆

 楼主| 发表于 2014-8-23 11:22:57 | 显示全部楼层
unsigned long 32位

出0入0汤圆

 楼主| 发表于 2014-8-25 07:54:08 | 显示全部楼层
czg1411 发表于 2014-8-23 10:55
//time_1s 初值等于1  
if(time_1s)
{

想再咨询下,要是建立一个数组,有5个元素,   第一的平均值为(a1);第二次平均(a1+a2)/2;。。第3次平均(a1+a2+a3)/3。。第4次平均(a1+a2+a3+a4)/4。。第5次平均为(a1+a2+a3+a4+a5)/5;这样应该如何操作好的呢  ,然后先进,后出,这样显示值应该更稳定,这样C语言应该如何表述好点呢

出0入0汤圆

 楼主| 发表于 2014-8-25 07:54:25 | 显示全部楼层
lcw_swust 发表于 2014-8-23 11:11
自己多想想,多试试。
上电时,可以把第一次读的数复制到整个数组的每个元素,这样取平均值就没影响了。 ...

想再咨询下,要是建立一个数组,有5个元素,   第一的平均值为(a1);第二次平均(a1+a2)/2;。。第3次平均(a1+a2+a3)/3。。第4次平均(a1+a2+a3+a4)/4。。第5次平均为(a1+a2+a3+a4+a5)/5;这样应该如何操作好的呢  ,然后先进,后出,这样显示值应该更稳定,这样C语言应该如何表述好点呢

出0入0汤圆

 楼主| 发表于 2014-8-25 07:54:41 | 显示全部楼层
babysnail 发表于 2014-8-23 10:58
小白
51这种低端的,最好做优化,像3次这种不科学。最好是2的N次,如 2,4,8,16............ ...

想再咨询下,要是建立一个数组,有5个元素,   第一的平均值为(a1);第二次平均(a1+a2)/2;。。第3次平均(a1+a2+a3)/3。。第4次平均(a1+a2+a3+a4)/4。。第5次平均为(a1+a2+a3+a4+a5)/5;这样应该如何操作好的呢  ,然后先进,后出,这样显示值应该更稳定,这样C语言应该如何表述好点呢

出0入0汤圆

 楼主| 发表于 2014-8-25 07:59:17 | 显示全部楼层
babysnail 发表于 2014-8-23 11:08
举个特殊的例子吧, /256 ,就是把低字节直接去了,根本不用运算

想再咨询下,要是建立一个数组,有5个元素,   第一的平均值为(a1);第二次平均(a1+a2)/2;。。第3次平均(a1+a2+a3)/3。。第4次平均(a1+a2+a3+a4)/4。。第5次平均为(a1+a2+a3+a4+a5)/5;这样应该如何操作好的呢  ,然后先进,后出,这样显示值应该更稳定,这样C语言应该如何表述好点呢

出0入0汤圆

 楼主| 发表于 2014-8-25 08:02:01 | 显示全部楼层
tam2907 发表于 2014-8-23 09:35
加个变量 cnt
中断里 time_1s =1

想再咨询下,要是建立一个数组,有5个元素,   第一的平均值为(a1);第二次平均(a1+a2)/2;。。第3次平均(a1+a2+a3)/3。。第4次平均(a1+a2+a3+a4)/4。。第5次平均为(a1+a2+a3+a4+a5)/5;这样应该如何操作好的呢  ,然后先进,后出,这样显示值应该更稳定,这样C语言应该如何表述好点呢
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 10:22

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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