多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

光纤干涉传感PGC-DCM解调原理与MATLAB仿真实现

光纤干涉传感PGC-DCM解调原理与MATLAB仿真实现 简介基于PGC相位生成载波调制与微分交叉相乘DCM解调算法的MATLAB实现资源面向光纤传感、干涉测量及信号处理方向的工程师、研究生与科研人员适用于需要对相位载波信号进行高精度解调的场景。压缩包共含3个文件以M脚本为主分别实现微分交叉相乘解调主流程与低通滤波器功能另附一份PDF文档系统总结滤波器设计原理与参数选择依据便于读者在理解算法细节后自行修改参数或扩展功能。代码结构清晰、注释明确可直接运行也能作为核心逻辑迁移到实际项目中。资源包整体约382KB轻量紧凑下载与使用门槛低。目前已有2257人学习下载是入门PGC-DCM算法、搭建仿真验证环境及开展相关课题研究的实用参考资料适合具备一定MATLAB基础、希望快速掌握PGC解调流程的读者。 做光纤干涉传感的朋友对PGC这个词应该不会陌生。相位生成载波Phase Generated Carrier, PGC是干涉型光纤传感器中最常用的信号解调方案之一而微分交叉相乘Differentially Cross-Multiplying, DCM则是PGC解调里最经典、最容易上手的一种算法。这次分享的MATLAB代码就围绕这一主题从干涉信号的生成、PGC调制到DCM解调链路的完整仿真实现适合正在做光纤水听器、光纤振动传感、加速度计或者相关课题的研究生和工程师直接参考使用。这篇文章会把代码背后的原理讲透把每一步为什么这么做说清楚并且附上我在调试过程中踩过的坑和总结的参数选择经验。如果你刚开始接触PGC解调拿这套仿真作为起点非常合适。1. 项目背景与算法选型思路1.1 干涉型光纤传感器的“相位模糊”问题干涉型光纤传感器的基本原理是外界待测信号作用于传感光纤改变光程差进而改变干涉光的相位。光强与相位之间是一个余弦关系即输出光强可以写成I A Bcos(φ)的形式。问题就出在这个余弦函数上余弦是偶函数cos(φ)和cos(-φ)完全一样所以仅凭干涉光强你无法判断相位究竟是变大还是变小这就是所谓的“相位模糊”问题。另外环境温度、气压等缓慢变化会引起大量低频相位漂移这些干扰幅度往往远大于待测信号如果直接对余弦输出做处理根本没法把有效信号和干扰分开。PGC方案的核心思想是主动在干涉仪中引入一个高频载波调制把这个低频段的待测相位信号“搬到”高频载波的边带上然后再利用算法把相位信息从载波中解调出来。这样既解决了相位模糊也能通过后续的滤波处理将低频环境干扰和有效信号区分开。在实际系统中调制通常是通过PZT压电陶瓷拉伸参考臂光纤或者直接调制激光器频率来实现的。1.2 为什么选择DCM而不是PGC-ArctanPGC解调的常用算法主要有两种DCM微分交叉相乘和Arctan反正切。这套代码选择DCM是因为它在工程上对载波调制深度的要求更宽松。先解释一下“调制深度”C这个概念C是由加载在PZT上的驱动信号幅度和PZT本身的灵敏度共同决定的单位是rad。实际硬件工作一段时间后PZT的响应特性会发生漂移C很难精确稳定在一个设定值。Arctan算法为了消除Bessel函数项的干扰通常希望C稳定在2.63 rad附近否则解调结果会出现明显的非线性失真。而DCM算法的最终输出幅度与贝塞尔函数乘积J1(C)·J2(C)成正比只要C不落在贝塞尔函数的零点附近即使C偏离设计值影响的只是增益大小波形形状基本不变大不了后期做一次幅度标定。两种算法的核心差异大概这样对比对比维度PGC-DCMPGC-Arctan核心运算混频、低通、微分、交叉相乘、积分混频、低通、正交分量相除、反正切对调制深度C的依赖避开贝塞尔零点即可宽容度高最好精确保持C≈2.63 rad对光强波动B变化的敏感性增益与B²有关受光强波动影响通过反正切比值自动抵消B的影响相位测量范围原则上没有周期限制需要保证相位在(-π/2, π/2)主值范围内噪声特性微分运算会放大高频噪声对噪声的抑制相对平滑实现难度流程简单易调试需要处理相位跳变与展开问题从实际工程角度看DCM更适合作为第一版验证方案先跑通链路再根据需求做算法升级。2. PGC调制与DCM解调的数学原理2.1 干涉信号的Bessel展开理解DCM解调关键是把干涉信号的数学表达式搞明白。经过PGC调制后的干涉仪输出可以写成I(t) A B·cos[C·cos(ω₀t) φ(t)]其中A是直流光强分量B是干涉条纹可见度决定的幅度ω₀是载波角频率φ(t)D·sin(ωₛt)ψ(t)包含待测信号和低频环境噪声。这个式子直接用是没法解调的必须利用Bessel函数展开cos[C·cos(ω₀t) φ] 展开后将会在基频ω₀处产生与sinφ成正比的J1(C)分量在二倍频2ω₀处产生与cosφ成正比的J2(C)分量。这正是DCM解调的数学基础。J1(C)和J2(C)是第一类和第二类Bessel函数这两个系数决定了最终解调信号的增益大小。要注意的是Bessel函数不是单调函数J1和J2各自有一系列零点比如J1的零点出现在3.83、7.02附近J2的零点出现在5.14、8.42附近后面选参数时要刻意避开这些点。2.2 DCM解调的完整推导DCM解调流程可以分解成五步混频、低通滤波、微分、交叉相乘相减、积分。我按步骤推一遍这样你在看代码的时候就能对上号。第一步将干涉信号I(t)分别与载波cos(ω₀t)和二倍频载波cos(2ω₀t)相乘I(t)·cos(ω₀t)经低通滤波后得到S1 -B·J1(C)·sinφ(t)I(t)·cos(2ω₀t)经低通滤波后得到S2 -B·J2(C)·cosφ(t)低通滤波器的作用是滤掉混频产生的3ω₀、4ω₀等高频分量只保留差频后落到基带的项。S1和S2实际上就是把φ的sin和cos分量分别“提取”出来了这是一对正交信号。第二步分别对S1和S2做微分dS1/dt -B·J1(C)·cosφ·(dφ/dt)dS2/dt B·J2(C)·sinφ·(dφ/dt)微分结果中出现了dφ/dt说明解调链路最终恢复的是相位变化率这也是DCM算法名称里“微分”二字的来源。第三步交叉相乘并相减S1·(dS2/dt) - S2·(dS1/dt) -B²·J1(C)·J2(C)·(dφ/dt)展开后你会发现sin²φ cos²φ 1相位φ本身被抵消了剩下的只与dφ/dt成正比。这一步是整个算法的精髓它巧妙地消除了正交信号中剩余的相位依赖项输出不再受φ具体值的影响。第四步对上述结果做积分φ_out(t) -B²·J1(C)·J2(C)·φ(t)积分之后dφ/dt变回了φ(t)但直流分量和极低频环境噪声也会被积分后的常数项带进来所以最后还需要加一个高通滤波器把直流漂移和低频干扰去掉得到的就是与待测相位信号成比例的解调输出。从推导也可以看出DCM的输出幅度正比于B²·J1(C)·J2(C)这个系数就是系统的整体增益。在仿真里我们用的是归一化光强B1但在实际系统中B会受到光功率波动影响这是后续工程化时要特别注意的点。3. MATLAB仿真实现与关键代码3.1 仿真参数设置仿真参数的选择要符合实际物理场景。比如载波频率必须远高于信号频率否则边带会发生混叠采样率又要远高于载波频率满足奈奎斯特采样定理。我常用的默认参数如下参数数值说明采样率 fs5 MHz载波频率的25倍留足滤波余量载波频率 fc200 kHzPGC高频载波信号频率 fsig5 kHz待测信号远低于载波信号幅度 D0.5 rad典型小信号调制深度 C2.63 radJ1≈J2附近增益较均衡低通截止频率30 kHz滤除混频高频保留5kHz信号高通截止频率100 Hz去除环境低频干扰仿真时长10 ms包含500个信号周期便于频谱分析这里特别说明一下为什么低通截止频率取30 kHz它必须高于待测信号最高频率5kHz同时又远低于载波频率200kHz这样混频后的高频分量才能被彻底滤除。如果用截止频率太高的低通滤波器混频分量滤不干净解调输出会带有明显的载波泄漏锯齿如果截止频率太低信号本身会被衰减得不偿失。3.2 PGC干涉信号生成生成干涉信号的MATLAB代码很简洁本质就是在复现公式I(t) A B·cos[C·cos(ω₀t) φ(t)]fs 5e6; T 0.01; t (0:round(T*fs)-1)/fs; fc 200e3; fsig 5e3; C 2.63; D 0.5; A 1; B 1; % 待测相位 phi D * sin(2*pi*fsig*t); % 低频环境干扰 phi_env 0.8 * sin(2*pi*30*t); phi phi phi_env; % PGC调制后的干涉信号 carrier C * cos(2*pi*fc*t); I A B * cos(carrier phi);这里我把环境干扰也加进去了频率设为30 Hz、幅度0.8 rad模拟实际系统中温度、振动等慢变干扰。如果不加这个解调链路里的高通滤波器作用就不明显和真实场景差距比较大。注意环境幅度比信号大解调后必须靠高通滤波把它滤掉这也能直观验证算法的抗干扰能力。3.3 DCM解调链路实现完整的DCM解调链路代码大约分为六个环节我按顺序拆开讲解% 第一步低通滤波器设计4阶巴特沃斯 [b_lpf, a_lpf] butter(4, 30e3/(fs/2), low); % 第二步混频 s1_raw I .* cos(2*pi*fc*t); s2_raw I .* cos(2*2*pi*fc*t); % 第三步低通滤波去除高频混频项 s1 filtfilt(b_lpf, a_lpf, s1_raw); s2 filtfilt(b_lpf, a_lpf, s2_raw); % 第四步微分用中心差分提高精度 d1 [0, diff(s1)]; d2 [0, diff(s2)]; d1(1) 0; d2(1) 0; % 第五步交叉相乘再相减 p s1 .* d2 - s2 .* d1; % 第六步积分还原相位 phi_est cumsum(p) / fs; % 第七步高通滤除直流和低频环境干扰 [b_hpf, a_hpf] butter(4, 100/(fs/2), high); phi_est filtfilt(b_hpf, a_hpf, phi_est);这里有两个实现细节值得注意。第一滤波我用了filtfilt做零相位滤波而不是filter。原因是filter会引入与滤波器阶数相关的群延迟导致解调波形和原始信号在时间上发生平移影响你对比波形。filtfilt是双向滤波相位延迟为零但要求整段信号已知所以只适合离线仿真实时系统里没法用只能用filter再补偿延迟。如果你是做实时系统验证建议用filter后把输出整体平移滤波器群延迟对应的采样点数。第二微分步骤用diff直接差分在采样率很高时会放大高频噪声。信号本身干净时问题不大一旦你给干涉信号加了白噪声这个差分会导致解调输出噪声明显增大。更稳妥的做法是先用平滑滤波或者改用更高精度的五点中心差分公式我在后面的问题排查章节会再讲。4. 关键参数的影响与选择建议4.1 调制深度C的选择与漂移影响调制深度C的数值对DCM解调结果影响非常直接。从理论推导知道输出增益正比于J1(C)·J2(C)这个乘积随C呈振荡变化。C2.63 rad时J1≈0.46J2≈0.47两者乘积约0.22是一个比较合适的增益水平。更重要的是C2.63附近J1和J2随C的变化率相对平缓也就是说即使C漂移正负0.2 rad输出增益变化也不大对解调波形影响很小。但你要特别小心C落在贝塞尔函数的零点。比如C3.83 rad时J1(C)0此时混频后基频分量根本提取不出来S1项直接为零整个DCM解调输出会被压到接近零C5.14 rad时J2(C)0同样会让输出消失。实际用PZT做调制时驱动电压和环境温度都会影响C所以务必要避开这些零点区域这也是我在代码中把C预设为2.63的原因之一。4.2 载波频率与信号频率的匹配关系载波频率fc和信号最高频率fmax之间必须满足fc远大于fmax一般建议至少10倍以上。原因在于低通滤波器需要保留fmax以内的信号成分同时滤除fc附近的混频分量。如果fc和fmax距离不够滤波器过渡带就会很紧张要么压不干净高频混频分量要么把有效信号边缘衰减掉只能靠增加滤波器阶数来缓解但阶数越高群延迟越大实时性越差。采样率fs也要留足余量。我建议fs至少取fc的20倍以上5 MHz采样200 kHz载波就是25倍关系。这样高次谐波如3fc600kHz、4fc800kHz都以较低频率混叠低通滤波器压力小很多。如果你把采样率降到1 MHz高次谐波会折叠混叠回基带附近解调结果会出现很多奇怪的杂散分量排查起来非常头大。4.3 低通滤波器阶数与截止频率的平衡DCM算法对低通滤波器的要求可以总结成一句话既要滤得干净又要尽量少影响信号。我默认用4阶巴特沃斯截止频率设在30 kHz这是在多次试验后比较折中的选择。滤波器阶数过低时过渡带太宽混频分量衰减不够阶数过高时虽然滤波效果好但群延迟变大且初次调试波形延迟会让人误以为算法写错了。这里有个小技巧如果你想在仿真里直观对比解调波形和原始信号可以用filtfilt双路零相位滤波波形几乎无延迟但换到实时系统时别忘了把延迟补偿回去。滤波器的瞬态响应也会影响前段几百个采样点所以分析波形时建议跳过前1 ms的数据或者直接看稳定段。5. 常见问题与排查技巧这套代码我在不同参数下跑过很多轮也遇到过一些典型问题整理成速查表供你参考现象可能原因解决方案解调输出有强烈高频毛刺微分运算放大了混频残余或系统噪声减小低通截止频率、提高滤波器阶数对微分结果平滑波形存在明显延迟偏移filter/filtfilt引起群延迟离线用filtfilt在线用filter后补偿延迟输出幅度远小于理论值调制深度C靠近贝塞尔零点检查C的设定确保J1(C)和J2(C)都不接近零解调结果含有缓慢起伏环境低频干扰未被滤除提高高通滤波器截止频率先看信号最低频率是多少前段波形杂乱、后段正常滤波器瞬态响应去掉前1 ms数据或改用filtfilt载波泄漏明显正弦波上叠锯齿低通截止频率过高混频分量未滤净降低低通截止频率检查fc与截止频率的间距从我的实操经验看新手最容易忽略的是低通滤波器的瞬态效应。第一次跑仿真时解调输出前一小段总是跳变很大我当时以为算法推导出了问题反复检查公式和代码最后才发现是filter的初始状态为零导致的瞬态响应前半段数据根本不代表算法真实性能。这个问题在调实时系统时尤其要注意。另外一个容易踩的坑是差分运算的边界处理。直接用diff得到的信号比原信号短一个点如果直接和原信号相乘做交叉相乘会报维度不匹配。很多人的第一反应是补零但我建议用前一个差分值填充或者直接用中心差分不然边界那一点会变成一个伪突变后面积分出来会多出一个尖峰。正确做法是先算中心差分再处理首尾端点或者直接用gradient函数一步到位。6. 从仿真走向工程化写这篇分享时我重新把代码跑了一遍越是在项目上做过头的人越能体会这套仿真里那些“不起眼”的参数选择有多重要。我个人在实际操作中的体会是先别急着改参数默认参数跑通后试着把C从2.63改成1.5再改成3.5观察解调幅度的变化规律再试着把环境干扰幅度调大看看高通滤波的作用这样比单纯看一条完美曲线收获大得多。最后再分享一个扩展思路这套DCM代码很容易改造成PGC-Arctan版本只需要在提取S1和S2后把微分交叉相乘积分替换成反正切运算再相位展开就行。两种算法对比着跑一遍你对PGC解调的认识会比只看理论公式深刻得多。如果后续要做水声信号或振动信号处理还可以在信号端加入特定频带噪声检验算法在低信噪比下的表现。希望这份代码和调试心得能帮你少走一些弯路祝调通顺利。本文还有配套的精品资源点击获取
返回列表