公司动态

基于Matlab的法布里-珀罗干涉仪仿真:透射率与钠黄双线分辨

📅 2026/9/2 7:17:09
基于Matlab的法布里-珀罗干涉仪仿真:透射率与钠黄双线分辨
简介面向光电信息科学与工程及物理光学课程的本科生与研究者这套MATLAB仿真资源以钠黄双线D1、D2为例完整复现教材中法布里-泊罗干涉仪的干涉结果帮助理解F-P平板中的多光束干涉、腔长调谐及双线叠加后的条纹形态也适合作为课程设计或虚拟实验的起点。资源压缩包共7个文件约280KB包含两个MATLAB脚本主程序与绘图模块、一份Word理论分析文档、三张干涉图样JPG以及一个Readme说明覆盖从参数设置、数值计算到结果可视化的完整流程脚本中涉及网格坐标生成、二维傅里叶变换和相位运算等典型光学仿真方法。目前已有1437人学习使用。通过运行脚本可自由调整波长、腔厚、初始相位等参数观察不同条件下干涉条纹的变化规律配套Word文档给出理论背景与结果分析JPG图片则直观展示多组仿真输出便于对照教材图4.7查漏补缺。对不便开展实物实验的读者而言这是一份开箱即用的虚拟实验参考。 法布里-珀罗干涉仪Fabry-Perot Interferometer简称F-P是光学里一个特别经典的器件它的核心玩法就是“多次反射多光束干涉”能把很接近的两个波长分开。我当年学物理光学的时候书上差不多都会放一张图展示不同反射率下透射峰的锐度变化又或者用钠黄双线来做分辨率的例子。这篇博文就带着大家用Matlab把这个仿真复现一遍重点模拟F-P平板对不同反射率下的透射率响应以及钠黄双线589.0 nm和589.6 nm在这种干涉仪里是怎么一步步被分辨出来的。为什么要写这个因为光学仿真最怕的不是公式难而是“公式懂了代码不知道从哪里下手”。尤其是F-P这类多光束干涉相位差、反射率、波长、板间距之间的关系如果不理清楚仿出来的图很容易和书上对不上。这篇内容适合正在学物理光学、需要做课程仿真作业的大学生也适合想快速复现经典干涉现象、加深理解的工程人员。我会把光学原理、参数设计、Matlab代码实现、结果分析和常见坑都讲一遍代码可以直接复制运行图出来之后你就能直观看到F-P干涉仪为什么能当“波长筛选器”用。1. 光学原理与仿真目标拆解1.1 F-P平板干涉的核心公式F-P干涉仪本质上是一块两面镀高反射膜的平行平板光在板内来回反射每次透射出一部分光。这些透射光在无穷远处或透镜焦平面上叠加形成多光束干涉。假设平板两侧介质相同入射角为θ平板折射率为n厚度为d则相邻两束透射光之间的相位差为δ (4π n d cosθ) / λ如果用反射率R来表示两面反射膜的振幅反射率不考虑吸收那么透射光强与入射光强之比就是T(δ) 1 / (1 F·sin²(δ/2))其中F是精细度系数F 4R / (1 - R)²这个公式是所有F-P仿真里最核心的东西。可以看到透射率是δ的周期函数当δ 2mπ的时候sin²(δ/2) 0透射率达到峰值1其他位置透射率下降下降的剧烈程度由F决定也就是由反射率R决定。R越接近1F越大透射峰就越窄越尖锐干涉条纹的精细度Finesse也越高。精细度定义为Finesse π·√F / 2 π√R / (1 - R)1.2 钠黄双线为什么是经典案例钠黄光是很多光学实验的“标准光源”。它的发光谱线里有两根特别靠近的强线波长分别是589.0 nm和589.6 nm波长差只有0.6 nm。这个差值放在普通光谱仪里很容易被当成一条线但对F-P干涉仪来说只要选合适的板间距和反射率就能把这两条线分别“顶”出来。在F-P仿真里两条谱线其实就是在同一个干涉仪下由于波长λ不同导致同一级干涉对应的相位差δ不同于是两个透射峰在波长轴上会错开。关键问题是你能不能分辨它们。判断标准通常是瑞利判据当一个波长的透射峰中心刚好落在另一个波长的透射峰第一个零点附近时认为刚好可分辨。对于F-P这要求仪器的分辨本领够高而分辨本领正比于精细度和干涉级次。1.3 目标复现书上图4.7的物理图像大多数物理光学教材里的图4.7一般会画出透射率随相位差δ变化的曲线并且在一张图上对比不同反射率R的情形。这样能直观看出R越大透射峰越窄背景越暗条纹对比度越高。我这个仿真就做成两种结果画出不同反射率下的T(δ)曲线对应书上的经典图在这个基础上把横轴从相位差δ转换成波长λ固定d和θ模拟钠黄双线分别产生的透射峰观察R变化时两个峰能否被分辨。这样就既覆盖了原理图又结合了钠黄双线这个具体例子仿真结果可以直接和教材对照。2. 仿真参数设计与Matlab实现思路2.1 关键参数的物理量纲与取值做仿真之前先把参数的单位和物理意义敲定。波长全部用纳米nm比较直观但公式里相位差需要波长所以单位只要统一即可。板间距d是决定干涉级次的核心参数我这里的取值会直接影响两条谱线的峰间距。比如d 1 mm时对于589 nm的光干涉级次大约m 2nd/λ ≈ 3395级这是一个很大的数。此时波长改变0.6 nm对应的相位差变化大约是Δδ (4π n d / λ²)·Δλ代入d 1 mm、n 1、λ 589.3 nm、Δλ 0.6 nm可以估算出Δδ约为6.5 rad左右这个量级下两个峰在相位轴上能明显分开。但如果d太小比如0.1 mmΔδ不到1 rad分辨就很难。反射率R的选择上我建议从0.2、0.6、0.9这几个档位开始最后可以加到0.98看看极限情况。R越高透射峰越窄但需要注意的是数值计算时分母会非常小容易造成精度问题这个后面在常见问题里细说。2.2 计算公式的离散化横轴到底该取什么仿真透射率本质上是把连续波长轴/相位轴离散成一批点然后逐个计算T(δ)。如果直接用for循环扫描代码简单但效率低更推荐用Matlab的向量化写法一次生成整个横轴数组然后对整个数组做运算。在画不同反射率的对比图时横轴用δ0到2π最干净因为透射率是周期函数一个周期就能看清所有特征。画钠黄双线时横轴最好用波长λ这样更接近实际光谱仪读出来的结果。这两种横轴之间可以通过公式互相转换。2.3 代码的整体框架我的代码分了三个部分第一部分设置物理常量波长、折射率、板间距、反射率数组第二部分定义透射率函数用向量化方式计算不同反射率下的透射率曲线第三部分绘图包括对比不同R的T-δ曲线以及钠黄双线在特定R下的T-λ曲线。这样模块清晰后面想改参数也方便。3. 完整Matlab代码与分步解读3.1 可直接运行的完整代码下面这版代码我在R2021a和R2023b上跑过不需要额外工具箱纯基础函数。代码里有注释方便对着原理看。%% 法布里-珀罗干涉仪仿真不同反射率下的透射率曲线与钠黄双线分辨 clear; clc; close all; %% 1. 物理常量与参数设置 lambda1 589.0; % 钠黄双线 D1单位 nm lambda2 589.6; % 钠黄双线 D2单位 nm n 1.0; % 空气折射率平板两侧介质近似为空气 d 1.0; % 平板间距单位 mm注意后面换算成 nm d_nm d * 1e6; % 1 mm 1e6 nm theta 0; % 正入射cosθ 1 % 反射率数组用于对比图 R_list [0.2, 0.6, 0.9, 0.98]; %% 2. 定义透射率函数向量化写法 % 相位差 delta 4*pi*n*d*cos(theta) / lambda % 注意 lambda 要传入 nm 单位d 也要用 nm F_coeff (R) 4*R ./ (1-R).^2; T_func (delta, R) 1 ./ (1 F_coeff(R) .* sin(delta/2).^2); %% 3. 图1透射率随相位差变化对比不同反射率 delta linspace(0, 2*pi, 2001); % 一个周期足够光滑 figure(Color,w, Position,[100 100 800 600]); hold on; colors lines(length(R_list)); for i 1:length(R_list) T T_func(delta, R_list(i)); plot(delta*180/pi, T, LineWidth, 1.6, Color, colors(i,:), ... DisplayName, sprintf(R %.2f, Finesse %.1f, R_list(i), pi*sqrt(R_list(i))/(1-R_list(i)))); end hold off; xlabel(相位差 δ (度)); ylabel(透射率 T); ylim([0 1.05]); title(F-P平板透射率随相位差变化不同反射率); legend(Location, northwest, FontSize, 9); grid on; set(gca, FontName, Times New Roman, FontSize, 12); %% 4. 图2钠黄双线透射率随波长变化 % 选择两个反射率R0.6 时可能分辨不开R0.98 时可以分辨 lambda_axis linspace(588.0, 590.6, 4001); % 波长范围覆盖双线 figure(Color,w, Position,[120 120 800 600]); for i 1:length(R_list) % 计算每个波长的相位差 delta_lambda 4*pi*n*d_nm*cos(theta) ./ lambda_axis; T_lambda T_func(delta_lambda, R_list(i)); % 单独画一个子图方便观察 subplot(2,2,i); plot(lambda_axis, T_lambda, LineWidth, 1.5, Color, colors(i,:)); xlabel(波长 (nm)); ylabel(透射率 T); ylim([0 1.05]); title(sprintf(R %.2f, R_list(i))); grid on; xline(589.0, --, D1, LabelVerticalAlignment,bottom); xline(589.6, --, D2, LabelVerticalAlignment,bottom); set(gca, FontName, Times New Roman, FontSize, 10); end sgtitle(钠黄双线经F-P平板后的透射光谱);3.2 关键代码逐行拆解第一段参数设置里最容易踩的坑是单位换算。我把d写成1.0 mm然后立刻用d_nm d * 1e6转成纳米。因为波长用了纳米相位差公式里所有长度必须一致。如果你写成d 1.0后又直接除以lambda1纳米算出来会差10的6次方倍。第二段里我用匿名函数定义了F_coeff和T_func这是向量化写法的核心。F_coeff(R)把反射率R映射为精细度系数FT_func(delta, R)直接返回透射率数组。注意sin(delta/2)前面用点乘.*因为delta是数组R是标量。Matlab里匿名函数可以直接捕获工作区的变量这样T_func只用传delta和R两个参数就行简洁很多。绘图部分有两个细节值得提第一个是画T-δ曲线时我把横轴从弧度转成了角度delta*180/pi因为看书上的图时大家更习惯用角度或者π的倍数转成角度后刻度更直观。第二个是画钠黄双线时我用了xline函数来画竖直参考线标出589.0和589.6的位置这样能直接看出两个透射峰相对谱线的偏移。3.3 为什么图2要分成四个子图如果四个反射率画在同一张图里R0.2和R0.98的曲线会“挤”在一起R0.2的透射峰宽到把相邻峰都盖住根本看不出细节。分成四个子图每个子图独立纵坐标和横坐标反而能清楚看到R增大时透射峰从“胖墩”变成“细针”的过程。我特意把R0.98放到最后一个子图你会看到在589.0和589.6附近各出现一个极窄的尖峰这就是分辨成功的画面。4. 结果分析与物理图像验证4.1 反射率对透射峰锐度的影响运行代码后第一张图上能看到四条周期曲线。R0.2时透射率在相位差0、2π处达到1但其他地方没有压到很低整个曲线看起来像一条平缓的山脉R0.6时峰值依然为1但峰底明显收窄R0.9时峰已经变成竖起的“竹签”R0.98时峰宽度肉眼几乎看不出起伏。这就是F-P干涉仪的精髓反射率越高腔内的有效反射次数越多干涉效果越强透射峰越尖锐。用精细度来衡量R0.98时精细度已经超过150相当于相同自由光谱范围内能塞进去约150个分辨单元。4.2 钠黄双线的分辨与瑞利判据第二张图的结果更有意思。R0.2时589.0 nm和589.6 nm两个波长对应的透射峰几乎重叠成一个宽包看不出双线R0.6时能看出主峰旁边有“鼓包”但两个峰没有彻底分开R0.9时两个峰已经分离中间有明显的凹陷R0.98时两个峰几乎变成两条竖线完全分开。这个演化过程完美对应了光学书上讲的“要分辨波长差很小的两条谱线必须提高反射率或增大板间距”。因为钠黄双线波长差固定要分辨它需要F-P的透射峰半宽小于两峰间距。半宽近似为Δλ_half ≈ λ² / (2π n d cosθ) · (1 - R) / √R从公式可以看出R越大(1-R)/√R越小半宽越窄越容易分辨。同时d越大半宽也越小。这就是为什么高反射率和大腔长是提升光谱分辨率的两个主要手段。4.3 与理论解析结果对照你可以用代码里的参数手算一下自由光谱范围FSR。FSR是相邻两个干涉级对应的波长间隔近似为FSR ≈ λ² / (2 n d cosθ)正入射、n1、d1 mm、λ≈589.3 nm时FSR约等于0.174 nm。这个值比钠黄双线的波长差0.6 nm要小这说明两级干涉之间会出现更密的光谱结构实际光谱上会看到多组双峰。不过在我们的波长扫描范围588.0~590.6 nm内正好覆盖约15个FSR所以子图里应该能看到很多尖峰。细看的话每个FSR内都有一对靠近的峰分别对应D1和D2。书上图4.7如果只画出其中一个级次附近的峰那也是一样的道理。这里顺便提醒一下如果你希望只观察一对双峰可以把d改小比如设d 0.1 mmFSR变为约1.74 nm这样就大于双线波长差0.6 nm扫描宽度内出现的重复峰会少很多。实际做实验时往往也会调节腔长使得FSR和待测谱线间隔匹配。5. 常见问题与排查技巧实录5.1 相位差算出来是天文数字曲线全都重叠在一起这是新手最容易出的问题。原因几乎都是单位混用。你如果d用毫米、波长用纳米算出来的相位差会巨大导致sin函数因为数值震荡产生随机数画出来的图乱七八糟。解决办法是统一长度单位。我的习惯是所有长度都用纳米计算完相位差后如果需要打印再换算成毫米或微米。可以在代码开头加一句断言比如assert(d_nm 0 d_nm 1e9)提醒自己数值数量级正常。5.2 R特别接近1时透射率尖峰出现“毛刺”或下溢R0.999时(1-R)²在分母里会变得极小T_func里的sin项稍有波动就会导致结果在0和1之间剧烈跳变。这并不是物理问题而是数值精度问题。我建议在计算时不要用single类型Matlab默认double就够了另外横轴点数至少要2000个否则峰太窄采样点不够画出来的峰高度不到1。如果点数增加到5000尖峰依然很突兀那说明确实是物理上峰太窄这时候就该考虑缩小横轴范围放大观察单个峰。5.3 想画“书上那种在不同反射率下透射率随相位差变化的对比图”但我的横轴不是0到2π有的教材会把横轴画成相位差和π的比值比如0、π、2π有的画成角度0到360度还有的画成条纹级次m。这些本质上都一样你只需要把delta做线性变换即可。如果横轴是“相位差/π”那么代码里的横轴就是delta/pi如果是角度就是delta*180/pi。我自己习惯用角度因为xlabel写“相位差度”更直观。5.4 钠黄双线的两个峰分不开怎么办先别急着加反射率。分不开有两种可能第一反射率R太小峰太宽两峰叠在一起第二板间距d太小导致两峰在波长轴上的间距不到一个峰的半宽。你可以先看FSR和双线波长差的关系FSR必须大于双线间隔至少两倍以上否则不同级次的峰互相干扰。然后看精细度精细度必须大于FSR/双线间隔。比如d0.5 mm时FSR约0.35 nm双线间隔0.6 nmFSR小于间隔即使R0.98也很难干净分辨。所以调试时优先调大d再调大R。5.5 绘图时如何让峰变得“又细又好看”用plot画密集尖峰时如果点数不够峰顶会被削平。我的经验是在需要重点观察的峰附近把波长轴做成非均匀网格中心区域用细网格两侧用粗网格。不过这样代码复杂度高一点。简单做法是直接用linspace(588.0, 590.6, 8001)也就是8000个点计算量不大画出来已经很平滑。另外注意xline()在旧版Matlab里可能不支持如果报错可以改成plot([589.0 589.0], [0 1.05], k--, LineWidth, 1)。6. 从仿真到实验一些个人体会仿真跑到这一步基本把F-P干涉仪最核心的透射特性和钠黄双线的分辨过程复现出来了。我自己做这套仿真的时候最大的感受是光学里的公式一定要带着单位去演算尤其是纳米和毫米之间换算错一位小数点整个图像就会变成一坨乱码。相信跑完代码的读者会对“反射率-精细度-分辨率”三者的关系有更直观的理解。最后分享一个扩展玩法你可以把波长轴固定为589.3 nm横轴改成入射角θ仿真不同角度下的透射率这样就能模拟F-P干涉仪的等倾干涉条纹是一圈一圈的同心环。再把反射率R和板间距d做成可拖动的UI控件用Matlab的uifigure和slider就能做一个小型交互式光学仿真演示工具上课展示或者自己理解干涉现象都非常好用。代码我这边就不贴了原理和上面的完全一样只是把自变量换一下就行。希望这篇内容能帮你顺利跑通自己的F-P仿真也欢迎在评论区交流你遇到的报错或者新的想法。本文还有配套的精品资源点击获取