第四章:信号处理基础——拉曼散射信号的提取与去噪
各位同学,欢迎来到信号处理这一章。说实话,很多做光纤测温的朋友,硬件搭得漂漂亮亮,最后卡在信号处理上。我当年第一次搭DTS系统时,看着示波器上那堆毛刺,差点以为传感器坏了。后来才明白——信号处理,才是决定系统精度的关键。
4.1 拉曼散射信号的Stokes与Anti-Stokes提取
先说说最基础的事。拉曼散射光里,有两个关键成分:Stokes光和Anti-Stokes光。Stokes光波长比入射光长,Anti-Stokes光波长比入射光短。温度信息,就藏在它们的强度比里。
怎么提取呢?我习惯用带通滤波器加解调的方式。具体来说,分三步:
- 光电转换:APD或PMT把光信号变成电信号
- 带通滤波:分别提取Stokes和Anti-Stokes对应的频率成分
- 同步解调:用参考信号做相敏检测,把有用信号从噪声里捞出来
这里有个坑——两个通道的增益必须匹配。我曾经因为APD偏压没调好,Stokes通道增益比Anti-Stokes高了3dB,算出来的温度直接偏了5度。嗯,后来我加了个自动增益校准环节,每10分钟自检一次。
核心公式:温度T与拉曼强度比R的关系
R = (I_Anti / I_Stokes) ∝ exp(-hΔν / kT)
其中h是普朗克常数,Δν是拉曼频移,k是玻尔兹曼常数。说白了,测出强度比,就能反推出温度。
4.2 累加平均去噪算法
单次采集的信号,信噪比通常很差。你想想看,拉曼散射本身就很弱,再加上APD的暗电流噪声、放大器的热噪声……信号经常淹没在噪声里。
怎么办?累加平均。这是最朴素也最有效的办法。
原理很简单:噪声是随机的,均值趋近于零。信号是确定的,累加后线性增长。累加N次,信噪比提升√N倍。
// 累加平均伪代码
#define N 1000 // 累加次数
double sum_stokes[1024] = {0};
double sum_anti[1024] = {0};
for (int i = 0; i < N; i++) {
acquire_frame(stokes, anti); // 采集一帧
for (int j = 0; j < 1024; j++) {
sum_stokes[j] += stokes[j];
sum_anti[j] += anti[j];
}
}
// 取平均
for (int j = 0; j < 1024; j++) {
avg_stokes[j] = sum_stokes[j] / N;
avg_anti[j] = sum_anti[j] / N;
}
我的经验:N不是越大越好。N=1000时,信噪比提升约31倍,但采集时间也长了1000倍。对于静态测温,N取500-2000合适。对于动态测温(比如监测电缆发热),N取100-200就够了,否则跟不上温度变化。
4.3 滑动平均滤波
累加平均做完后,信号还是会有一些毛刺。这时候就该滑动平均上场了。
滑动平均,说白了就是取一个窗口,窗口内的数据求平均,然后窗口滑动。窗口宽度m越大,平滑效果越好,但空间分辨率会下降。
// 滑动平均实现
void moving_average(double *input, double *output, int len, int window) {
int half = window / 2;
for (int i = 0; i < len; i++) {
double sum = 0;
int count = 0;
for (int j = i - half; j <= i + half; j++) {
if (j >= 0 && j < len) {
sum += input[j];
count++;
}
}
output[i] = sum / count;
}
}
窗口宽度怎么选?我一般这样定:
| 应用场景 | 窗口宽度(采样点) | 空间分辨率损失 |
|---|---|---|
| 短距离测温(<1km) | 3-5 | 0.5-1m |
| 中距离测温(1-5km) | 7-15 | 1-3m |
| 长距离测温(>5km) | 15-31 | 3-6m |
注意:滑动平均会模糊温度突变点。比如电缆上有个局部热点,窗口太宽会把热点抹平。我曾经吃过这个亏——客户说测温不准,查了半天,原来是滑动窗口设了31点,把5米长的热点给平均成温升只有实际的一半。
4.4 差分衰减补偿
光纤是有损耗的。光在光纤里传播,距离越长,信号越弱。Stokes和Anti-Stokes的衰减系数还不一样,这就导致远端温度计算出现偏差。
差分衰减补偿,就是把这个偏差纠正回来。
具体做法:
- 先测量光纤的衰减曲线(用OTDR原理)
- 分别得到Stokes和Anti-Stokes的衰减系数α_s和α_a
- 对每个距离点的信号做补偿:
// 差分衰减补偿
double compensate(double raw_signal, double distance, double alpha) {
// alpha单位:dB/km,distance单位:km
double loss = alpha * distance; // 总衰减dB
double gain = pow(10, loss / 10); // 转为线性增益
return raw_signal * gain;
}
// 实际使用时,对Stokes和Anti-Stokes分别补偿
double comp_stokes = compensate(raw_stokes, dist, alpha_stokes);
double comp_anti = compensate(raw_anti, dist, alpha_anti);
关键点:补偿后的强度比R_comp = comp_anti / comp_stokes,这个比值才真正反映温度。如果不做补偿,远端温度会显示偏高——因为Anti-Stokes衰减更快,比值虚高。
我记得有一次在现场调试,30公里长的光纤,远端温度显示比实际高了8度。排查了半天,发现是光纤弯曲处衰减异常,补偿系数没跟上。后来我加了个自适应衰减追踪算法,每隔1公里重新校准一次衰减系数,问题就解决了。
知识体系总览
下面这张图,把本章的核心逻辑串起来了:
这张图把整个信号处理链路画清楚了。从光信号进来,到温度曲线出去,中间每一步都有讲究。你想想看,任何一个环节没做好,最终温度都可能差好几度。
好了,这一章的内容就这些。信号处理是个熟能生巧的活,多调参数、多看波形,慢慢就有感觉了。