2. 压力传感器数据采集:压阻式与电容式压力传感器原理、模拟前端电路设计、I2C/SPI接口读取数据实战(以MS5611为例)

2.1 压阻式与电容式压力传感器原理

在呼吸机中,压力传感器用于监测气道压力(Paw)、呼气末正压(PEEP)以及患者触发呼吸的负压信号。根据应用场景的不同,主要采用压阻式和电容式两种原理。

2.1.1 压阻式压力传感器

工作原理:基于半导体材料的压阻效应。当压力作用于硅膜片时,膜片发生形变,导致扩散在其上的电阻值发生变化。通常采用惠斯通电桥结构,将电阻变化转换为差分电压输出。

  • 优点:灵敏度高、线性度好、响应速度快(适合高频呼吸监测)、易于集成温度补偿。
  • 缺点:对温度敏感(需温度补偿)、长期稳定性略逊于电容式。
  • 典型应用:呼吸机吸气/呼气压力传感器、气道阻塞检测。

2.1.2 电容式压力传感器

工作原理:利用平行板电容原理。压力改变极板间距或相对面积,导致电容值变化。通过电容-电压转换电路(如C-V转换器或Σ-Δ调制器)输出数字信号。

  • 优点:功耗极低、温度稳定性好、无迟滞效应、适合低功耗便携设备。
  • 缺点:寄生电容敏感、需要复杂的检测电路、响应速度相对较慢。
  • 典型应用:便携式呼吸机、长期监测的PEEP传感器。
特性压阻式电容式
灵敏度中等
温度稳定性需补偿
响应时间μs级ms级
功耗mA级μA级
典型接口模拟差分输出数字(I2C/SPI)

2.2 模拟前端电路设计

无论哪种传感器,模拟前端(AFE)的设计都直接影响信噪比和测量精度。以下以压阻式传感器为例,给出关键电路设计要点。

2.2.1 仪表放大器与差分信号调理

压阻式传感器输出为mV级差分信号,需使用高共模抑制比(CMRR)的仪表放大器(如AD8226、INA333)。

// 电路设计要点(伪代码描述)
1. 激励电压:恒压源(2.5V或5V)或恒流源驱动电桥。
2. 差分输入:传感器输出接仪表放大器正负输入端。
3. 增益设置:通过外部电阻Rg设置增益G = 1 + (49.4kΩ / Rg)。
   例如:Rg = 1kΩ → G ≈ 50.4,将±20mV信号放大至±1V。
4. 低通滤波:在仪表放大器输出端加一阶RC低通(fc = 1/(2πRC)),
   截止频率设为呼吸频率的10倍(如50Hz)。
5. 偏置调整:使用精密基准电压源(如REF3025)将信号偏置到ADC输入范围中心。

2.2.2 抗混叠滤波器设计

在ADC采样前必须设置抗混叠滤波器。对于呼吸机压力信号(带宽通常0.1~40Hz),建议使用二阶有源低通滤波器(如Sallen-Key结构),截止频率设为100Hz,阻带衰减>40dB@1kHz。

2.2.3 电容式传感器的C-V转换

电容式传感器通常集成在数字芯片内部(如MS5611),外部只需提供去耦电容和电源。若使用分立电容传感器,需采用开关电容电路或交流激励法,此处不展开。

2.3 I2C/SPI接口读取数据实战(以MS5611为例)

MS5611是一款高精度压阻式压力传感器,内部集成温度传感器和24位Σ-Δ ADC,支持I2C和SPI接口。其典型量程为10~1200mbar,分辨率可达0.012mbar(约0.12cmH₂O),非常适合呼吸机气道压力监测。

2.3.1 硬件连接

  • I2C模式:CSB接VDD(高电平),PS接VDD(I2C使能),SDA/SCL接MCU对应引脚。
  • SPI模式:CSB接片选,PS接GND(低电平),SDI/SDO/SCLK接SPI总线。
  • 电源:VDD 3.3V,VBUS可悬空,需在VDD与GND间加100nF+10μF去耦电容。

2.3.2 通信协议与命令

MS5611的通信基于以下关键命令(以I2C为例,7位地址0x76或0x77):

命令(十六进制)功能说明
0x1E复位复位传感器,需等待2.8ms
0xA0~0xAE读取PROM读取6个校准系数(每系数16位)
0x48启动压力转换(OSR=4096)转换时间约8.22ms
0x58启动温度转换(OSR=4096)转换时间约8.22ms
0x00读取ADC结果返回24位压力或温度值

2.3.3 Python实战代码(基于Raspberry Pi / Linux嵌入式平台)

以下代码使用smbus2库通过I2C读取MS5611,并进行温度补偿计算,输出实际压力值(单位:mbar)。

