信号处理的设计原则

就像 P&ID 是气路的宪法一样,在信号处理领域,也有一个铁打的“五层金字塔”框架。我们将这个框架称为 “信号净化提纯流水线” 。

第一层:物理获取层 —— “原矿开采”

这一层负责把物理世界变成数字世界。核心原则是“保真”**。

  • 输入: 光子、离子、电子(模拟量)。
  • 动作:
    1. IV 转换 (TIA): 把微弱电流变成电压(前放板的任务)。
    2. 量程匹配 (Auto-Ranging): 如果信号太小,放大 100 倍;太大,放大 1 倍。确保 ADC 能吃饱,但不撑死。
    3. 过采样 (Oversampling): 比如 ADC 是 1000Hz 采样的,我采 100 个点只取 1 个平均值。这能物理提升 ADC 的信噪比(每 4 倍过采样,增加 1 位分辨率)。
  • 输出: Raw Counts (原始码值)。
    • 特征: 这通常是一个 0~65535 的整数,甚至可能是负数,没有任何物理单位,充满噪声。

第二层:清洗滤波层 —— “洗去泥沙”

这一层负责把噪声(Noise)去掉,留下信号(Signal)。核心原则是“时域与频域的结合”

  • 输入: 充满毛刺的 Raw Counts。
  • 核心算法:
    1. 锁相放大 (PSD): (针对 NDIR/GFC)剔除所有非 30Hz 的光干扰。
    2. 剔除脉冲噪声 (Spike Rejection): 如果突然有一个点飞到了天上去(可能是静电干扰),直接删掉,不算。
    3. 滑动平均 / 卡尔曼滤波: 根据当前的工况(稳态还是突变),平滑数据。
  • 输出: Filtered Voltage (纯净电压)。
    • 特征:这是一个很稳的电压值(如 2.500V),但它还不是浓度。

第三层:物理修正层 —— “化学反应”

这是最体现仪器技术含量的部分。我们要用数学公式去修补物理传感器的缺陷。顺序绝对不能乱!

  • 输入: Filtered Voltage。
  • 步骤顺序(黄金法则):
    1. 零点扣除 (Zero Subtraction): 先减去“暗电流”或“零点背景”。$$V_{net} = V_{meas} - V_{zero}$$
    2. 线性化 (Linearization): 把弯曲的电压拉直。$$C_{raw} = f(V_{net})$$
    3. 温压补偿 (P/T Comp): 理想气体状态方程修正。$$C_{std} = C_{raw} \times \frac{101.3}{P_{cur}} \times \frac{T_{cur}}{273}$$
    4. 交叉干扰补偿 (Cross-Interference): 扣除水和 CO2 的影响。$$C_{final} = C_{std} - (K \times C_{H2O})$$
  • 输出: Physics Concentration (物理浓度)。
    • 特征:此时已经是 ppm 或 mg/m³ 了,是真实的物理值。

第四层:逻辑裁决层 —— “盖章认证”

这一层不处理数值大小,只处理“数据身份”。结合我们讲的状态机。

  • 输入: 物理浓度 + 系统状态(测量/校准/故障)。
  • 动作:
    1. 有效性判断: 现在的状态机是在 MEASURE 吗?
      • 如果是 CAL (校准) $\rightarrow$ 标记为 Calibration,数值照发(供调试看),但环保局不统计。
      • 如果是 FAULT (故障) $\rightarrow$ 标记为 Invalid,数值可能强制归零或保持。
      • 如果是 PURGE (反吹) $\rightarrow$ 标记为 Hold,数值锁定在反吹前一刻。
    2. 上下限报警: 是否超过量程?是否低于 -5%(仪表漂移异常)?
  • 输出: Display Value (显示值) + Status Flag (状态旗)。

五层:输出格式层 —— “打包发货”

