打印

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

[复制链接]
11105|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作显示用。

使用特权

评论回复
5
gmm2015| | 2015-7-2 11:15 | 只看该作者
发代码出来分析下

使用特权

评论回复
6
coody| | 2015-7-2 11:19 | 只看该作者
没看程序。每个采样点计算绝对值(就是减中点电压取绝对值),然后平方和,要用32位的整数计算,最多可以做4096个采样不溢出。准确性还可以的,但是幅度很小时,准确度下降,比如测量220V,一般校准后做到1%没有问题,但是再测量一个几V的,误差会大点。

使用特权

评论回复
7
gx_huang| | 2015-7-2 11:34 | 只看该作者
wangpeng59 发表于 2015-7-2 11:14
我把那点儿程序截取下来看看:

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

不要在定时器中断里运行一些浮点计算函数。
有些函数,要求在主程序里计算。
中断程序里,只计算ulong类型的平方和。

使用特权

评论回复
8
军训的茶杯| | 2015-7-2 11:37 | 只看该作者
LZ你采集的是工频(50Hz)信号?

使用特权

评论回复
9
wangpeng59|  楼主 | 2015-7-2 12:21 | 只看该作者
gx_huang 发表于 2015-7-2 11:34
不要在定时器中断里运行一些浮点计算函数。
有些函数,要求在主程序里计算。
中断程序里,只计算ulong类 ...

我改成ulong,也还是不行。。

使用特权

评论回复
10
wangpeng59|  楼主 | 2015-7-2 12:22 | 只看该作者
军训的茶杯 发表于 2015-7-2 11:37
LZ你采集的是工频(50Hz)信号?

是啊,咋知道的?

使用特权

评论回复
11
gx_huang| | 2015-7-2 12:27 | 只看该作者
你要有合适的调试办法。
voltage每次赋予一个固定的值,看看结果多少。
C51的数学计算,要自己仔细计算一下是否溢出。
keil下可以直接软件仿真的。

使用特权

评论回复
12
gx_huang| | 2015-7-2 12:28 | 只看该作者
还有,U是什么?

使用特权

评论回复
13
lgq_123| | 2015-7-2 12:51 | 只看该作者
我感觉你可以先测试一下每次读取到的电压值,如果每一次的电压值都对的话,再考虑是不是数据类型或算法的问题,Ueff电压平方根值最好定义成float类型的值,然后考虑一下是不是需要把电压值放大10的倍数进行计算。

使用特权

评论回复
14
wangpeng59|  楼主 | 2015-7-2 12:57 | 只看该作者
gx_huang 发表于 2015-7-2 12:28
还有,U是什么?

U是AD采进来的原始数据,10位二进制数。0~1023

使用特权

评论回复
15
军训的茶杯| | 2015-7-2 12:57 | 只看该作者
工频信号采样,哪有1ms采一次的。。。
一般来说16点采样、24点、32点是常用的方法。
如果信号中有很多谐波,用傅里叶算法做滤波和计算。
如果只为了算有效值,最简单的就是24点数据相加再除以24.(24点采样时,所有数均为正数)

使用特权

评论回复
16
军训的茶杯| | 2015-7-2 13:02 | 只看该作者
LZ,给你个资料,你自己看下吧

采样方法.zip

776.56 KB

使用特权

评论回复
17
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字节的,溢出了。

使用特权

评论回复
评论
zyj9490 2015-7-2 19:41 回复TA
VOL=voltage*voltage*1ul; 这样,运算按ULONG 处理. 
18
lgq1542380129| | 2015-7-2 14:23 | 只看该作者
感觉还是中断里设置标志位,处理在中断外处理好。

使用特权

评论回复
19
gx_huang| | 2015-7-2 14:26 | 只看该作者
C51里,我研究过,8*8=16,16*16还是16,应该把16强制转换成32bit的。

使用特权

评论回复
20
dirtwillfly| | 2015-7-2 14:40 | 只看该作者
涉及到那么多数据的计算,建议每次采样后进行计算,取平方,累加,并除以1000,和计数

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

39

主题

217

帖子

2

粉丝