我是靠谱客的博主 大胆老虎,最近开发中收集的这篇文章主要介绍c语言中离散化,PID控制器的离散化推导及其C语言实现,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、理论

下图是采用了PID控制器的闭环控制策略。

ad62754283ea87703e69143e01c8ff10.png

PID控制器的传递函数:

a57e31710a36e5432a5f1b82eef44d30.png

上式中,Y是控制器的输出,U是控制器的输入。

有时候,在Matlab仿真中已经调好了Kp和Ki、Kd参数,但是离散化后,系数和离散时间有关。因此需要重新计算系数。

方法一、用公式替代s算子

用Trapezoid(Tustin)方法离散化PID控制器。另外更多的传递函数离散化方法请浏览:https://blog.csdn.net/qq_27158179/article/details/82739641#2%E3%80%81%E7%A6%BB%E6%95%A3%E5%8C%96%E9%A2%84%E5%A4%87%E7%9F%A5%E8%AF%86

a57e31710a36e5432a5f1b82eef44d30.png

d83bb7a854db7054c2ab719f8f008e6b.png代入上式,得到

691c62cedf180c2a804658713013804b.png

化简过程略,得到:

3e649d11b28d98753bd116f09c7057a7.gif

故离散化公式为:

a1b84f82814eb5e63093311c2c6508db.gif

方法二、传统计算方法

PID控制器分为比例环节、积分环节、微分环节。如下:

d55396b3fa5a880e485e204f5a91f2cd.png

上式也是位置式PID。

如果要转换为增量式,过程如下:

我们把PID控制器分为比例环节、积分环节、微分环节。由于控制器的输出就是三个环节的叠加,因此可以分别计算每个环节:

比例部分:

d3e9ae0912a9dbb14b83d617d70c669c.png

积分部分:

21e6a85b6283abb1aa56bba680ad17cf.png

由于

3361c34246a2594d0732be008bfe9aae.png

因此,可以用I(k-1)替代冗长的u(i),i=1,2,...,k的累加。

d332f0abba9afcf45f3ad29e71bcb8f0.png

微分部分:

bf0cc5997a54b7aded4bced3f37d3123.png

把比例、积分、微分三部分叠加,可以得到公式:

71456fec929b5e8396619a5a971298c3.png

化简:

cc39c23726e2c20f29f7c020e88ceeb0.png

至此,只要需要了解离散时间,也就是执行本控制器算法的间隔Ts,即可把已经在上位机仿真模型中调好的Kp、Ki、Kd、通过计算转换成u(k)和u(k-1)的系数。

二、实践

上机,以下代码主要来自XMC™ Control Library。Infineon提供的library中有PI控制器,我在这个基础上增加了微分环节。

1、PID.c

/*

* PID.c

*

* Created on: 2018年10月1日

* Author: xxJian

*/

#include "PID.h"

/* Initializes a PID controller with anti-windup scheme and programmable output limit saturation. */

void XMC_CONTROL_LIB_PIDFloatInit(XMC_CONTROL_LIB_PID_DATA_FLOAT_t* handle_ptr,

volatile float* ref_ptr, volatile float* fdbk_ptr,

float kp, float ki, float kd,

float limit_min, float limit_max,

volatile uint32_t* out)

{

//memset((void *)handle_ptr, 0, sizeof(*handle_ptr));

handle_ptr->fdbk_ptr = fdbk_ptr; /**< pointer to ADC register which is used for feedback */

handle_ptr->ref_ptr = ref_ptr; /**< ADC ref */

handle_ptr->kp = kp; /*coefficient filter current input*/

handle_ptr->ki = ki; /*coefficient filter input one previous*/

handle_ptr->kd = kd;

handle_ptr->out_limit_max = limit_max; /*maximum output saturation*/

handle_ptr->out_limit_min = limit_min; /*output saturation min for filter implementation*/

handle_ptr->out = out;

}

void XMC_CONTROL_LIB_PIDFloat(XMC_CONTROL_LIB_PID_DATA_FLOAT_t* handle_ptr)