这一层负责把数据翻译成别人(PLC、DCS)能听懂的语言。

  • 输入: 显示值 + 状态旗。
  • 动作:
    1. D/A 转换: 把 0100 ppm 映射到 4.0020.00 mA。
      • 注意:如果状态是 Invalid,可能输出 2 mA (故障电流) 告诉 DCS。
    2. 协议打包: 放入 Modbus 寄存器(40001 = 浓度,40002 = 状态)。
    3. 统计存储: 存入硬盘,生成“分钟均值”、“小时均值”。

框架中的三个“反直觉”经验

  1. 先线性化,再做补偿:
    • 一定要先用多项式把电压变成浓度(线性化),然后再去减干扰气体的浓度。
    • 错误做法:在电压阶段就减去干扰信号。这是错的,因为电压是非线性的,不能直接加减。
  2. 滤波放在线性化之前:
    • 一定要在电压阶段(L2)把噪声滤干净,再进公式(L3)。
    • 原因:线性化公式通常是高次方程($V^3, V^4$)。如果电压里有噪声,经过 3 次方放大,噪声会变成巨大的误差。
  3. 显示值 $\neq$ 4-20mA 值:**
    • 在 L5 层,屏幕显示通常为了好看,会保留 2 位小数。
    • 但给 DAC(4-20mA)的数据,必须经过量程缩放
    • 坑点:很多时候屏幕显示 50.00,但后台 DAC 芯片只有 12 位精度,输出可能是 49.8。调试时要区分“显示层”和“硬件输出层”。

Mermaid 信号流转框架图

graph TD %% 样式定义 classDef physical fill:#e1f5fe,stroke:#01579b,stroke-width:2px; classDef clean fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px; classDef math fill:#fff9c4,stroke:#fbc02d,stroke-width:2px; classDef logic fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px; classDef output fill:#ffebee,stroke:#c62828,stroke-width:2px; %% 1. 物理层 subgraph L1 ["第一层:物理获取 (Acquisition)"] Sens(("传感器")) --> TIA["前置放大 TIA"] TIA --> ADC["ADC 模数转换"] ADC --> |"Raw Counts (原始码)"| OS["过采样/均值"] end class Sens,TIA,ADC,OS physical %% 2. 清洗层 subgraph L2 ["第二层:清洗滤波 (Cleaning)"] OS --> PSD["锁相放大/解调"] PSD --> SPIKE["剔除脉冲噪声"] SPIKE --> FILTER["自适应滤波/卡尔曼"] FILTER --> |"Filtered Voltage (净电压)"| NEXT2 end class PSD,SPIKE,FILTER clean %% 3. 修正层 subgraph L3 ["第三层:物理修正 (Correction)"] NEXT2(("V")) --> ZERO_SUB["减零点背景"] ZERO_SUB --> LIN["多项式线性化"] LIN --> PT_COMP["温度/压力补偿"] PT_COMP --> INTER_COMP["交叉干扰补偿"] INTER_COMP --> |"Physics Conc. (真浓度)"| NEXT3 end class ZERO_SUB,LIN,PT_COMP,INTER_COMP math %% 4. 逻辑层 subgraph L4 ["第四层:逻辑裁决 (Logic)"] NEXT3(("C")) --> STATE_CHECK{"状态机检查"} STATE_Check_Logic --> STATE_CHECK STATE_CHECK --"正常测量"--> VALID["标记: Valid"] STATE_CHECK --"反吹/校准"--> HOLD["标记: Hold/Cal"] STATE_CHECK --"硬件报错"--> FAULT["标记: Invalid"] end class STATE_CHECK,VALID,HOLD,FAULT logic %% 5. 输出层 subgraph L5 ["第五层:输出格式 (Output)"] VALID --> DAC["4-20mA 输出"] HOLD --> DAC FAULT --> DAC VALID --> MODBUS["Modbus/RS485"] VALID --> LOG["历史数据存储"] end class DAC,MODBUS,LOG output %% 外部输入 STATE_Check_Logic["系统状态机"] -.-> STATE_CHECK
Licensed under CC BY-NC-SA 4.0