目录

基于STM32的高精度智能压力变送器

本文介绍了一个具有就地显示功能、RS485串口通信功能、4-20mA线性标准化电流输出功能的压力变送器仪表的设计。该仪表量程为0-1MPa,精度在1级以内,且具有配套的基于MFC的上位机软件。

硬件选型与设计

测量部分

压力传感器

压力的测量使用了MPM280型压阻式压力传感器,它的耐压范围为0-2MPa,低压参考端通大气,测得的压力为表压。MPM280可以将气压信号转化为应变片的形变。MPM280为全桥接法,通过给全桥一个恒定且稳定的电压激励,便可以生成电压模拟信号供电路采集。

https://img.yuanze.wang/posts/stm32-pressure-transmitter/mpm280.jpg
MPM280型压阻式压力传感器

压力的生成使用了实验室提供的斯贝克SPMK2000E高压气体压力源,它自带一个高精度的量程为0-2MPa的标准表,同时提供了两个接入压力表的接口,通过压杆可以向装置内打气,并通过螺杆精密产生压力。

https://img.yuanze.wang/posts/stm32-pressure-transmitter/spmk2000e.jpg
SPMK2000E高压气体压力源

ADC芯片

HX711是一款高精度的24位A/D转换器芯片,该芯片集成了包括稳压电源、片内时钟振荡器等电路。利用HX711可以将全桥输出的微小模拟信号转化成为24位的数字信号,并由单片机进行读取,后经过单片机内部程序,通过标定的数值,将ADC读数转换为压力值。

HX711内置输入选择开关与2个通道,可任意选取通道A或通道B与其内部的低噪声可编程放大器相连。通道A的可编程增益为128或64,对应的满额度差分输入信号幅值分别为±20mV或±40mV。通道B则为固定的32增益。芯片内提供稳压电源,可直接向外部传感器和芯片内的A/D转换器提供电源。

压力传输与显示

就地显示与上位机连接

就地显示使用了工业中常用的LCD1602液晶显示屏,用于实时显示当前的压力值。

工业仪表常常使用RS485电平来进行强抗干扰的低速通信。本设计同样使用RS485电平将压力表与上位机连接。仪表使用一块MAX485芯片,将单片机的TTL电平转换为RS485电平。上位机使用常见的USB转TTL模块,并通过TTL-RS485转换模块将电平转换为RS485电平。

https://img.yuanze.wang/posts/stm32-pressure-transmitter/rs485-module.jpg
使用TTL转RS485模块与上位机相连

4-20mA远传部分

在信号远传中,若不使用电流传输方式而是电压传输方式,被传输的信号将会容易受到导线电阻的影响,这会对传输精度造成影响。因此,本设计使用通用的4-20mA电流信号来传输压力值。当电流为4mA时,代表压力为0Pa,电流为20mA时,代表压力为最大量程1MPa

单片机将传感器产生的模拟信号转换成数字信号后才能处理,因此需要利用高精度DA芯片将数字信号重新转换为模拟信号才能够转换为模拟电流。本设计使用高精度12位DAC芯片TLC5615,产生可调的电压信号,并经由电流环电路,产生4-20mA线性标准化的电流信号。

XTR115是单片4-20mA电流信号两线变送器。它提供了完整的电桥激励、传感器线性化和电流输出电路,可利用VREG脚从附加的外部输入电路提供电流。

https://img.yuanze.wang/posts/stm32-pressure-transmitter/xtr115.png
XTR115的框图

下面列为整个系统的信号转化流图。

电路的设计

变送器的整体原理图如下图所示。PDF版的高清原理图可在文末链接中下载。

https://img.yuanze.wang/posts/stm32-pressure-transmitter/sch.png
变送器的原理图

软件设计

上位机设计

串口接收到的数据的处理

在处理串口接收数据的时候,首先注册了串口数据接收的事件函数,当串口接收到有效数据时事件函数会被执行。在接收事件函数中,首先获取串口接收到的数据,并将数据转换为字节数组以便后续处理。接着,在事件函数内会调用数据的处理函数,这个函数内包含数据包的CRC校验与数据每一帧的解析与存储,并且会根据所选择的小数格式来读取浮点型小数。

串口相关的所有函数都被设置在了一个窗口内,这个窗口包含串口控件的初始化、消息处理函数、参数设置以及打开关闭串口等菜单的功能。这个窗口中的定时器负责周期性采集传感器数据,并使用其中的串口接收事件函数来获取数据,并对数据进行处理,将处理之后的数据存储到数据存储结构体内,同时显示到窗口上的文本框中。

Modbus通信协议

Modbus协议是一种已广泛应用于当今工业控制领域的通用通讯协议。通过此协议,控制器相互之间、或控制器经由网络可以和其它设备之间进行通信。Modbus协议使用的是主从通讯技术,即由主设备主动查询和操作从设备。Modbus通讯物理接口可以选用串口(包括RS232和RS485),也可以选择以太网口。

Modbus协议的数据包主要分为四部分:设备地址、功能代码、数据与校验值。对于本次计算机与压力表的通信来说,计算机就是主机,负责向压力表查询数据;而压力表相当于从机,相应主机的查询请求并返回对应的数据。主机发送的命令基本结构如下:

字节 0x01 0x03 0x13 0xBA 0x00 0x0F 0x20 0xAF
意义 设备地址 “读”功能代码 目标寄存器起始地址高位 目标寄存器起始地址低位 读取字节数高位 读取字节数低位 CRC校验码低位 CRC校验码高位

从机回复的数据包结构如下:

字节 01 03 0A 00 00 00 00 00 00 00 00 00 00 xx xx
意义 设备地址 “读”功能代码 返回数据长度(int) 压力(float) 温度(未使用,float) 状态(int) CRC校验码高低位

