1. 引言
在变流器控制中,通常采用C语言实现传递函数,且通常写成独立的C文件,本文简要介绍如何在MATLAB/Simulink中调用这些C文件。
在本文中,采用C语言实现了一阶低通滤波器、二阶低通滤波器、滑动平均滤波器,具体代码见附录。同时需要安装C编译工具链,参考《Using GCC with MinGW》。
2. 接口代码文件准备
为调用已写好的C文件,需要做一层额外的封装供Simulink的MATLAB Function
调用。本文将这一接口文件命名作porting.h
和porting.c
。
2.1 porting.c文件
在该文件中,主要提供两类函数:仿真运行开始时的初始化(init)函数、离散周期中调用的回调(callback)函数。这两类函数都是基于已有的文件进行封装的,一个原则就是不要动已有的文件。
#include "ufilter.h"
#include "porting.h"
/**
* @brief Handler for the 1st-order LPF
*/
static ufilter_lp1st_t lp1st;
/**
* @brief Hanlder for the 2nd-order LPF
*/
static ufilter_lp2nd_t lp2nd;
/**
* @brief Handler for the moving average
*/
static float ma_buffer[260];
static ufilter_ma_t ma;
float porting_ufilter_lp1st_init_lp1st(void)
{
ufilter_lp1st_init(&lp1st, 314, 0.0001);
}
float porting_ufilter_lp1st_callback_lp1st(float _x)
{
float y;
y = ufilter_lp1st_callback(&lp1st, _x);
return y;
}
float porting_ufilter_lp2nd_init_lp2nd(void)
{
ufilter_lp2nd_init(&lp2nd, 314, 0.5, 0.0001);
}
float porting_ufilter_lp2nd_callback_lp2nd(float _x)
{
float y;
y = ufilter_lp2nd_callback(&lp2nd, _x);
return y;
}
float porting_ufilter_ma_init_ma(void)
{
ufilter_ma_init(&ma, 260, ma_buffer);
}
float porting_ufilter_ma_callback_ma(float _x)
{
float y;
y = ufilter_ma_callback(&ma, _x, 200);
return y;
}
2.2 porting.h文件
该文件的主要作用时将已经封装函数声明,供外部调用。
float porting_ufilter_lp1st_init_lp1st(void);
float porting_ufilter_lp1st_callback_lp1st(float _x);
float porting_ufilter_lp2nd_init_lp2nd(void);
float porting_ufilter_lp2nd_callback_lp2nd(float _x);
float porting_ufilter_ma_init_ma(void);
float porting_ufilter_ma_callback_ma(float _x);
3. Simulink调用及配置方法
3.1 初始化函数的调用
在如下位置调用porting.c
文件中重新封装的初始化函数。
3.2 回调函数的调用
在Simulink中添加MATLAB Function
模块,在MATLAB Function
中调用porting.c
文件中重新封装的回调函数,例如:
function y = lp1st(u)
y = 0;
y = coder.ceval("porting_ufilter_lp1st_callback_lp1st", u);
end
并将MATLAB Function
模块的Update method
设置为Discrete
,Sample Time
设置为C代码中回调函数在实际系统中的采样周期。(在Simulink中MODELING
选项卡下选择Model Explorer
可打开以下窗口)
3.3 Simulink仿真文件配置
主要需要进行3个内容的配置:Include directories (C文件所在路径)、Header file(以代码方式添加)、Source file(列出C文件)。
4. 仿真效果
仿真模型如下:
运行结果如下,仿真结果正确:
附录
A. ufilter.h文件
/**
*******************************************************************************
* @file ufilter.h
* @author xixizhk
*******************************************************************************
* @version V20210109 \n
* Initial version.
*******************************************************************************
*/
/* Define to prevent recursive inclusion **************************************/
#ifndef _UFILTER_H
#define _UFILTER_H
#ifdef __cplusplus
extern "C" {
#endif
/**
*******************************************************************************
* @addtogroup Includes
* @{
*/
#include "stdint.h"
/**
* @}
*/
/**
*******************************************************************************
* @addtogroup Definitions
* @{
*/
/** Definition of the handler for the 1st lowpass filter. */
typedef struct
{
/* Coefficients for differential equation */
float b_0;
float a_1;
/* Intermediate variables */
float y_k_1;
} ufilter_lp1st_t;
/** Definition of the handler for the 2nd lowpass filter. */
typedef struct
{
/* Coefficients for differential equation */
float b_1;
float a_1;
float a_2;
/* Intermediate variables */
float x_k_1;
float y_k_1;
float y_k_2;
} ufilter_lp2nd_t;
/* Definitions of the handler for the moving average. */
typedef struct
{
/* Pointer to integral buffer. */
float *buffer;
/* Length of int_buffer. */
unsigned int N;
/* Index for callback. */
unsigned int index;
/* Offset for integral. */
float offset;
} ufilter_ma_t;
/**
* @}
*/
/**
*******************************************************************************
* @addtogroup Types
* @{
*/
/**
* @}
*/
/**
*******************************************************************************
* @addtogroup Constants
* @{
*/
/**
* @}
*/
/**
*******************************************************************************
* @addtogroup Variables
* @{
*/
/**
* @}
*/
/**
*******************************************************************************
* @addtogroup Macros
* @{
*/
/**
* @}
*/
/**
*******************************************************************************
* @addtogroup Functions
* @{
*/
/* For the 1st lowpass filter. */
void ufilter_lp1st_init
(
ufilter_lp1st_t *_ufilter,
float _omega_c,
float _Ts
);
float ufilter_lp1st_callback
(
ufilter_lp1st_t *_ufilter,
float _input
);
void ufilter_lp1st_reset
(
ufilter_lp1st_t *_ufilter
);
/* For the 2nd lowpass filter. */
void ufilter_lp2nd_init
(
ufilter_lp2nd_t *_ufilter,
float _omega_n,
float _zeta,
float _Ts
);
float ufilter_lp2nd_callback
(
ufilter_lp2nd_t *_ufilter,
float _input
);
void ufilter_lp2nd_reset
(
ufilter_lp2nd_t *_ufilter
);
/* For the moving average. */
void ufilter_ma_init
(
ufilter_ma_t *_ufilter,
unsigned int _N,
float *_buffer
);
float ufilter_ma_callback
(
ufilter_ma_t *_ufilter,
float _input,
unsigned int _W
);
void ufilter_ma_reset
(
ufilter_ma_t *_ufilter
);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* _UFILTER_H */
/**************************** ALL RIGHTS RESERVED *****************************/
B. ufilter.c文件
/**
*******************************************************************************
* @file ufilter.c
* @author xixizhk
*******************************************************************************
* @version V20210109 \n
* Initial version.
*******************************************************************************
*/
/**
*******************************************************************************
* @addtogroup Includes
* @{
*/
#include "ufilter.h"
#include "math.h"
/**
* @}
*/
/**
*******************************************************************************
* @addtogroup Definitions
* @{
*/
/**
* @}
*/
/**
*******************************************************************************
* @addtogroup Types
* @{
*/
/**
* @}
*/
/**
*******************************************************************************
* @addtogroup Constants
* @{
*/
/**
* @}
*/
/**
*******************************************************************************
* @addtogroup Variables
* @{
*/
/**
* @}
*/
/**
*******************************************************************************
* @addtogroup Macros
* @{
*/
/**
* @}
*/
/**
*******************************************************************************
* @addtogroup Functions
* @{
*/
/**
* @brief Initialize the handler of the 1st lowpass filter.
* @param _ufilter [In]: Pointer to the handler of the filter.
* @param _omega_c [In]: Cut frequency of the filter.
* @param _Ts [In]: Sample time.
* @retval None.
*/
void ufilter_lp1st_init
(
ufilter_lp1st_t *_ufilter,
float _omega_c,
float _Ts
)
{
/* Coefficients calculation */
_ufilter->b_0 = _omega_c * _Ts;
/**
* Origin expression:
* _ufilter->a_1 = -exp(-(_omega_c * _Ts)),
* which results in steady-state error.
*/
_ufilter->a_1 = -(1.0F - _omega_c * _Ts);
/* Reset intermediate variables */
ufilter_lp1st_reset(_ufilter);
}
/**
* @brief Callback function of the 1st lowpass filter.
* @param _ufilter [In]: Pointer to the handler of the filter.
* @param _input [In]: Input of the filter.
* @retval Output of the filter.
*/
float ufilter_lp1st_callback
(
ufilter_lp1st_t *_ufilter,
float _input
)
{
float output;
/* Calculate output */
output = _ufilter->b_0 * _input - _ufilter->a_1 * _ufilter->y_k_1;
/* Update intermediate variables */
_ufilter->y_k_1 = output;
/* Return output */
return output;
}
/**
* @brief Reset the handler of the 1st lowpass filter.
* @param _ufilter [In]: Pointer to the handler of the filter.
* @retval None.
*/
void ufilter_lp1st_reset
(
ufilter_lp1st_t *_ufilter
)
{
_ufilter->y_k_1 = 0;
}
/**
* @brief Initialize the handler of the 2nd lowpass filter.
* @param _ufilter [In]: Pointer to the handler of the filter.
* @param _omega_n [In]: Resonant frequency of the filter.
* @param _zeta [In]: Coefficient of damping.
* @param _Ts [In]: Sample time.
* @retval None.
*/
void ufilter_lp2nd_init
(
ufilter_lp2nd_t *_ufilter,
float _omega_n,
float _zeta,
float _Ts
)
{
/* Coefficients calculation */
_ufilter->b_1 = _omega_n * _Ts / sqrt(1 - _zeta * _zeta)
* exp(-_zeta * _omega_n * _Ts)
* sin(_omega_n * _Ts * sqrt(1 - _zeta * _zeta));
_ufilter->a_1 = -2 * exp(-_zeta * _omega_n * _Ts)
* cos(_omega_n * _Ts * sqrt(1 - _zeta * _zeta));
_ufilter->a_2 = exp(-2 * _zeta * _omega_n * _Ts);
/* Reset intermediate variables */
ufilter_lp2nd_reset(_ufilter);
}
/**
* @brief Callback function of the 2nd lowpass filter.
* @param _ufilter [In]: Pointer to the handler of the filter.
* @param _input [In]: Input of the filter.
* @retval Output of the filter.
*/
float ufilter_lp2nd_callback
(
ufilter_lp2nd_t *_ufilter,
float _input
)
{
float output;
/* Calculate output */
output = _ufilter->b_1 * _ufilter->x_k_1 - _ufilter->a_1 * _ufilter->y_k_1
- _ufilter->a_2 * _ufilter->y_k_2;
/* Update intermediate variables */
_ufilter->x_k_1 = _input;
_ufilter->y_k_2 = _ufilter->y_k_1;
_ufilter->y_k_1 = output;
/* Return output */
return output;
}
/**
* @brief Reset the handler of the 2nd lowpass filter.
* @param _ufilter [In]: Pointer to the handler of the filter.
* @retval None.
*/
void ufilter_lp2nd_reset
(
ufilter_lp2nd_t *_ufilter
)
{
_ufilter->x_k_1 = 0;
_ufilter->y_k_1 = 0;
_ufilter->y_k_2 = 0;
}
/**
* @brief Initialize handler of specified moving average handler.
* @param _ufilter [In]: Pointer to the handler of moving average.
* @param _N [In]: Length of integral buffer.
* @param _buffer [In]: Pointer to integral buffer.
* @retval None.
**/
void ufilter_ma_init
(
ufilter_ma_t *_ufilter,
unsigned int _N,
float *_buffer
)
{
unsigned int i;
_ufilter->N = _N;
_ufilter->buffer = _buffer;
_ufilter->index = 0;
_ufilter->offset = 0;
for (i = 0; i < _N; i++)
{
*(_ufilter->buffer + i) = 0;
}
}
/**
* @brief Callback function of specified moving average handler to
* calculate the output.
* @param _ufilter [In]: Pointer to the handler of moving average.
* @param _input [In]: Input of moving average.
* @param _W [In]: Length of window of moving average (1 <= W <= N).
* @retval Value of moving average.
**/
float ufilter_ma_callback
(
ufilter_ma_t *_ufilter,
float _input,
unsigned int _W
)
{
float tmp_float;
/* moving average.*/
float ave;
/* Integral value at the end of the window and its index. */
float int_W;
unsigned int int_W_index;
/* Limit the window. */
if (_W > _ufilter->N)
{
_W = _ufilter->N;
}
if (_W == 0)
{
_W = 1;
}
/* Update callback index and calculate integral. */
tmp_float = *(_ufilter->buffer + _ufilter->index);
_ufilter->index = (_ufilter->index + 1U) % _ufilter->N;
int_W_index = (_ufilter->index + _ufilter->N - _W) % _ufilter->N;
int_W = *(_ufilter->buffer + int_W_index);
*(_ufilter->buffer + _ufilter->index) = tmp_float + _input;
/* Determine the offset and add to the buffer. */
if ( _ufilter->index == 0U)
{
_ufilter->offset = *(_ufilter->buffer + _ufilter->index);
*(_ufilter->buffer + _ufilter->index) = 0.0F;
}
/* Calculate moving average. */
if (int_W_index >= _ufilter->index)
{
int_W -= _ufilter->offset;
}
ave = (*(_ufilter->buffer + _ufilter->index) - int_W) / ((float)_W);
/* Return the average. */
return ave;
}
/**
* @brief Reset the handler of the moving average filter.
* @param _ufilter [In]: Pointer to the handler of the filter.
* @retval None.
*/
void ufilter_ma_reset
(
ufilter_ma_t *_ufilter
)
{
unsigned int i;
for (i = 0; i < _ufilter->N; i++)
{
*(_ufilter->buffer + i) = 0.0F;
}
}
/**
* @}
*/
/**************************** ALL RIGHTS RESERVED *****************************/
参考文献
[1] Rlover_star. Simulink调用外部C代码的几种方法. 2023.11.17. https://blog.csdn.net/Rlover_star/article/details/127882271
标签:Simulink,ufilter,float,lp1st,C语言,filter,MATLAB,ma,lp2nd From: https://www.cnblogs.com/zysgy/p/17839223.html