发新帖我要提问
12
返回列表
打印
[C语言]

ADC采集不准确问题。

[复制链接]
楼主: qazq123
手机看帖
扫描二维码
随时随地手机跟帖
21
gx_huang| | 2015-10-20 16:20 | 只看该作者 回帖奖励 |倒序浏览
qazq123 发表于 2015-10-20 15:34
不对吧,ADC均方根的信号是交流加直流的信号吧?我不减的话也不应该等于直流的信号啊,交流信号出不来。 ...

呵呵,好久不搞数学,数学都忘记了。
假设直流信号是a,交流信号是b*sin(t),则总电压y(t)=a+b*sin(t),a>b。
根据能量合成原理,你不应该这么算呀。
这应该是纯粹的数学问题。

使用特权

评论回复
22
gx_huang| | 2015-10-20 16:25 | 只看该作者
你把问题搞复杂了,你的ADC值,减去直流偏置,就是交流信号,对这个交流信号均方根,就可以了,就得出交流信号的有效值了。

使用特权

评论回复
23
qazq123|  楼主 | 2015-10-20 16:47 | 只看该作者
gx_huang 发表于 2015-10-20 16:25
你把问题搞复杂了,你的ADC值,减去直流偏置,就是交流信号,对这个交流信号均方根,就可以了,就得出交流 ...

我试试

使用特权

评论回复
24
qazq123|  楼主 | 2015-10-20 17:26 | 只看该作者
gx_huang 发表于 2015-10-20 16:20
呵呵,好久不搞数学,数学都忘记了。
假设直流信号是a,交流信号是b*sin(t),则总电压y(t)=a+b*sin(t),a ...

太久不接触数学了- -

使用特权

评论回复
25
qazq123|  楼主 | 2015-10-23 15:33 | 只看该作者
本帖最后由 qazq123 于 2015-10-23 15:35 编辑
gx_huang 发表于 2015-10-20 16:25
你把问题搞复杂了,你的ADC值,减去直流偏置,就是交流信号,对这个交流信号均方根,就可以了,就得出交流 ...

能不能再帮忙看看。我数码管显示为225.0V,有万用表测限流电阻端的电压为0.299~0.302之间变换。我是计算出问题了吗?还是数据类型出问题?还是采集错了?求帮忙,大哥。temp_single是unsigned int型。temp_sum是unsigned long型。VREF是50。 参考电压为5V。直流偏置2.4V

#pragma interrupt_handler adc_isr:iv_ADC     
void adc_isr(void)
{
ADMUX =0x46;//选择内部AVCC为基准
temp_single=ADC&0x3ff;
temp_single=(unsigned long)((unsigned long)(temp_single*50/0x3ff)-24);
temp_sum = temp_sum + temp_single*temp_single;
if(flag==64)
{
   adc_rel=(unsigned int)((unsigned long)(sqrt((temp_sum)/64))*750);
   flag = 0;
   temp_sum = 0;
}

}




使用特权

评论回复
26
gx_huang| | 2015-10-23 15:56 | 只看该作者
基础呀,大于2.4V是正的,小于2.4V是负的,你当uint来算,能行么。
而且,每次电压的精度才0.1V,也太低了吧。

使用特权

评论回复
27
qazq123|  楼主 | 2015-10-23 16:12 | 只看该作者
本帖最后由 qazq123 于 2015-10-23 16:22 编辑
gx_huang 发表于 2015-10-23 15:56
基础呀,大于2.4V是正的,小于2.4V是负的,你当uint来算,能行么。
而且,每次电压的精度才0.1V,也太低了 ...

额额 。。有符号啊。不大懂额。你能不能距离一个类型转换或者处理的例子?就temp_single=(unsigned long)((unsigned long)(temp_single*50/0x3ff)-24);的例子吧,拜托~欧巴~

那精度的话,把小数点取多一点就可以了吧。

使用特权

评论回复
28
gx_huang| | 2015-10-24 09:48 | 只看该作者
应该拜托你自己呀,这些要靠自己学习的。
基础的数学、物理、电路分析,甚至连基本的C语言基础知识,这些都是研发的前提。
否则,你学单片机,连皮毛都没有学会呀。
1-24=-23,如果作为无符号数,结果不是-23,是65536-23=65513了.

使用特权

评论回复
29
qazq123|  楼主 | 2015-10-24 10:02 | 只看该作者
gx_huang 发表于 2015-10-24 09:48
应该拜托你自己呀,这些要靠自己学习的。
基础的数学、物理、电路分析,甚至连基本的C语言基础知识,这些都 ...

恩,现在数据是有了,但精度太低,在3V之间波动。 是不是需要校准还是什么方法提高精度?

使用特权

评论回复
30
gx_huang| | 2015-10-24 10:18 | 只看该作者
int temp_single;
temp_single=ADC&0x3ff;temp_single=(int)((long)temp_single*500/0x3ff)-240;
temp_sum = temp_sum +(long) temp_single*temp_single;
无非就是类型不要错,数据不要溢出。

使用特权

评论回复
31
gx_huang| | 2015-10-24 10:19 | 只看该作者
电压扩大到0.01V精度