实际Modbus应用时,一个总线往往并联数个仪表,因此每个仪表需要有自己唯一的地址,主机查询数据的时候,仪表需要根据自身地址确定是否响应请求,同时根据CRC校验的结果确定数据包是否有效。一旦确定数据包有效,即根据主机请求的数据地址,返回相应的数据。

定时采集并显示压力参数曲线

串口相关的代码都放在了串口控制面板这一个窗口类之中。在这个窗口类中,通过打开串口的按钮,设定了一个定时器,在这个定时器的事件函数中,控制串口向压力表发送查询压力函数;压力表接收到查询指令后返回数据包,触发串口的接收事件函数,在接收事件函数内,对数据包进行解包处理,并将数据更新到结构体内保存以及显示到文本框中。 程序在解析数据包的过程中,首先验证CRC校验码。如果校验失败则丢弃数据包,如果验证成功,则接收数据包,并根据数据包中每一个数据的位置,使用浮点数转换函数,将16进制数据转换为正确的浮点数。

单片机主控程序设计

单片机采用STM32F103C8T6。单片机首先设置HX711ADC与TLC5615的采样周期与时钟周期,然后循环读取数据,并通过参考电压换算公式转换为模拟电压信号,同时使用RS485接口,使用与上位机匹配的Modbus协议进行数据传输。

ADC采集与量化

ADC的作用是将传感器的输出端电压转化为数字信号,通过量化、拟合得到相应的气压值。HX711采集到的数据是24位的。由于电压传感器输出端输出的电压值变换范围不够大,因此需要编程设置ADC在采集时使用B通道并采用32倍增益采集。

作为压阻式传感器,其与气压的对应关系并非是完全线性的,存在一定的非线性误差;且需要确定其灵敏度和零点值,所以需要对ADC读数进行标定与多项式拟合。通过拟合,得出如下使用三次曲线的拟合结果。

y = 0.00000000000000000116 x^3 - 0.00000000000000750175 x^2 + 0.00000770572583981333 x - 0.00105882952018538000

通过三次曲线拟合,使个别点的相对误差降低到0.1%,基本消除了传感器与检测电路的非线性误差,保证了变送器的精度,得到了ADC读数与气压值的精确对应关系。

主程序

下面为单片机程序的主函数部分。主函数首先对各个外设进行初始化,然后进入主循环。在主循环中,程序首先读取ADC的值,然后使用最近8次的读数进行平均以降低误差和抖动。接下来,使用拟合公式,将ADC读数转换为压力值,并分别使用LCD显示、发送到上位机和使用DAC输出对应的电流。

int main(void)
{
    char str[20];
    int val;
    float pressure; 
    delay_init();
    uart_init(9600); 
    HX711_Init();
    LCD1602_Init();
    TLC5615_Init();
    LED_KEY_BUZZ_Init(); 
    while(1)
    {
        HX711_data[HX711_dataIndex] = HX711_Read()>>5;//读取AD数据 舍弃低5位
        HX711_dataIndex ++;
        if(HX711_dataIndex >= HX711_DATA_SIZE)
            HX711_dataIndex = 0;
        val = getAverage(HX711_data,HX711_DATA_SIZE);//将最近的8次数据平均 提高稳定性
        pressure = getPressure(val);//根据公式拟合气压值
        sprintf(str,"%6.3fMPa",pressure);
        LCD1602_ShowStr(0,3,str);//使用LCD屏幕就地显示
        memcpy(modbusData+3,(void*)&pressure,4);//ModBus总线数据
        transmitterOutput(pressure,1);//使用DAC输出电流 参数为当前压力值与最大压力值
    }
}

下面的代码主要包括了对数据进行平均值处理和根据ADC读数拟合气压值的函数。

#define HX711_DATA_SIZE 8
int32_t HX711_data[HX711_DATA_SIZE];
uint8_t HX711_dataIndex = 0;
void transmitterOutput(float outData,float maxData)
{
    float ma = 4 + outData / maxData * (20-4);//换算变送器数值
    
    TLC5615_Update(ma/20*1023);//将4-20ma换算为电压值
}
int32_t getAverage(int32_t* dat,uint8_t num)
{
    uint8_t i;
    int32_t sum = 0; 
    for(i = 0;i < num;i ++)
    {
        sum += dat[i];
    } 
    return sum / num;
}
double getPressure(double x)//根据公式拟合气压值
{
    return
        0.00000000000000000116 * pow(x,3)
        - 0.00000000000000750175 * pow(x,2)
        + 0.00000770572583981333 * pow(x,1)
        - 0.00105882952018538000 * pow(x,0);
}

实验结果

测试现场布置如下图。

https://img.yuanze.wang/posts/stm32-pressure-transmitter/test-env.jpg
测试现场实拍图

下图中展示了电路板的各个模块。引出了用于连接压力传感器全桥的4个引脚和4-20mA电流输出的2个引脚。左下部是LCD1602显示模块,中间为STM32最小系统、TCL5615模块、HX711模块和XTR115模块。

https://img.yuanze.wang/posts/stm32-pressure-transmitter/pcb.jpg
电路板硬件

下图为校验现场的实测压力。可以看到上图中的就地显示值与下图中标准表的显示几乎一致,且对应的4-20mA输出值换算至压力的误差也很低。

https://img.yuanze.wang/posts/stm32-pressure-transmitter/pressure-test.jpg
标准表示数与电流表示数

与此同时,上位机软件通过RS485总线与变送器通信,可以实时获取当前压力值并显示在屏幕上,并绘制成曲线图。

https://img.yuanze.wang/posts/stm32-pressure-transmitter/modbus-viewer.png
上位机软件曲线显示

 上位机软件源码

 单片机程序工程

 高清原理图