{

/*

* I(k) = Ki * error + I(k-1)

* U(k) = Kp * error + I(k) + Kd * (error - error_1)

* if(min < U(k) < max){I(k-1) = I(k);}//Anti wind-up

*/

handle_ptr->error = *(handle_ptr->ref_ptr) - *(handle_ptr->fdbk_ptr);

handle_ptr->ik = (handle_ptr->error * handle_ptr->ki) + handle_ptr->ik_1;

handle_ptr->uk = (handle_ptr->error * handle_ptr->kp) + handle_ptr->ik + handle_ptr->kd*(handle_ptr->error - handle_ptr->error_1);

if (handle_ptr->uk > handle_ptr->out_limit_max)

{

handle_ptr->uk = handle_ptr->out_limit_max; /*Disable anti wind up filter*/

}

else if (handle_ptr->uk < handle_ptr->out_limit_min)

{

handle_ptr->uk = handle_ptr->out_limit_min; /*Disable anti wind up filter*/

}

else

{

handle_ptr->ik_1 = handle_ptr->ik; /*Enable anti wind up filter*/

}

handle_ptr->error_1 = handle_ptr->error;

*(handle_ptr->out) = (uint32_t)handle_ptr->uk;

}

2、PID.h

/*

* PID.h

*

* Created on: 2018年10月1日

* Author: xxJian

*/

#ifndef PID_H_

#define PID_H_

#include "main.h"

#include "stm32f4xx_hal.h"

/**

* @brief PI floating point data & coefficients structure

*/

typedef struct XMC_CONTROL_LIB_PID_DATA_FLOAT

{

volatile float* fdbk_ptr; /**< Pointer to feedback, generally ADC result register*/

volatile float* ref_ptr; /**< Pointer to reference */

float error; /*!< PID error signal (reference value - feedback value), error[k] */

float error_1; /*!< PID error signal (reference value - feedback value), error[k-1] */

float kp; /*!< Proportional gain Kp constant */

float ki; /*!< Integral gain Ki constant*/

float kd; /*!< Differential gain Ki constant*/

float out_limit_max; /*!< Maximum value of the PI output */

float out_limit_min; /*!< Minimum value of the PI output */

float uk; /*!< PI output U[k] */

float ik; /*!< Integral result I[k] */

float ik_1; /*!< Integral result I[k-1] */

volatile uint32_t* out; /*!< PI Output after anti-windup scheme */

} XMC_CONTROL_LIB_PID_DATA_FLOAT_t;

/*******************************************************************************************************************/

/**

* @brief Initializes the data structure of XMC_CONTROL_LIB_PIFloat() API.

* @param handle_ptr pointer to XMC_CONTROL_LIB_PI_DATA_FLOAT_t structure

* @param ref_ptr Pointer to reference voltage variable

* @param fdbk_ptr pointer to feedback variable

* @param kp Proportional gain constant

* @param ki Integral gain constant

* @param ki Differential gain constant

* @param limit_max maximum output limit for anti-windup scheme

* @param limit_min minimum output limit for anti-windup scheme

* @param out Pointer to PI output variable

*

* parDescription:

* The function can be used to initialize the data structure XMC_CONTROL_LIB_PI_DATA_FLOAT_t used by

* XMC_CONTROL_LIB_PIFloat() API.

*

* Example Usage:

* @code

#include int main(void)

{

uint32_t ref = 3247.1304f; //reference voltage 3.3 volts in steps of ADC

uint32_t vout = 2702.5139f; //measured feedback voltage 3 volts in steps of ADC

uint32_t compare_value; //CCU4/8 compare value for PWM generation

float kp = 0.001f; //Proportional gain constant

float ki = 0.01f; //Integral gain constant

float kd = 0.0f; //Integral gain constant

float limit_max = 1023.0f; //maximum output for anti-windup scheme

float limit_min = 155.0f; //minimum output for anti-windup scheme

XMC_CONTROL_LIB_PID_DATA_FLOAT_t handle; //control data structure

XMC_CONTROL_LIB_PIDFloatInit(&handle,

&ref, &vout,

kp, ki, kd,

limit_min, limit_max,

&compare_value

);

XMC_CONTROL_LIB_PIDFloat(&handle);

//compare_value will holds the output

while(1)

{

}

return 0;

}

* @endcode

*

*/