使用特权

评论回复
32
qazq123|  楼主 | 2015-10-24 10:58 | 只看该作者
gx_huang 发表于 2015-10-24 10:18
int temp_single;
temp_single=ADC&0x3ff;temp_single=(int)((long)temp_single*500/0x3ff)-240;
temp_sum ...

不行啊 = = 不知道为什么我只要把VREF改成500或5000,直流偏置相应增加, 分压倍数相应减小。就都不行。插上去一点反应都没有

使用特权

评论回复
33
qazq123|  楼主 | 2015-10-24 11:02 | 只看该作者
gx_huang 发表于 2015-10-24 10:18
int temp_single;
temp_single=ADC&0x3ff;temp_single=(int)((long)temp_single*500/0x3ff)-240;
temp_sum ...
#pragma interrupt_handler adc_isr:iv_ADC     
void adc_isr(void)
{
ADMUX =0x46;//选择内部AVCC为基准
temp_single=ADC&0x3ff;
temp_single=(long)temp_single*Vref/0x3ff-240;

temp_sum = (long)temp_sum + (long)temp_single*temp_single;
if(flag==128)
{
   adc_1=(int)(sqrt((temp_sum)/128));
  // flag = 0;
   temp_sum = 0;
}
if(flag==256)
{
   adc_2=(int)((sqrt((temp_sum)/128)));
  // flag = 0;
   temp_sum = 0;
}
if(flag==384)
{
   adc_3=(int)((sqrt((temp_sum)/128)));
  // flag = 0;
   temp_sum = 0;
}
if(flag==512)
{
   adc_4=(int)((sqrt((temp_sum)/128)));
   //flag = 0;
   temp_sum = 0;
   
   
}
if(flag==640)
{
   adc_5=(int)((sqrt((temp_sum)/128)));
  // flag = 0;
   temp_sum = 0;
}
if(flag==768)
{
   adc_6=(int)((sqrt((temp_sum)/128)));
  // flag = 0;
   temp_sum = 0;
}
if(flag==896)
{
   adc_7=(int)((sqrt((temp_sum)/128)));
  // flag = 0;
   temp_sum = 0;
}
if(flag==1024)
{
   adc_8=(int)((sqrt((temp_sum)/128)));
  // flag = 0;
   temp_sum = 0;
}
if(flag==1152)
{
   adc_9=(int)((sqrt((temp_sum)/128)));
  // flag = 0;
   temp_sum = 0;
}
if(flag==1280)
{
   adc_10=(int)((sqrt((temp_sum)/128)));
   //flag = 0;
   temp_sum = 0;
   
}
if(flag==1408)
{
   adc_11=(int)((sqrt((temp_sum)/128)));
  // flag = 0;
   temp_sum = 0;
}
if(flag==1536)
{
   adc_12=(int)((sqrt((temp_sum)/128)));
   flag = 0;
   temp_sum = 0;
   adc_rel=(int)((float)(adc_2+adc_3+adc_4+adc_5+adc_6+adc_7+adc_8+adc_9+adc_10+adc_11+adc_12)/11*75.3);
}
}

帮我看下数据类型有错可否。 VREF500

使用特权

评论回复
34
qazq123|  楼主 | 2015-10-24 11:53 | 只看该作者
gx_huang 发表于 2015-10-24 10:19
电压扩大到0.01V精度

不大懂什么意思

使用特权

评论回复
35
gx_huang| | 2015-10-24 12:31 | 只看该作者
自己的事情自己解决呀,就是调试的技巧呀,一步一步显示出来,看看哪里的问题。

使用特权

评论回复
36
gx_huang| | 2015-10-24 12:32 | 只看该作者
24表示2.4V,240表示2.40V,精度就是0.01V了,这个也不懂?

使用特权

评论回复
37
qazq123|  楼主 | 2015-10-24 13:48 | 只看该作者
本帖最后由 qazq123 于 2015-10-24 13:53 编辑
gx_huang 发表于 2015-10-24 12:32
24表示2.4V,240表示2.40V,精度就是0.01V了,这个也不懂?

这个知道。= = 但是我不知道为什么Vref设置为500,   减去240. 这样得不出值额,是不是数据类型出错了,可是查不出哪里出错了,感觉是对的- -

使用特权

评论回复
38
gx_huang| | 2015-10-24 14:49 | 只看该作者
所以,这就是调试的问题了,有些错误一下子发现不了,你可以输入一个模拟的输入值,一步一步看,看哪个环节的计算出问题。

使用特权

评论回复
39
qazq123|  楼主 | 2015-10-26 14:26 | 只看该作者
貌似稿手 发表于 2015-10-19 17:59
应该多次采样(10次) 去掉 最大值与最小值  取平均值 就行了  我这边就是这样做的很准呢 ...

精度问题这样就可以解决吗?我感觉不行啊, 我采集的电压为0.306~0.310之间变动,分压倍数为750。以下就扩大了太多倍了啊。这怎么解决,,为啥万用表测市电那端能稳定在0.5V之间变动呢?这是怎么实现的?

使用特权

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

本版积分规则