就像 P&ID 是气路的宪法一样,在信号处理领域,也有一个铁打的“五层金字塔”框架。我们将这个框架称为 “信号净化提纯流水线” 。
第一层:物理获取层 —— “原矿开采”
这一层负责把物理世界变成数字世界。核心原则是“保真”**。
- 输入: 光子、离子、电子(模拟量)。
- 动作:
- IV 转换 (TIA): 把微弱电流变成电压(前放板的任务)。
- 量程匹配 (Auto-Ranging): 如果信号太小,放大 100 倍;太大,放大 1 倍。确保 ADC 能吃饱,但不撑死。
- 过采样 (Oversampling): 比如 ADC 是 1000Hz 采样的,我采 100 个点只取 1 个平均值。这能物理提升 ADC 的信噪比(每 4 倍过采样,增加 1 位分辨率)。
- 输出: Raw Counts (原始码值)。
- 特征: 这通常是一个 0~65535 的整数,甚至可能是负数,没有任何物理单位,充满噪声。
第二层:清洗滤波层 —— “洗去泥沙”
这一层负责把噪声(Noise)去掉,留下信号(Signal)。核心原则是“时域与频域的结合”。
- 输入: 充满毛刺的 Raw Counts。
- 核心算法:
- 锁相放大 (PSD): (针对 NDIR/GFC)剔除所有非 30Hz 的光干扰。
- 剔除脉冲噪声 (Spike Rejection): 如果突然有一个点飞到了天上去(可能是静电干扰),直接删掉,不算。
- 滑动平均 / 卡尔曼滤波: 根据当前的工况(稳态还是突变),平滑数据。
- 输出: Filtered Voltage (纯净电压)。
- 特征:这是一个很稳的电压值(如 2.500V),但它还不是浓度。
第三层:物理修正层 —— “化学反应”
这是最体现仪器技术含量的部分。我们要用数学公式去修补物理传感器的缺陷。顺序绝对不能乱!
- 输入: Filtered Voltage。
- 步骤顺序(黄金法则):
- 零点扣除 (Zero Subtraction): 先减去“暗电流”或“零点背景”。$$V_{net} = V_{meas} - V_{zero}$$
- 线性化 (Linearization): 把弯曲的电压拉直。$$C_{raw} = f(V_{net})$$
- 温压补偿 (P/T Comp): 理想气体状态方程修正。$$C_{std} = C_{raw} \times \frac{101.3}{P_{cur}} \times \frac{T_{cur}}{273}$$
- 交叉干扰补偿 (Cross-Interference): 扣除水和 CO2 的影响。$$C_{final} = C_{std} - (K \times C_{H2O})$$
- 输出: Physics Concentration (物理浓度)。
- 特征:此时已经是 ppm 或 mg/m³ 了,是真实的物理值。
第四层:逻辑裁决层 —— “盖章认证”
这一层不处理数值大小,只处理“数据身份”。结合我们讲的状态机。
- 输入: 物理浓度 + 系统状态(测量/校准/故障)。
- 动作:
- 有效性判断: 现在的状态机是在 MEASURE 吗?
- 如果是 CAL (校准) $\rightarrow$ 标记为 Calibration,数值照发(供调试看),但环保局不统计。
- 如果是 FAULT (故障) $\rightarrow$ 标记为 Invalid,数值可能强制归零或保持。
- 如果是 PURGE (反吹) $\rightarrow$ 标记为 Hold,数值锁定在反吹前一刻。
- 上下限报警: 是否超过量程?是否低于 -5%(仪表漂移异常)?
- 有效性判断: 现在的状态机是在 MEASURE 吗?
- 输出: Display Value (显示值) + Status Flag (状态旗)。
五层:输出格式层 —— “打包发货”
这一层负责把数据翻译成别人(PLC、DCS)能听懂的语言。
- 输入: 显示值 + 状态旗。
- 动作:
- D/A 转换: 把 0
100 ppm 映射到 4.0020.00 mA。- 注意:如果状态是 Invalid,可能输出 2 mA (故障电流) 告诉 DCS。
- 协议打包: 放入 Modbus 寄存器(40001 = 浓度,40002 = 状态)。
- 统计存储: 存入硬盘,生成“分钟均值”、“小时均值”。
- D/A 转换: 把 0
框架中的三个“反直觉”经验
- 先线性化,再做补偿:
- 一定要先用多项式把电压变成浓度(线性化),然后再去减干扰气体的浓度。
- 错误做法:在电压阶段就减去干扰信号。这是错的,因为电压是非线性的,不能直接加减。
- 滤波放在线性化之前:
- 一定要在电压阶段(L2)把噪声滤干净,再进公式(L3)。
- 原因:线性化公式通常是高次方程($V^3, V^4$)。如果电压里有噪声,经过 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