用Scope模块做了三年多仿真,我一直默认“Simulink里的Scope是没法加图例的”,直到有次调试并联PID参数,三组曲线在Scope里缠成一团,我才认认真真把这个“看似无解”的需求捋了一遍。
先说结论:Scope模块本身确实没有“右键添加图例”这种内置按钮,但这不是死路。Simulink里至少有三四种靠谱的办法能让你看清“哪条线是哪个信号”,而且不同办法适用的场景完全不一样。这篇我就把它们挨个拆开讲,顺便把我在实际模型里踩过的坑也一并交代清楚,免得你照着教程做了一半卡住。
1. 搞清楚为什么Scope看信号容易“黑成一锅粥”
在动手解决图例问题之前,你得先明白Scope模块的显示机制。很多人以为Scope就是简单的示波器,把信号画上去就行,但实际上Scope模块从R2012a之后经历过一次比较大的架构调整,默认情况下它的显示逻辑和早期的LTI Viewer、甚至是MATLAB里的plot函数都有本质区别。
1.1 Scope默认显示行为的三个“坑”
第一个坑是通道识别。Scope模块的输入端如果直接接一根信号线,它默认显示为一个端口一组曲线。可一旦你接入的是Mux或者Bus Creator组合出来的多路信号,Scope会把它们当作多个通道画在同一个坐标系里,但通道名称并不会自动带出来。你打开Scope窗口之后看到的就是几条颜色不同的线,但压根不知道哪个颜色对应哪个信号。
第二个坑是Port Naming。Simulink支持给信号线命名(Signal Name),但这个名字在Scope窗口里默认是不显示的。除非你专门在Scope窗口里打开配置菜单,找到Display栏下的“Signal name”选项,勾选之后才可能在图例区看到信号名。很多人根本不知道这个入口,自然就以为Scope没有图例功能。
第三个坑,也是最大的坑:版本的差异化。不同MATLAB版本里,Scope模块的右键菜单和配置窗口长得完全不一样。在R2018b里,你右键Scope波形区域可以直接看到“Legend”选项,布尔开关加上就能显示信号名;到了R2020a之后,右键菜单改成了在Scope窗口顶部的工具栏里找“Display”图标,路径变了但功能还在。网上一搜一大把的旧教程,很多操作步骤放到新版软件上根本对不上号,这才是大家觉得“Simulink加图例特别难”的根源。
1.2 明确需求:你到底要的是“屏幕上看清”还是“导出图片用”
我接触过的需求里,给Scope加图例还可以细分成两种完全不同的场景:
一种是仿真过程中实时查看——你盯着Scope窗口,想一眼分辨哪条线是转速、哪条线是电流、哪条线是参考值。这种情况下你需要的是一个可交互的、颜色与信号名对应的显示面板。
另一种是仿真结束后做报告、写论文——你需要的是把Scope波形导出成图片,图片上要有清晰的图例,最好还带网格、带坐标轴标注。这种情况下直接在Scope窗口里折腾图例意义不大,更合适的做法是勾选“Open at simulation stop”自动打开Scope,或者直接把数据丢到MATLAB工作区里用plot函数画。
我个人的建议是:实时代码调试认准方案一,报告输出认准方案三(MATLAB侧绘图)。两头通吃的方案是Data Inspector,这个后面专门讲。
2. 最直接的办法:Scope窗口自带的信号名显示与图例开关
这一节是正餐。很多人不知道Scope窗口里其实藏着一个“信号名显示”的开关,它基本上就是我们想要的“半自动图例”。
2.1 R2018b及之后版本的操作步骤
我拿R2019a为例,这是目前工业界用得最多的几个版本之一,操作路径如下:
第一步:双击Scope模块,打开Scope窗口。
第二步:在波形显示区域的空白处点击鼠标右键,弹出上下文菜单。你会看到菜单底部有一个“Legend”选项,点一下。
第三步:此时Scope波形图的右上角会出现一个半透明的小方框,里面列出了当前Scope显示的所有通道,通道名称默认取的是信号传输线上的Signal Name。如果信号线没命名,显示出来的就是“Port N”这样的占位名。
第四步:为了让图例显示的是你真正关心的信号名,你需要回到Simulink模型窗口中,双击信号线(或单击信号线后按Enter)给每根线命名。命名之后重新仿真,Scope里的Legengd内容就会跟着更新。
如果你是R2020a以上的版本,右键菜单里可能找不到“Legend”这个英文单词,而是变成了中文“图例”,或者藏在Scope窗口顶部工具栏的“Display”下拉按钮里。点开Display按钮,里面有“Legend”“Grid”“Signal name”等一堆显示选项,全在一个面板里管理。
2.2 关键注意:信号线命名与Mux总线信号的坑
这里有一个特别容易被忽略的细节:信号命名只有在信号线属性里设置才有效,在信号生成模块的输出端口上乱写名字是无效的。我见过有人直接在Gain模块的图标上改名字,结果Scope图例里啥也不显示,查了半天才搞明白问题出在哪。
第二种情况更常见——你用的是Mux组合的多路信号。在这种情况下,光给Mux输入端的各条信号线命名是不够的,Scope显示的是Mux输出端的整体信号,它只有一个总线的名字。正确的做法是给Mux的每个输入端信号线都单独命名,然后在Scope输入端之前再接一个Demux,或者用Bus Selector把信号拆出来再接到Scope的多个端口上,这样Scope才能分别识别每个信号的名字。
实际效果对比如下:
| 处理方式 | Scope图例显示 | 适用场景 |
|---|---|---|
| 单根信号线直连Scope | 显示该信号的Signal Name | 只观察一个信号 |
| Mux输出信号直连Scope | 只显示总线名,不显示子信号 | 单纯看趋势,不需要区分 |
| Bus Selector拆分后连Scope | 可以显示各子信号名 | 需要精确区分多路信号 |
| To Workspace + MATLAB绘图 | 完全自定义图例文本 | 报告、论文输出 |
所以,如果你想让Scope自带的Legend功能起作用,最稳妥的方案其实是“一把Bus Selector把需要的信号挑出来,再并排接到Scope的多个输入端口上”。这样Scope天然把每个输入端口当作一个独立通道,分别显示对应信号的名字。
2.3 这个方案的优缺点,我实测后的体会
优点很明显:操作路径短、不用写代码、与模型交互性强。仿真过程中Scope窗口里的图例是实时跟着信号走的,信号被替换掉,图例内容也自动变化。
缺点也很明显:Scope窗口里生成的图例只是临时显示,并不方便导出。如果你把Scope窗口截图给别人看,图例文字在低分辨率截图里很容易糊掉。而且,Scope窗口自带的图例排版很松散,字大了遮波形,字小了看不清,无法调整字体大小和位置,这在做正式报告时挺难受的。
所以我的结论是:这个方案适合“自己调试模型时用”,不适合“做交付材料用”。
3. 进阶方案:把Scope当成一个“带图例的显示面板”来配置
如果你用的是比较新的Simulink版本(R2019b之后),Scope模块还支持一种叫做“Simulink Scope Viewer”的更新交互模式。在这种模式下,你可以把Scope当成一个独立的显示面板来配置图例、字体、网格等属性,自由度比老版本高得多。
3.1 开启Scope Viewer模式
在模型窗口中,双击Scope模块会默认打开Scope Viewer窗口。这个视窗和传统Scope窗口的区别在于,它更像一个独立的图形显示应用,左侧有一个“配置面板”抽屉,可以设置:
- 信号显示样式(线条颜色、线宽、线型)
- 坐标轴范围(自动或手动)
- 网格(X轴/Y轴网格开关)
- 图例显示开关与位置
- 数据光标(用于查看每个点的数值)
要打开图例,直接用快捷键“L”或者点击配置面板里的“Legend”图标即可。这个方法比右键菜单更直观,而且随时可以切换显隐,非常适合做实时仿真演示。
3.2 如何在Scope Viewer里自定义图例显示名称
Scope Viewer里的图例文本,默认也是取自信号线名称。但你可以在模型窗口里给信号线用“Signal Editor”或“Signal Properties”设置更详细的描述文字(Description),Scope Viewer会优先显示这个描述文字而不是Signal Name,这在很多复杂模型里反而更好用。
举个例子,我做一个电机控制模型时,电流环PI输出的信号线命名为“Iq_ref”,但在Scope Viewer里不显示“Iq_ref”而显示“电流环输出参考”,全靠信号属性里的Description字段。这样看图时脑子里不需要做“Iq_ref是啥来着”的翻译,确实提升不少效率。
3.3 适合做交付报告的导出技巧
Scope Viewer导出图片的功能也比老版本完善得多。文件菜单里有“导出图像”选项,导出前可以设置分辨率和尺寸。这样做出的波形图自带图例、网格,且不会出现失真的情况,基本能满足论文配图的要求。
不过还是不推荐直接在Scope里导出。最稳的做法是把信号通过To Workspace模块发到MATLAB工作区,再用MATLAB的plot/figure命令画图。这样图例格式、字体、配色完全可控,你甚至可以批量生成自定义风格的波形图。
4. 另一种思路:用To Workspace把数据导出来,在MATLAB里画带图例的图
如果你跟我一样,经常需要把仿真结果贴到Word文档或PPT里,那Scope本身我们就没必要死磕了。我更推荐的是“Simulink做仿真、MATLAB出图”的组合,这样图例配置完全不受Scope限制。
4.1 快速导出一条信号到工作区
在模型里双击你想要观察的信号线,选择“Create and Connect To Workspace”,或者直接拖一个To Workspace模块到模型中,把它和信号线连起来,设置变量名(比如simout)、采样时间(-1表示继承)。
仿真结束后,在MATLAB命令窗口直接输入:
plot(simout.Time, simout.Data); legend({'信号1', '信号2'}, 'FontSize', 12); grid on; xlabel('时间/s'); ylabel('幅值');这种做法的灵活度有多高,你不用我说也明白。想画几条线就画几条线,想用什么样的图例风格就用什么样的。特别是做电机控制、电力电子方向的朋友,如果你要投期刊或写毕业论文,图的质量很大程度上决定审稿人的第一印象,Scope自带截图完全不够看。
4.2 多信号对比时的数据组织技巧
用To Workspace导出多路信号时,你要注意数据类型。默认情况下To Workspace模块输出的是一个带时间戳的timeseries对象,如果你把多个信号导到同一个变量里,需要设置Save Format为“Array”或“Structure With Time”,否则会出现维数对不上的问题。
我在对比多个控制策略时,通常会把不同策略的仿真结果分别导出为不同的变量(比如sim_策略A、sim_策略B),然后在MATLAB脚本里统一绘图:
figure; plot(sim_策略A.Time, sim_策略A.Data, 'r-', 'LineWidth', 1.5); hold on; plot(sim_策略B.Time, sim_策略B.Data, 'b--', 'LineWidth', 1.5); legend('策略A', '策略B', 'Location', 'best'); title('两种控制策略的响应对比');这样出来的图干净、清晰、可直接放入论文,完全摆脱Scope窗口的限制。
4.3 这个方案的坑:别把数据存成稀疏矩阵
还有一个我踩过的坑。如果你在To Workspace模块设置里选了“Timeseries”以外的格式,并且仿真时间特别长,数据可能存成一个稀疏矩阵(Sparse Matrix),用plot命令画出来是断裂的线。解决方案是在To Workspace模块输出变量类型里,手动指定“Structure”或者直接在MATLAB里用full()把稀疏矩阵转成普通矩阵再画图。
另外,多信号同时导出的情况下,数据的列顺序很容易搞混。我的习惯是:每个要导出的信号单独用一个To Workspace,单独命名,绝不合并。虽然模型看起来多了几个方块,但出图的时候永远不会张冠李戴。
5. 高级玩法:用Simulink Data Inspector替代Scope
如果你还在用老版本MATLAB,或者项目里需要同时对比多次仿真的结果,我强烈建议你试试Simulink Data Inspector(数据检查器)。
5.1 Data Inspector是什么,跟Scope有什么区别
Data Inspector是Simulink提供的一个数据可视化工具,它和Scope最大的区别在于:Scope显示的是“实时”信号流,Data Inspector显示的是“记录”好的数据。也就是说,仿真跑完之后,你依然可以打开Data Inspector去翻看刚才的波形,放大、缩小、加图例,操作都不会影响仿真进程。
用Data Inspector给曲线加图例的方式非常简单——它天生就为每条信号线显示信号名和颜色标签。你甚至不需要做任何配置,只要在模型里启用“Data Logging”,仿真结束后点击模型底部的“Review Results”按钮就能打开Data Inspector。
5.2 对比多次仿真结果的图例技巧
Data Inspector最厉害的地方是可以把多次仿真结果都加载进来对比。每次仿真完,左侧信号列表会多出一组数据,信号名前带不同的颜色标签和仿真批次标记。做参数扫描或策略对比时,不用反复改图例名称,选中的每组曲线都用不同颜色和线型区分,非常直观。
我还经常用它辅助调试PID参数:跑完一组Kp和Ki参数,不用记录数据,直接在Data Inspector里拖一下时间轴就能看到超调量、响应时间的变化。省去了一堆“数据→导出→画图→对比”的中间步骤。
5.3 Data Inspector里如何“显示图例文字”
Data Inspector左侧的“Properties”面板中,点击某条信号,右侧会显示该信号的完整路径和名称,你可以在这里修改它的显示名称。这个名称会直接替换掉图例里默认的名字。所以如果你不想给模型里的信号线重新命名,直接在Data Inspector里改显示名就行。
有一点提醒:Data Inspector的显示名改动只会写进当次会话,不会修改模型本身的信号名,所以每次新仿真你都需要重新设置。如果觉得麻烦,还是老老实实回到模型里给信号线起好名。
6. 各方案对比,选型建议与经验分享
写到这里,估计你自己也快分不清到底该用哪个方案了。我把几个方案的核心差异和适用场景整理成一张表,帮助你快速决策。
6.1 四种方案对比表
| 方案 | 操作成本 | 图例可实现性 | 交付质量 | 推荐场景 |
|---|---|---|---|---|
| Scope内置Legend | 低,右键开关即可 | 一般,依赖信号命名 | 中,截图可用 | 日常调试,快速看趋势 |
| Scope Viewer面板 | 中,需熟悉新UI | 好,支持字体设置 | 中高,可导出图像 | 需要现场演示、演示汇报 |
| To Workspace + MATLAB绘图 | 中高,需写绘图脚本 | 极高,完全可控 | 极高,论文级 | 写报告、论文、存档 |
| Simulink Data Inspector | 低,自动记录 | 极好,天然带名称 | 高,可导出数据 | 多仿真对比、参数扫描 |
如果你还在纠结,我建议按下面这条思路选:
- 如果你只是在自己的电脑上调试模型,把Scope的Legend开关打开就够了,顶多再按一下“L”键快速启停图例,不用想太多。
- 如果你要给别人做技术汇报、演示,用Scope Viewer,把图例和网格打开,最好再加一组数据光标,现场效果会专业很多。
- 如果你想把结果留存在文档里,或者做严肃的对比分析,直接用To Workspace + MATLAB绘图,别把时间浪费在Scope的排版和截图上面。
6.2 一个真实的工程案例:多信号并联PID调试
我去年做一个伺服电机位置环、速度环、电流环三环控制器联调,Scope里同时看了位置参考、位置反馈、速度参考、速度反馈、电流参考、电流反馈六条曲线。在没有图例的情况下,用颜色区分六条线几乎是不可能的。
当时我采用了方案一+方案三的组合:先用Scope的Legend开关快速定位哪条线对应哪个环,确认大方向没问题后,再把关键数据通过To Workspace导出,用MATLAB画出带图例的对比图用于调试记录和项目周报。
那个周报反馈特别好,领导一眼就能看出速度环有超调、位置环跟踪正常、电流环纹波偏大。如果当时只截一个Scope的模糊截图,沟通成本至少翻倍。
6.3 别陷入“Scope万能”的陷阱
最后说句掏心窝的话。很多初学者被Scope的便捷界面“惯坏了”,所有信号都想往Scope里拖,连个原始波形都舍不得丢掉,就怕漏掉什么数据。但实际上,Scope是“看”的工具,不是“存”的工具。你想做严谨的分析、对比、文档化,数据一定要进工作区,图像一定要用绘图脚本来出。
我在团队里带新人的时候,要求他们每个人把自己负责的模块信号都用To Workspace统一命名导出,再写一个标准的output_plot.m脚本,到周报节点只要跑一遍脚本,所有波形图自动批量生成。这个习惯一旦养成,做正式交付的效率会高出好几个量级。Scope图例只是让你“看得懂”,而规范的出图流程才是让你“拿得出”。
7. 写在后面的个人经验
关于Scope图例,网上讨论一直存在争议,有人说Simulink这个设计很反人类,也有人觉得是自己没用对技巧。我的观点比较实际:工具就是工具,它不可能满足你所有想象中“应该有的功能”,但只要你理解了它的设计逻辑——Scope重点服务实时信号监视,图例优先级低——你就不会在这上面浪费太多时间。
我个人的习惯是:模型里习惯给每条关键的信号线命名,而且命名带有明确的语义,比如Pos_Ref、Speed_FB、Iq_Ref,不搞模棱两可的Signal1。这样做的好处不只是Scope图例能正常显示,后面做自动代码生成、做HIL仿真、做文档导出,都会收到正向反馈。
另外,有条件的朋友建议多逛一下官方文档里关于“Display Signal Attributes”和“Visualize Simulation Data”的章节,里面关于Scope、Data Inspector、Record模块的内容非常系统,能帮你少走很多弯路。市面上很多东拼西凑的教程,都是基于旧版软件写的,照着做真的不如翻官方文档好用。
最后再分享一个小操作:如果你有多个Scope模块散落在模型各处,又不想一个一个去开启图例,可以在模型菜单栏选择“Display” → “Signals & Ports” → “Port Value Labels”之类的选项批量管理信号显示属性。虽然这不是严格意义上的图例配置,但是能让信号名在实际连接线上显示出来,找信号的时候特别方便,算是给Scope图例打了个很好的辅助补丁。