模拟量采集从硬件到程序,从滤波到实际值转换,多少人懂了

在单片机系统里对模拟量的处理要比数字量稍显复杂,但是只要掌握了使用技巧,使用起来也很简单,很多朋友一开始比较纠结于单片机的底层语言,非要先弄个明白才罢休,其实大可不必,重要的是我们要先学会怎么应用。

现以铅酸电池电压检测充电电流检测为例讲解模拟量的硬件和程序的设计。

如图1为28节铅酸电池的电压检测电路,1--14节组成电池组1,15--28节组成电池组2;第1节正极为BAT+,14与15节之间为BATM,第28节负极为BAT-。输入端的8个二极管的作用是钳位作用;电路计算如图所示。

图1:电池组电压检测电路

如图2为铅酸电池的充电电流检测电路,TA1为工频电流互感器,输入的4个二极管为整流二极管,电流流过R37(510Ω)形成压差△V。电路计算如图所示。

图2:电池组充电电流检测电路

如图3为单片机STM32F103CBT6,图1和图2的模拟信号输入至单片机的PA5、PA6、PA7。

图3:STM32F103CBT6单片机

由于代码较多,为便于浏览,我就把其中一部分以截图的形式展示

如图4为单片机adc.c文件的底层配置,把PA5、PA6、PA7端口配置成模拟输入模式

图4:配置端口模式

如图5对以上三个模拟量进行模数转换并缓存入数组ADC_ConvertedValue[3],得到的AD值的范围是0~4096

图5:模数转换并缓存

如图6把以上两个配置函数整合在一起,定义成模拟量的初始化函数void ADC1_Init(void)。

图6:初始化

如图7在adc.h文件里声明函数void ADC1_Init(void),另外几个函数也在adc的c文件里定义的,后面附上源程序(非截图)。

图7:声明函数

如图8在main()主函数里调用ADC1_Init()初始化函数(要去掉void),初始化函数一定要放在while(1)的前面,表示在进入while(1)无限循环前只执行一次。Analog_Processing()为模拟量处理函数,要放在while(1)无限循环里面(该函数在下面讲)。

图8,函数调用

以下为模拟量在main.c文件里的定义。

s16 Charging_Current; //充电电流实际值
s16 Battery1_Voltage; //电池组1电压实际值
s16 Battery2_Voltage; //电池组2电压实际值
s16 Battery_Voltage; //电池组总电压值

❤下面三个函数的定义都在adc.c文件里面定义的。

以下代码为模拟量处理函数:①对数组ADC_ConvertedValue[3]缓存值进行滤波处理;②对滤波后的AD值转换为实际值。

