单片机采集并算电压有效值的问题

[复制链接]
12115|42
 楼主| wangpeng59 发表于 2015-7-2 10:47 | 显示全部楼层 |阅读模式
RT,用STC12C5A60S2单片机自带的AD采集电压信号。
本来计划每1毫秒采集的电压数据样本,计算平方,积累到1000个样本后求和,平方和除以1000,再开根号后就得到电压的均方根。写了写程序,显示是0。而且,运算中感觉数值太大,难道要用到float型?想问问这种计算有没有比较好的程序模板可以参考参考?谢谢!!
gx_huang 发表于 2015-7-2 11:01 | 显示全部楼层
那怎么出来0的,平方后,都是大于等于0的吧。
前面的1000个数据平方累加,用ulong类型应该够大了吧。你的ADC是10bit的吧,实际0V对应VCC/2还是0V?
最后开根号可以用浮点数了。
 楼主| wangpeng59 发表于 2015-7-2 11:11 | 显示全部楼层
gx_huang 发表于 2015-7-2 11:01
那怎么出来0的,平方后,都是大于等于0的吧。
前面的1000个数据平方累加,用ulong类型应该够大了吧。你的AD ...

不知道呢,所以我觉得是数据类型设定有问题?
 楼主| wangpeng59 发表于 2015-7-2 11:14 | 显示全部楼层
我把那点儿程序截取下来看看:

unsigned long VOL;  //存采集电压的平方值
float SUM=0;        //累加求和
uint number=1;      //采集次数
uint Ueff;          //电压均方根值
int voltage;  //每1ms采集到的电压瞬时值
extern uint U; //经内部转化产生10位二进制数

/*****定时器0 1ms 中断*****/
void timer0IntProc() interrupt 1
{
    TL0 = TIMER_LOW;                  //方式1,产生1ms定时的初值。晶振11.0592MHz
    TH0 = TIMER_HIGHT;
    voltage=U*17-8453;         //电压转换公式计算后的结果:[3302×0.512×(5U/1024-5/2)]/5,再乘以10,四舍五入而得
        VOL=voltage*voltage;
        SUM=VOL+SUM;
        number++;
        if(number==1001)
        {
         number=1;
         SUM=SUM/1000;
         Ueff=sqrt(SUM);
         SUM=0;
         }
}  

Ueff拿去再给12864作显示用。
gmm2015 发表于 2015-7-2 11:15 | 显示全部楼层
发代码出来分析下
coody 发表于 2015-7-2 11:19 | 显示全部楼层
没看程序。每个采样点计算绝对值(就是减中点电压取绝对值),然后平方和,要用32位的整数计算,最多可以做4096个采样不溢出。准确性还可以的,但是幅度很小时,准确度下降,比如测量220V,一般校准后做到1%没有问题,但是再测量一个几V的,误差会大点。
gx_huang 发表于 2015-7-2 11:34 | 显示全部楼层
wangpeng59 发表于 2015-7-2 11:14
我把那点儿程序截取下来看看:

unsigned long VOL;  //存采集电压的平方值

不要在定时器中断里运行一些浮点计算函数。
有些函数,要求在主程序里计算。
中断程序里,只计算ulong类型的平方和。
军训的茶杯 发表于 2015-7-2 11:37 | 显示全部楼层
LZ你采集的是工频(50Hz)信号?
 楼主| wangpeng59 发表于 2015-7-2 12:21 | 显示全部楼层
gx_huang 发表于 2015-7-2 11:34
不要在定时器中断里运行一些浮点计算函数。
有些函数,要求在主程序里计算。
中断程序里,只计算ulong类 ...

我改成ulong,也还是不行。。
 楼主| wangpeng59 发表于 2015-7-2 12:22 | 显示全部楼层
军训的茶杯 发表于 2015-7-2 11:37
LZ你采集的是工频(50Hz)信号?

是啊,咋知道的?
gx_huang 发表于 2015-7-2 12:27 | 显示全部楼层
你要有合适的调试办法。
voltage每次赋予一个固定的值,看看结果多少。
C51的数学计算,要自己仔细计算一下是否溢出。
keil下可以直接软件仿真的。
gx_huang 发表于 2015-7-2 12:28 | 显示全部楼层
还有,U是什么?
lgq_123 发表于 2015-7-2 12:51 | 显示全部楼层
我感觉你可以先测试一下每次读取到的电压值,如果每一次的电压值都对的话,再考虑是不是数据类型或算法的问题,Ueff电压平方根值最好定义成float类型的值,然后考虑一下是不是需要把电压值放大10的倍数进行计算。
 楼主| wangpeng59 发表于 2015-7-2 12:57 | 显示全部楼层
gx_huang 发表于 2015-7-2 12:28
还有,U是什么?

U是AD采进来的原始数据,10位二进制数。0~1023
军训的茶杯 发表于 2015-7-2 12:57 | 显示全部楼层
工频信号采样,哪有1ms采一次的。。。
一般来说16点采样、24点、32点是常用的方法。
如果信号中有很多谐波,用傅里叶算法做滤波和计算。
如果只为了算有效值,最简单的就是24点数据相加再除以24.(24点采样时,所有数均为正数)
军训的茶杯 发表于 2015-7-2 13:02 | 显示全部楼层
LZ,给你个资料,你自己看下吧

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
gx_huang 发表于 2015-7-2 13:25 | 显示全部楼层
wangpeng59 发表于 2015-7-2 12:57
U是AD采进来的原始数据,10位二进制数。0~1023

VOL=voltage*voltage;
这个语句错了,VOL是4字节的,后面是2字节的,结果还是2字节的,溢出了。

评论

VOL=voltage*voltage*1ul; 这样,运算按ULONG 处理.  发表于 2015-7-2 19:41
lgq1542380129 发表于 2015-7-2 14:23 | 显示全部楼层
感觉还是中断里设置标志位,处理在中断外处理好。
gx_huang 发表于 2015-7-2 14:26 | 显示全部楼层
C51里,我研究过,8*8=16,16*16还是16,应该把16强制转换成32bit的。
dirtwillfly 发表于 2015-7-2 14:40 | 显示全部楼层
涉及到那么多数据的计算,建议每次采样后进行计算,取平方,累加,并除以1000,和计数
您需要登录后才可以回帖 登录 | 注册

本版积分规则

39

主题

217

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部