一、理论

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

PID控制器的传递函数:

上式中,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

代入上式,得到

化简过程略,得到:

故离散化公式为:

方法二、传统计算方法

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

上式也是位置式PID。

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

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

比例部分:

积分部分:

由于

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

微分部分:

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

化简:

至此,只要需要了解离散时间,也就是执行本控制器算法的间隔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** \par<b>Description: </b><br>* 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 <DAVE.h>int main(void)
{uint32_t ref       = 3247.1304f;             //reference voltage 3.3 volts in steps of ADCuint32_t vout      = 2702.5139f;             //measured feedback voltage 3 volts in steps of ADCuint32_t compare_value;                      //CCU4/8 compare value for PWM generationfloat kp        = 0.001f;              //Proportional gain constantfloat ki        = 0.01f;              //Integral gain constantfloat kd        = 0.0f;              //Integral gain constantfloat limit_max = 1023.0f;                //maximum output for anti-windup schemefloat limit_min = 155.0f;                 //minimum output for anti-windup schemeXMC_CONTROL_LIB_PID_DATA_FLOAT_t handle;  //control data structureXMC_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 outputwhile(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.** \par<b>Description: </b><br>* 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 <br>** Example Usage:* @code#include <DAVE.h>int main(void)
{uint32_t ref       = 3247.1304f;             //reference voltage 3.3 volts in steps of ADCuint32_t vout      = 2702.5139f;             //measured feedback voltage 3 volts in steps of ADCuint32_t compare_value;                      //CCU4/8 compare value for PWM generationfloat kp        = 0.001f;              //Proportional gain constantfloat ki        = 0.01f;              //Integral gain constantfloat kd        = 0.0f;              //Integral gain constantfloat limit_max = 1023.0f;                //maximum output for anti-windup schemefloat limit_min = 155.0f;                 //minimum output for anti-windup schemeXMC_CONTROL_LIB_PI_DATA_FLOAT_t handle;  //control data structureXMC_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 outputwhile(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,可以让系统有微微的超调量。让电机运动有较好的快速性和稳定性。

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

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

PID控制器的离散化推导及其C语言实现相关推荐

  1. PID控制器的传递函数推导

    传递函数的定义: 传递函数是指零初始条件下线性系统响应(即输出)量的拉普拉斯变换(或z变换)与激励(即输入)量的拉普拉斯变换之比.记作G(s)=Y(s)U(s)G(s)=Y(s)U(s)G_{(s)} ...

  2. 一文读懂pid控制器

    文章目录 PID控制器 1. 控制器 1.1 电机速度控制系统 1.2 温度或水位控制系统 1.3 小小总结 2. PID 3. 模拟式PID 4. 数字式PID 4.1 位置式PID算法 4.1.2 ...

  3. 实验三、数字PID控制器的设计

    实验三.数字PID控制器的设计 --- 直流闭环调速实验 一.实验目的 1.理解晶闸管直流单闭环调速系统的数学模型和工作原理;. 2. 掌握PID控制器参数对控制系统性能的影响; 3. 能够运用MAT ...

  4. 20190109基于贝加莱PLC 用C语言构建PID控制器 与应用一

    void _CYCLIC PIDRegulation(void) { // // typedef struct // // { // // float setpoint; //设定值 // // fl ...

  5. PID控制器改进笔记之六:改进PID控制器之参数设定

      前面我们发布了一系列PID控制器相关的文章,包括经典PID控制器以及参数自适应的PID控制器.这一系列PID控制器虽说实现了主要功能,也在实际使用中取得了良好效果,但还有很多的细节部分可以改进以提 ...

  6. PID控制器开发笔记之九:基于前馈补偿的PID控制器的实现

    对于一般的时滞系统来说,设定值的变动会产生较大的滞后才能反映在被控变量上,从而产生合理的调节.而前馈控制系统是根据扰动或给定值的变化按补偿原理来工作的控制系统,其特点是当扰动产生后,被控变量还未变化以 ...

  7. PID控制器开发笔记之七:微分先行PID控制器的实现

    前面已经实现了各种的PID算法,然而在某些给定值频繁且大幅变化的场合,微分项常常会引起系统的振荡.为了适应这种给定值频繁变化的场合,人们设计了微分先行算法. 1.微分先行算法的思想 微分先行PID控制 ...

  8. PID控制器开发笔记之一:PID算法原理及基本实现

           在自动控制中,PID及其衍生出来的算法是应用最广的算法之一.各个做自动控制的厂家基本都有会实现这一经典算法.我们在做项目的过程中,也时常会遇到类似的需求,所以就想实现这一算法以适用于 ...

  9. 微分先行PID控制器的实现

    理论部分参考:https://blog.csdn.net/foxclever/article/details/80633275 这里附上写的matlab程序: clear all; close all ...

  10. PID控制器及其C++实现

    PID控制器原理 PID控制器实际上是对偏差的控制,其原理图如下: 其数学的表达如下: u(x)=Kp(err(t)+1T.∫err(t)dt+TDderr(t)dt)u(x)=Kp(err(t)+1 ...

最新文章

  1. 在plsql里面怎么去掉空行_盐渍樱花怎么做?详细做法告诉您,一年都不会坏,学会再也不用买...
  2. 干货 | YOLOV5 训练自动驾驶数据集,并转Tensorrt,收藏!
  3. linux下的last以及lastb命令
  4. 【Linux网络编程】原始套接字实例:发送 UDP 数据包
  5. php人才招聘系统描述,基于ThinkPHP框架的人才招聘网站系统PHP源码
  6. 田亮:坚信大数据的变革力量
  7. php ssh 管理服务器,php 利用ssh执行远程或本地liunx服务器命令
  8. DOM(二)——修改内容、属性、样式
  9. Android studio吧,Android Studio 连接真机
  10. 显式锁(二)Lock接口与显示锁介绍
  11. armv6、armv7、armv7s、armv8、armv64及其i386、x86_64区别
  12. VMware激活密钥
  13. R语言聚类分析-kmeans聚类分析实战
  14. keyshot渲染很慢_提高Keyshot逼真渲染的小技巧!
  15. 删除之后在计算机操作中快捷键,计算机中删除的快捷键是什么
  16. 关于安装wordcloud库的那些事
  17. [推荐]“痘痘”与所对应的疾病
  18. java组织机构代码验证规则
  19. Redis入门总结(一):redis配置文件,五种数据结构,线程模型和持久化方式
  20. SVN服务器迁移方法(Windows环境)

热门文章

  1. Android开发应用apk文件发送到微信打不开解决方案
  2. Adobe Acrobat 如何通过书签制作多级目录
  3. JEP 379:将低暂停时间的垃圾收集器Shenandoah推向生产
  4. matlab simulink单相桥式逆变电路
  5. 平面方程(Plane Equation)求解方法
  6. 漫画:什么是 B+ 树?
  7. 优秀IT顾问的七大能力之一--专业技术能力
  8. 2022最推荐的四款免费bi工具
  9. 武汉php东和,武汉探东之旅,未完成
  10. 使用C++调用Socket接口实现简易TCP服务器