Simulink S-Function的使用(以串口接收MPU6050六轴陀螺仪参数为实例)
S-Function 允许使用自定义C/C++函数作为传递函数,具有可移植性。也可以同样利用MATLAB函数进行相同的运算,看开发者熟悉程度而定。
项目流程
- 由系统串口接收数据包。
- 通过S-Function自定义函数解析数据包,得到数据集合。
- 数据集合总线输出,分为各部分数据进行可视化显示。
串口接收
首先需要通过MPU6050数据手册将其寄存器的各项输出数据通过UART读出,并将其处理为我们所需要的7项参数(加速度Accl. [X,Y,Z],角加速度Gyro. [X,Y,Z],温度Temp)。
但是这不是本文的重点,因此本文假设已经处理好了上述数据,并且以字符打印的形式通过串口稳定输出,(通过Rasberry Pico PI预处理)如下:
我们需要配置串口接收参数:
COM口以用户本机分配为准
Serial Configuration配置如图
Serial Receive配置如图
注意,由于是以字符char
接收,因此选择类型为uint8
,Data Size设置缓冲区大小,此处设为128为例。同样可以设置数据包头和数据包尾,我们此处不做设置。
当然,在实际项目中会以更高效率的数据包传输,此处仅为示例作用,因此选用字符接收。
S-Function函数示例
从Library Browser中找到User-Defined functions(用户自定义函数),在系统仿真中这部分是较为常用的。
选择S-Function Builder,双击点开面板。由于是面板端编辑,直接面向对象,逻辑更清晰,但是限制也较多。
填写函数名,选择语言C++,即可Build编译。(初次需要按提示安装MinGW-w64方可编译,且安装目录不能带空格)
注意到,编辑器里面有三个子函数,分别封装S-Function的起始方程,输出方程和终止方程,在本实例中仅用到输出的封装,其他功能请自行学习浏览官方示例。
void xxx_Start_wrapper(void);
void xxx_Outputs_wrapper(const real_T *u0, real_T *y0);
void xxx_Terminate_wrapper(void);
注意到,输入输出参数都是以数组指针的形式传参的,带const
表示输入参数,不可更改,不带的即表示输出参数,可更改。函数的目的是按次调用这三个子函数。
我们可以先调试好C++程序再整合。
在本实例中,输入参数为大小为128*1的字符数组(uint8
),输出参数为包括三个参数的总线(Bus:gyroData
),以结构体形式调用。
在自己工程文件中定义头文件(structure.h
),用于类型的转换和结构体的定义等,这部分内容是为了便于程序能在本地调试成功,而由于在Simulink中这部分内容已有定义,因此在Simulink的S-Function Builder中编译的时候是需要将其之注释掉的。
structure.h
:
#ifndef _STRUCTURE_H
#define _STRUCTURE_H
typedef char uint8_T;
typedef short int16;
struct gyroData{
int16_t accl[3], gyro[3];
double temp;
};
#endif //_STRUCTURE_H
如果不注释掉,在编译时会由于变量类型冲突而编译失败。
在本地C++工程调试成功,即可移植。
调试成功后,将其移植至S-Function Builder中。
注意参数类型、维度都要一一匹配。需要用到的头文件和引入文件也需要在include部分添加进来。
如果C++工程包含其他文件,将工程文件目录添加至INC_PATH
,注意文件目录最好不要含有空格,否则再次打开时可能会产生修正而出错。
点击编译,提示ERROR: Bus object for output port 1 gyroData does not exist in workspace
,即:总线未被添加至工作区导致编译失败。
手动添加的办法,即打开MODELING中的Bus Editor选项进行添加,注意总线名称Object Name
以及元素名称,以及其类型、维度,均设置匹配。当然,也有通过代码区更方便添加的办法请自动查阅相关文档。
添加后请将其保存为.mat
文件方便日后直接将设置好的总线导入。
如果没有问题,会显示S-Function编译成功。
这时,我们可以用S-Function模块直接填写函数名,直接调用,模块会自动产生相应数目的输入输出端口,可以供检查。
(虽然S-Function Builder也可直接使用)
这样,我们的S-Function就编写完成。
数据可视化
我们利用Bus Selector模块进行对总线拆分,用Display模块显示文本(数组),用Scope模块进行示波器图像绘制,这些属于基本操作,就不详加叙述了。
这里提到一个调试的方法,即先使用静态文本(此处用了字符串常量String Constant)进行调试,确认S-Function功能无误即可接入动态数据进行观察。
最后
文章末尾,附上相关的工程文件供参考。
bus_gyroData.mat
gyroData总线getGyroData___
由S-Function生成的函数receive_test.slxc
接收端Simulink工作区面板gyroDataProcess
用于产生S-Function的C++文件
请访问我的Github URL以下载:https://github.com/Chiron19/Simulink
感谢阅读!欢迎分享。