/******************************模拟量处理函数******************************/void Analog_Processing(void){//对AD值进行滤波ADC_Charging_Current=Filter(ADC_ConvertedValue[0],ADC_Charging_Current,1,10);ADC_Battery1_Voltage=Filter(ADC_ConvertedValue[1],ADC_Battery1_Voltage,1,10);ADC_Battery2_Voltage=Filter(ADC_ConvertedValue[2],ADC_Battery2_Voltage,1,10);//AD值转换为实际值Charging_Current = Adc_To_Act(ADC_Charging_Current, 10, 4096, 0, 220);//22.0ABattery1_Voltage = Adc_To_Act(ADC_Battery1_Voltage, 10, 4096, 0, 267);//267VBattery2_Voltage = Adc_To_Act(ADC_Battery2_Voltage, 10, 4096, 0, 267);//267V//两组电压相加得到总电压Battery_Voltage = Battery1_Voltage + Battery2_Voltage;}

以下代码为滤波函数,滤波函数有很多,采用合适的才是最实用的(该函数滤波后的值是连续变化的,有些滤波函数滤波后的值是跳变的)。

/******************************
滤波函数(base/k越大,容性越大)
该函数相当于是一个电容,通常取值k=1,base=10
******************************/
u16 Filter(u16 NewData, u16 OldData, u8 k, u8 base)
{
u16 uiResult;
if (NewData > OldData)
{
uiResult = NewData - OldData;
uiResult *= k;
uiResult += base >> 2;
uiResult /= base;
uiResult = OldData + uiResult;
}
else if (OldData > NewData)
{
uiResult = OldData - NewData;
uiResult *= k;
uiResult += base >> 2;
uiResult /= base;
uiResult = OldData - uiResult;
}
else
{
uiResult = NewData;
}

return(uiResult);
}

使用方法如下:NewData表示最新采用的模拟量;OldData表示滤波后的模拟量。

ADC_Battery1_Voltage=Filter(ADC_ConvertedValue[1],ADC_Battery1_Voltage,1,10);

为便于逻辑计算、控制及显示,以下代码是把AD值转换为实际值,

/******************************
AD值转换实际值函数
******************************/
s16 Adc_To_Act(s16 Adc_Value, s16 Pre_Adc_Min, s16 Pre_Adc_Max, s16 Pre_Act_Min, s16 Pre_Act_Max)
{
s32 _temp;
s32 _range;
_temp = (s32)((Adc_Value - Pre_Adc_Min) * (Pre_Act_Max - Pre_Act_Min) / (Pre_Adc_Max-Pre_Adc_Min)) + Pre_Act_Min;
_temp = Adc_Value - Pre_Adc_Min;
_range = Pre_Act_Max - Pre_Act_Min;
_temp = _temp * _range;
_range = Pre_Adc_Max - Pre_Adc_Min;
_temp = _temp + _range / 2;
_temp = _temp / _range;
_temp = _temp + Pre_Act_Min;
return(_temp);
}

使用方法如下:Adc_Value表示要转换的模拟量;Pre_Adc_Min表示模拟量AD值的最小值;Pre_Adc_Max表示模拟量AD值的最大值;Pre_Act_Min表示转换后实际值的最小值;Pre_Act_Max表示转换后实际值的最大值;(以下最大实际值220表示22.0A,是因为数码管显示需要小数表示)。

Charging_Current = Adc_To_Act(ADC_Charging_Current, 10, 4096, 0, 220);//22.0A

要点:

①模拟量的采样电路,我多采用运放的差分放大电路,原因是被测电压可以和运放不用共地,且可有效抑制共模噪声,可达到较高的精确线性测量,比如以上电池组的被测电压的误差与实际相差在0.3V左右;

②电池组输入至运放的8个1M的电阻是两个为一组的,且功率至少1/4W以上,因为在高压下的电阻容易老化,为保险起见,通常一个电阻的最大压差在100V以下为宜;

③电池组分为两组检测,一是为了降低元件所承受的电压,二是为了监视两组电池电压之间是否平衡,达到保护电池目的。

③函数应功能模块化,且具备通用性质,便于移植和调用,对于很多朋友应先学会如何使用,底层代码只要会配置就完全足够了。

当然,以上提供的设计是我通常的做法,能满足大多数的常规应用。

来源:电卤药丸

(0)

相关推荐

  • 2021届最新模拟试题精编05:函数与导数

    2021届最新模拟试题精编05:函数与导数

  • 如何通过高性能的ADC帮助你搞定电赛

    写在最前面 本文是一篇并不枯燥的介绍ADC的文章.考虑到现在有些读者刷文章的翻台率比HR筛简历的速度还快,所以就算你不能每个字都读完,至少每张图也都花点时间看看,毕竟为了让表述言简意赅也是 [绞尽了脑 ...

  • 这个二次函数压轴题,就不亚于大连去年的模...

    这个二次函数压轴题,就不亚于大连去年的模拟,和今年各区的所有模拟考试题,不信,请大家试一试吧!

  • 【技巧1001-10】-下拉列表居然可以多选?!

    下拉列表的制作,基本上大家都会做,使用数据有效性-列表即可处理 如果还不会,查看 往期的教程: 智能下拉菜单系系列-可配置的一级下拉 项目实战系列-增强智能下拉列表[2] 以上都是一个单元格,只能选择 ...

  • STM32与串口屏交互(USART HMI)

    一.前期准备 二.串口屏上位机使用方法以及界面设计 三.STM32软件编程 四.单片机发送数据的字符串指令汇总 五.总结 不管是备战电赛还是准备毕设,一块能与单片机交互的屏幕显得尤为重要,相较于传统的 ...

  • 模拟量采集后间隔5秒采集记录相减程序

    模拟量采集后间隔5秒采集记录相减程序

  • PLC采集模拟量数据

    工业控制中,模拟量采集的主要过程原理是:将各种工艺参数如温度.压力.流量.液位.成分等物理量变换成统一标准信号(标准信号通常是:电流为4-20mA或电压为0-5V),再传送到控制器或者指示记录仪中,进 ...

  • 西门子PLC与变频器的模拟量干扰处理实例

    技成PLC课堂 从0到1,带你学习PLC技能! 79篇原创内容 公众号 01 实例一 现象说明: 西门子PLC中AO点发出一路4-20mA电流控制信号,输出至西门子变频器,无法控制变频器启动. 故障查 ...

  • 为什么采用4—20mA的电流来传输模拟量?

    采用电流信号的原因是不容易受干扰,因为工业现场的噪声电压的幅度可能达到数V,但是噪声的功率很弱,所以噪声电流通常小于nA级别,因此给4-20mA传输带来的误差非常小:电流源内阻趋于无穷大,导线电阻串联 ...

  • 调试PLC时,模拟量跳变、掉线或无穷大,怎么破?

    领取-史上最全的欧姆龙资料! (点击上方红字,免费领资料) 下面是一个变频器对PLC模拟量干扰的例子以及用信号隔离模块克服此类干扰的解决办法. 一.举例1 现象说明 西门子PLC中AO点发出一路4-2 ...

  • 学PLC不会模拟量?怎么行

    爱上PLC Official Account 一起学PLC 爱上PLC 如果你也是对PLC情有独钟,请先点击[关注]然后进入 Official Account 一起学PLC

  • 模拟量信号和数字量信号的区别

    工业控制中,一般有模拟量信号和数字量信号两种,其中模拟量信号常用4-20mA信号,其信息详见:工控上为什么多使用4~20mA信号? 模拟量信号与数字量信号的区别是,模拟量是再时间和数值上连续的物理量, ...

  • ABB工业机器人配置常用信号及配置模拟量输出

    ABB工业机器人配置常用信号 1. 通常打开示教器-"输入输出"窗口时,都会如下图显示为空. 2. 因为默认打开"输入输出"窗口时,进入"常用&quo ...

  • PLC对模拟量信号是如何转换的?

    模拟量信号是自动化过程控制系统中最基本的过程信号(压力.温度.流量等)输入形式.系统中的过程信号通过变送器,将这些检测信号转换为统一的电压.电流信号,并将这些信号实时的传送至控制器(PLC). PLC ...