在上一篇博客中,介绍了如何使用C Function 实现PI运算,但是在模块内编辑C代码,而不能直接调用已经写好了的C代码。
在Simulink中使用C Function调用自定义代码有两种方法,本篇博客介绍其中一种方法。
添加头文件和源文件
在实际系统中,使用C语言,一般需要添加源文件(.c)和头文件(.h)。因此,需要首先在Simulink仿真文件的相同路径下,新建“source”和“include”文件夹,然后再source和include的文件夹中分别添加源文件和头文件。当然,也可以全部放在仿真文件的路径中,但是这样不方便管理文件。如下图所示。
其中,PI_USER.c的代码如下
#include "PI_USER.h"
//*********** Function Definition ********//
void PI_USER_FUNC(PI_USER *v){
/* proportional term */
v->up = ((v->Ref - v->Fbk)*v->Kp);
/* integral term */
v->ui[0] = ((v->Ref - v->Fbk)*v->Ki)*v->delta_T+v->ui[1];
v->ui[1] = v->ui[0];
/* control output */
v->Out = v->up + v->ui[0];
}
其中,PI_USER.h的代码如下
#ifndef _PI_USER_H_
#define _PI_USER_H_
typedef struct {
float Ref; // Input: reference set-point
float Fbk; // Input: feedback
float Out; // Output: controller output
float Kp; // Parameter: proportional loop gain
float Ki; // Parameter: integral gain
float up; // Data: proportional term
float ui[2]; // Data: integral term
float delta_T;
} PI_USER;
//*********** Function Declarations *******//
void PI_USER_FUNC(PI_USER *v);
#endif /* _PI_USER_H_ */
配置C Function模块
接着,配置C Function模块。双击“C Function模块”,在“仿真自定义代码”下选项下,有头文件、源和搜索目录需要配置。如下图所示。
其中,头文件、源均与source和include文件夹下的文件名相同,搜索目录可以填写相对路径,即为source和include。
在“输出”部分,编辑C代码如下图所示
具体地解释如下
PI_USER pi_temp; //定义PI_USER 类型的结构体,PI_USER的定义在PI_USER.h中
pi_temp.Ref = ref; // C Function的输入ref赋值给PI_USER的输入Ref
pi_temp.Fbk = fbk; // C Function的输入fbk赋值给PI_USER的输入Fbk
pi_temp.Kp = kp; // C Function的参数ki赋值给PI_USER的比例系数Kp
pi_temp.Ki = ki; // C Function的参数ki赋值给PI_USER的积分系数Ki
pi_temp.ui[1] = ui1; // C Function的输出赋值给 PI_USER的上一周期的积分结果
pi_temp.delta_T = Tsample; // C Function的参数Tsample赋值给PI_USER的计算周期
PI_USER_FUNC(&pi_temp); // PI函数
Out= pi_temp.Out; // PI函数输出给C Function模块输出
ui0 = pi_temp.ui[0];// PI的积分输出
特别说明,因为在C语言代码中,PI_USER pi_temp;是定义在main.c中的,所以初始化后会给该结构体分配地址,且不会清空。但是在Simulink中,好像会清零,所以需要特别的把积分项通过C Function端口输出,如:“ui0 = pi_temp.ui[0];”同时,再将该输出给到C Function的模块输入。但是,这样会引入代数环(简单的理解为,模块自身的输出不能作为自身的输入),因此,需要加入Memory模块来Break该代数环,最终的仿真图如下图所示。
同时,也搭建一个没有Memory模块的仿真进行对比。
观察仿真结果
下图所示即为仿真结果的对比
从上图可以看出,如果没有Memory模块,则仿真时无法保留上一计算周期的积分项,导致只有比例环节起作用。可见,将积分结果输出再通过Memory存储后作为PI的输入,实现积分功能是很必要的!
以上便完成了,通过C Function调用用户自定义的外部代码,在Simulink中使用C语言的代码。
希望对你有所帮助!我是Mantou!