void XMC_CONTROL_LIB_PIDFloatInit(XMC_CONTROL_LIB_PID_DATA_FLOAT_t* handle_ptr,

volatile float* ref_ptr, volatile float* fdbk_ptr,

float kp, float ki, float kd,

float limit_min, float limit_max,

volatile uint32_t* out);

/**

* @brief Calculates a proportional integral controller output with programmable output limits for anti-windup scheme.

* @param handle_ptr XMC_CONTROL_LIB_PI_DATA_FLOAT_t structure with proper input values.

*

* parDescription:

* The function can be used to implement control loop feedback mechanism which commonly used in industrial applications.

* A PI controller continuously calculates an error value as the difference between a reference and a feedback.

*

* I[k] = Ki * error + I[k-1]

* U[k] = Kp * error + I[k] + Kd* (error[k]-error[k-1])

* if(min < U[k] < max){I[k-1] = I[k];}//Anti wind-up

*

* Example Usage:

* @code

#include int main(void)

{

uint32_t ref = 3247.1304f; //reference voltage 3.3 volts in steps of ADC

uint32_t vout = 2702.5139f; //measured feedback voltage 3 volts in steps of ADC

uint32_t compare_value; //CCU4/8 compare value for PWM generation

float kp = 0.001f; //Proportional gain constant

float ki = 0.01f; //Integral gain constant

float kd = 0.0f; //Integral gain constant

float limit_max = 1023.0f; //maximum output for anti-windup scheme

float limit_min = 155.0f; //minimum output for anti-windup scheme

XMC_CONTROL_LIB_PI_DATA_FLOAT_t handle; //control data structure

XMC_CONTROL_LIB_PIDFloatInit(&handle,

&ref, &vout,

kp, ki, kd,

limit_min, limit_max,

&compare_value

);

XMC_CONTROL_LIB_PIDFloat(&handle);

//compare_value will holds the output

while(1)

{

}

return 0;

}

* @endcode

*

*/

void XMC_CONTROL_LIB_PIDFloat(XMC_CONTROL_LIB_PID_DATA_FLOAT_t* handle_ptr);

#endif /* PID_H_ */

在STM32开发板上和直流有刷电机连接,电机上的霍尔编码器和单片机的TIM3连接。对电机进行PID闭环控制。由于我不喜欢微分环节(某些地方不喜欢振荡,微分环节会引入振荡,即闭环控制的输出参数会围绕着参考值上下波动),因此把Kd整为0.把Kp和Ki调节到合适的参数,可以让电机稳定在一个转速。我想把电机控制到1.6转每秒。把实时的转速通过USB转UART上传到电脑,使用STLINK可以直接改变Kp和Ki的值。Kp=100,Ki=0.5,可以让系统有微微的超调量。让电机运动有较好的快速性和稳定性。

ca4a8950814cc1dc50832f4ce2b6f067.png

现在TI的资料,controlSuite里面的软件,都用上汇编语言了,十分不方便移植到别的单片机中。看来围绕着Arduino、树莓派等开源活动,已经动摇电子界了。工程师们的知识产权有了提高,在开源所带来的声誉,和闭源所带来的安全,有了一个更好的平衡点。

特别鸣谢:www.infineon.com/xmc。

最后

以上就是大胆老虎为你收集整理的c语言中离散化,PID控制器的离散化推导及其C语言实现的全部内容,希望文章能够帮你解决c语言中离散化,PID控制器的离散化推导及其C语言实现所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(36)

评论列表共有 0 条评论

立即
投稿
返回
顶部