得到了物理量数值,就可以进行显示,故障判断等操作。
我们需要找到从模数转换数值到物理量之间的转换关系;
比如,用14位的ADC对市电电压进行采样,得到了某个数据,该数据并不是电压值,而需要经过转换关系得到电压值。
如果传感器和信号处理电路的线性度都比较好,可以在整个测量范围内采用线性关系进行转换,如下:
![855ab08fb9f44336919e069193127dda.jpg 855ab08fb9f44336919e069193127dda.jpg](https://static.assets-stash.eet-china.com/forum/202201/30/094050rh4j65i1pgd81mr8.jpg)
![7a3872a775694e17a1f68d0fee2545a8?from=pc.jpg 7a3872a775694e17a1f68d0fee2545a8?from=pc.jpg](https://static.assets-stash.eet-china.com/forum/202201/30/094050zulkdwu4m0kw5kwu.jpg)
ADC与物理量的线性关系
x为ADC读到的数值,y为物理量的数值,比如电压值、电流值、温度值、压力值等等。
有两个问题需要注意:
1) k,b的数值从何而来
2) 单片机如何转换
一、k, b数值的确认
我通常采用三种方法来确认k、b数值:
1)正向推导,根据传感器、信号处理电路的线性关系推导得到:
以下图的三相线电压测量电路为例:
![2abb642813d24e4f83239f7fd880fdba?from=pc.jpg 2abb642813d24e4f83239f7fd880fdba?from=pc.jpg](https://static.assets-stash.eet-china.com/forum/202201/30/094050kpr19ri524a35qrw.jpg)
三相线电压测量电路
电压互感器的参数为:
初次级的变比:1mA:1mA
初级限流电流为:400kΩ;
次级线圈电阻为:17Ω;
次级采样电阻为:100Ω;
运放组成的处理电路的参数为:
放大倍数:47/(4.7+0.1//0.017)=9.969。
根据这些参数,假设相电压的真有效值为U,按照下面步骤推导:
- 初级电流为
- 次极输出电压=次极电流*100//4700=
- 运放输出电压=次极输出电压*放大倍数
- 单片机读到的14位ADC的数值=
- ADC与线电压的关系为:
- 进一步得到:
- 为了减少量化误差,提供精度,我们对换算得到的电压保留一位小数,当用整数来表示需,需要扩大10倍,得到:
2)分段线性化以及最小二乘法确认转换关系
在另一篇文章中详述。
二、 单片机如何转换
当我们得到ADC数值与物理量之间的线性转换关系:
![443868b06014424db2eafcefc67b3f95.jpg 443868b06014424db2eafcefc67b3f95.jpg](https://static.assets-stash.eet-china.com/forum/202201/30/094050jejwlwxxeid986r8.jpg)
低端的单片机都没有硬件浮点数计算能力,即使是32位的cortex-M0/cortex-M3内核的处理器(如STM32F0xx以及STM32F1xx系统处理器)也没有硬件浮点数计算能力。
当我们通过浮点数进行转换运算时,会消耗大量的时间。
我的做法是,将k转变为整以一个整数后再除以另一个整数,
而对物理量保留小数点,利用扩大整10倍的整数进行存储时,b可以直接四舍五入为整数;
即:
![a2670342bba14556ba0fb5260519b6bb.jpg a2670342bba14556ba0fb5260519b6bb.jpg](https://static.assets-stash.eet-china.com/forum/202201/30/094050a5u33f02i720pp5r.jpg)
采用64MHz的时间频率,
计算65535次的浮点数转换的耗时为:164ms。
单次运算耗时为:2.5us。
转化为整数乘除运算,计算65535次耗时为:20ms。
单次运算耗时为:0.31us。
当转为整数运算时,可能会扩大舍入误差。
我的做法是,根据整数M、N的位数取大数,比如16位的数。
如果k小于1,则将N固定为65535。
M=round(k*65535)。
如果k大于等于1,则将M固定为65535。
N=round(65535/k)。
在上例中,k=3.302264,则M=65535,N=round(65535/3.302264)=19845。
const STRConfigCalDef g_pt_calvoldefs[PT_VOLTAGE_NUM] ={ {65535, 19845, 0}, {65535, 19845, 0}, {65535, 19845, 0} }; U16 pt_calval(U16 val, U16 pm, U16 pn, signed int pk,){ U32 uwDataA; signed int uwDataB; U16 resval; uwDataA = (U32)val * pm; if(pn == 0){ pn = 1; } uwDataA = (U32)val * pm; uwDataA = (U32)uwDataA / pn; uwDataB = (signed int)uwDataA; uwDataB = uwDataB + pk; if(uwDataB < 0){ uwDataB = 0; } if(uwDataB > 65535){ uwDataB = 65535; } resval = (U16)uwDataB; return(resval) }
复制代码![d994cd7ced7f4cc4b39b5c0bb9584fe4?from=pc.jpg d994cd7ced7f4cc4b39b5c0bb9584fe4?from=pc.jpg](https://static.assets-stash.eet-china.com/forum/202201/30/094050odgyriyfp1ygrpr3.jpg)
转为整数运算的转换算法
来源:物联网全栈开发