第3章 MATLAB/Simulink环境搭建:MATLAB安装与配置、Simulink基础操作、Stateflow入门
说实话,很多做飞控的朋友一开始就急着写代码。我当年也是这样,觉得画模型浪费时间。直到有一次,我在调试一个四旋翼的姿态控制器,代码改了十几版,每次烧录都提心吊胆。后来我老老实实把Simulink用起来,才发现——模型设计不是花架子,是保命的工具。
这一章,咱们就把环境搭好。别小看这一步,环境配不好,后面全是坑。
3.1 MATLAB安装与配置:别让版本坑了你
MATLAB的版本问题,我吃过亏。有一次项目赶进度,我用了R2020a,结果同事用的是R2019b,模型互相打不开。嗯,从那以后,我养成了一个习惯:团队统一版本。
3.1.1 版本选择建议
我个人习惯用R2021b以上版本。为什么?因为从R2021b开始,Simulink对C代码生成的支持更稳定了。特别是针对飞控这种硬实时系统,代码生成的质量直接关系到飞行安全。
| 用途 | 推荐版本 | 说明 |
|---|---|---|
| 学习/原型验证 | R2021b ~ R2023a | 功能完整,社区资源多 |
| 嵌入式代码生成 | R2022b+ | 对ARM Cortex-M支持更好 |
| 团队协作 | 统一版本 | 避免模型兼容性问题 |
3.1.2 安装时的关键配置
安装过程其实很简单,但有几个地方我建议你留意一下:
- 工具箱选择:做飞控开发,下面这几个工具箱是必须装的:
- Simulink(核心)
- Stateflow(状态机建模)
- Embedded Coder(代码生成)
- Aerospace Blockset(飞控专用模块)
- Signal Processing Toolbox(信号处理)
- 路径设置:我个人习惯把项目文件夹单独放,然后在MATLAB里用
addpath添加。千万别把工作路径设成桌面,否则模型文件一多,你会疯的。 - 编译器配置:如果你要做代码生成,记得配好C编译器。在MATLAB命令行输入
mex -setup,选择MinGW-w64或者你板子对应的交叉编译器。
ver命令,看看所有工具箱是否都加载成功。我曾经遇到过工具箱装上了但没激活的情况,折腾了半天才发现。
3.2 Simulink基础操作:从拖模块到跑仿真
Simulink说白了就是一个图形化的编程工具。你想想看,写代码的时候,一个PID控制器要写几十行。但在Simulink里,拖几个模块就搞定了。而且,你能直观地看到信号怎么流,这对理解飞控系统特别有帮助。
3.2.1 模型的基本结构
一个典型的飞控Simulink模型,通常包含这几部分:
- 输入源:比如传感器数据(IMU、GPS)、遥控器信号
- 控制器:姿态控制、位置控制、导航逻辑
- 被控对象:飞机动力学模型(或者真实硬件)
- 输出显示:示波器、数据记录
我第一次搭飞控模型时,把所有的模块都堆在一个画布里。结果呢?信号线乱得像蜘蛛网,自己都看不懂。后来我学会了用子系统(Subsystem)来分层管理。
3.2.2 常用模块速览
| 模块类别 | 常用模块 | 飞控中的应用 |
|---|---|---|
| 数学运算 | Add, Product, Gain | PID计算、坐标变换 |
| 连续/离散 | Integrator, Discrete PID Controller | 姿态角积分、控制器实现 |
| 信号路由 | Mux, Demux, Bus Creator | 多路传感器数据合并 |
| 逻辑判断 | Relational Operator, Switch | 模式切换、保护逻辑 |
3.2.3 仿真设置要点
跑仿真之前,有3个参数我建议你检查一下:
- 求解器(Solver):飞控系统通常是离散的,选
discrete (no continuous states)。如果你用连续求解器,仿真步长不对,结果会差很多。 - 步长(Step size):一般设成0.001秒(1ms),和飞控的实际控制周期一致。
- 仿真时间:先跑个10秒看看效果,别一上来就跑100秒,万一模型有bug,等半天才发现。
3.3 Stateflow入门:用状态机管理飞控逻辑
飞控系统里有很多状态切换的场景。比如:
- 解锁 -> 起飞 -> 悬停 -> 降落
- 手动模式 -> 增稳模式 -> 自主飞行模式
- 正常飞行 -> 低电量保护 -> 紧急降落
这些逻辑如果用纯C代码写,if-else嵌套会让你怀疑人生。而Stateflow就是专门干这个的——用状态图来管理复杂逻辑。
3.3.1 Stateflow的核心概念
说白了,Stateflow就三个东西:
- 状态(State):系统处于什么模式。比如
DISARMED、ARMED、FLYING。 - 转移(Transition):什么条件下从一个状态跳到另一个状态。比如
油门 > 10% && 解锁信号有效。 - 动作(Action):进入状态时做什么、在状态中做什么、离开状态时做什么。
我举个例子。一个简单的飞控解锁逻辑:
// 伪代码逻辑
if (状态 == DISARMED) {
if (遥控器解锁信号 == TRUE && 电池电压 > 3.5V) {
状态 = ARMED;
解锁电机;
}
}
在Stateflow里,你只需要画两个方框,连一条带条件的箭头。是不是直观多了?
3.3.2 一个简单的飞控状态机
咱们来搭一个最简的飞控状态机。包含三个状态:
- DISARMED:上锁状态,电机不转
- ARMED:解锁状态,电机怠速
- FLYING:飞行状态,正常控制
转移条件:
- DISARMED -> ARMED:解锁信号 && 电压正常
- ARMED -> FLYING:油门 > 20%
- FLYING -> ARMED:油门 < 5%
- 任何状态 -> DISARMED:急停信号
3.3.3 Stateflow与Simulink的联动
Stateflow不是孤立的。它通常作为Simulink模型中的一个模块存在。比如:
- Stateflow接收来自Simulink的传感器信号(电压、油门值)
- Stateflow输出当前状态(解锁/锁定)给控制器
- 控制器根据状态决定是否输出PWM
这种联动方式,说白了就是逻辑与算法的分离。Stateflow管逻辑,Simulink管算法,各司其职。
after()延时函数,结果生成的代码里出现了定时器冲突。后来我改用Simulink的计时器模块,把延时逻辑放到外面,问题就解决了。记住:Stateflow适合做逻辑判断,不适合做精确计时。
3.4 本章知识体系总览
下面这张图,是我对本章内容的一个梳理。你可以把它当作一个导航图,看看自己学到哪了。
嗯,环境搭建这部分,说白了就是磨刀不误砍柴工。我见过太多人一上来就急着写控制算法,结果模型跑不通,回头才发现是环境没配好。所以,花点时间把这一步做扎实,后面你会感谢自己的。
公众号:蓝海资料掘金营,微信deep3321