import smbus2
import time

# MS5611 I2C地址(默认0x76,若CSB接地则为0x77)
MS5611_ADDR = 0x76

# 命令定义
CMD_RESET = 0x1E
CMD_ADC_READ = 0x00
CMD_PROM_BASE = 0xA0
CMD_CONV_D1_4096 = 0x48  # 压力转换,OSR=4096
CMD_CONV_D2_4096 = 0x58  # 温度转换,OSR=4096

class MS5611:
    def __init__(self, bus=1):
        self.bus = smbus2.SMBus(bus)
        self.C = [0] * 7  # 校准系数数组
        self._init_sensor()

    def _init_sensor(self):
        # 复位传感器
        self.bus.write_byte(MS5611_ADDR, CMD_RESET)
        time.sleep(0.003)  # 等待2.8ms
        # 读取PROM中的6个校准系数(C1~C6)
        for i in range(1, 7):
            data = self.bus.read_i2c_block_data(MS5611_ADDR, CMD_PROM_BASE + i*2, 2)
            self.C[i] = (data[0] << 8) | data[1]
        # 校验CRC(可选,此处省略)

    def _read_adc(self):
        """读取24位ADC结果"""
        data = self.bus.read_i2c_block_data(MS5611_ADDR, CMD_ADC_READ, 3)
        return (data[0] << 16) | (data[1] << 8) | data[2]

    def read_pressure(self):
        """返回补偿后的压力值(单位:mbar)"""
        # 启动压力转换
        self.bus.write_byte(MS5611_ADDR, CMD_CONV_D1_4096)
        time.sleep(0.009)  # 等待转换完成
        D1 = self._read_adc()

        # 启动温度转换
        self.bus.write_byte(MS5611_ADDR, CMD_CONV_D2_4096)
        time.sleep(0.009)
        D2 = self._read_adc()

        # 温度补偿计算(参考MS5611 datasheet公式)
        dT = D2 - (self.C[5] << 8)
        TEMP = 2000 + (dT * self.C[6]) >> 23  # 温度值,单位0.01°C

        # 二阶温度补偿(针对低温/高温)
        if TEMP < 2000:
            T2 = (dT * dT) >> 31
            OFF2 = 5 * ((TEMP - 2000) ** 2) >> 1
            SENS2 = 5 * ((TEMP - 2000) ** 2) >> 2
        else:
            T2 = 0
            OFF2 = 0
            SENS2 = 0

        OFF = (self.C[2] << 16) + (self.C[4] * dT >> 7) - OFF2
        SENS = (self.C[1] << 15) + (self.C[3] * dT >> 8) - SENS2

        # 计算压力
        P = (D1 * SENS >> 21) - OFF
        pressure = P >> 15  # 单位:mbar
        return pressure / 100.0  # 转换为mbar(或hPa)

if __name__ == "__main__":
    sensor = MS5611()
    while True:
        pressure = sensor.read_pressure()
        print(f"Pressure: {pressure:.2f} mbar")
        time.sleep(0.1)  # 10Hz采样率

2.3.4 数据滤波与校准

原始压力数据存在噪声,需进行数字滤波。推荐在嵌入式端使用滑动平均滤波或一阶低通滤波(α=0.1~0.3)。

# 一阶低通滤波示例(在读取循环中调用)
alpha = 0.2
filtered_pressure = 0.0

while True:
    raw = sensor.read_pressure()
    filtered_pressure = alpha * raw + (1 - alpha) * filtered_pressure
    print(f"Filtered: {filtered_pressure:.2f} mbar")
    time.sleep(0.01)  # 100Hz采样

校准建议:在呼吸机出厂前,使用标准压力源(如水柱压力计)进行两点校准,修正传感器的零点和增益误差。将校准系数存入EEPROM,每次上电时加载。

2.4 实战注意事项

  • 电源噪声:传感器模拟部分与数字部分需隔离,使用LDO供电,避免开关电源纹波。
  • 采样率选择:呼吸机压力信号带宽通常为0.1~40Hz,建议采样率≥200Hz(满足奈奎斯特并留有余量)。
  • 温度补偿:MS5611内部已提供温度补偿算法,但若环境温度变化剧烈(如从冷启动到工作状态),建议增加外部温度传感器进行二次补偿。
  • 接口时序:I2C模式下,时钟频率不超过400kHz;SPI模式下,时钟频率不超过20MHz。注意上拉电阻(I2C需4.7kΩ)。

通过以上内容,学员应能掌握压阻式与电容式压力传感器的选型依据、模拟前端设计要点,并独立完成基于MS5611的I2C/SPI数据采集与滤波程序。下一节将结合呼吸机气道压力波形,讲解实时滤波算法与异常检测。