STM32应用(十)经典控制算法PID(单级和串级)原理与代码实现

您所在的位置:网站首页 串级控制系统应用举例讲解图表 STM32应用(十)经典控制算法PID(单级和串级)原理与代码实现

STM32应用(十)经典控制算法PID(单级和串级)原理与代码实现

2024-07-07 09:07| 来源: 网络整理| 查看: 265

文章目录 1.PID原理1.1 P I D三个参数简单理解1.2 P I D1.3 PI PD PID适用系统 2.串级PID原理3.PID代码3.1 单级PID3.1.1 初始化PID结构体3.1.2 单级PID计算3.1.3PID初始化3.1.4 清空PID 3.2 串级PID3.2.1 初始化串级PID结构体3.2.2 串级PID计算 4.PID的使用4.1 定义PID结构体并初始化4.2 定义电机速度函数4.3 在检测霍尔码盘时发送速度给电机4.4 实验效果

1.PID原理

PID是什么,P,I,D的分别功能

你和PID调参大神之间,就差这篇文章!

1.1 P I D三个参数简单理解

P(比例): 简单来说,P就是凉了加热水,热了加凉水。比目标值小,我就增加一点,比目标值大,我就减小一点。(现在) P可能出现的问题: 1.P太小,达到目标值需要花费很长的时间,而且会有稳态误差。2.P太大,达到目标值时可能会一直震荡。

I(积分): 将一段时间内的误差累积起来加到输出上,可以消除历史误差对当前实际曲线的影响,提高系统的稳定性。 (过去) I可能出现的问题: 1.I太小,可以消除稳态误差,但太慢了,对于某些需要很快响应的系统,显然不能满足要求。2.I太大,累计误差占比过大,就会出现抖动现象,难以收敛。

D(微分): 减小最大超调量。(下图中③就是最大超调量。) 可以有效减小震动的幅度。让曲线收敛更快 (未来) D可能出现的问题: 1.D太小,作用小,时间长。2.D太大,为了减小超调量,补偿的过多,导致震荡很久。 在这里插入图片描述

1.2 P I D

先调P,逐渐增加P直到系统出现震荡,将当前值乘0.7就是较为合适的值。 再调I,将稳态误差逐渐降低。 后调D,将最大超调量降到最低。

1.3 PI PD PID适用系统

PI:响应速度要求不那么高的系统。 PD:大惯性系统。超调量太大。 PID:都可以。

网上将PID原理太多太多了,我的理解也都是参见上面的内容。认真看肯定有收获。

2.串级PID原理

【串级PID】浅谈串级PID作用及意义——快速理解串级PID结构优势

这里个人理解就是,单机PID就是稳定速度。而需要带位置和角度的就要用串级PID了。常用于平衡车,板球系统等。 而转速闭环称为串级PID的内环,位置 (角度) 闭环称为串级PID的外环。其实也很好理解,位移是速度的积分,只有速度慢慢稳定,位置才能确定。

3.PID代码 3.1 单级PID 3.1.1 初始化PID结构体 typedef struct _PID { float kp,ki,kd; float error,lastError;//误差、上次误差 float integral,maxIntegral;//积分、积分限幅 float output,maxOutput;//输出、输出限幅 }PID; 3.1.2 单级PID计算 #define LIMIT(x,min,max) (x)=(((x)=(max))?(max):(x))) //单级pid计算 void PID_SingleCalc(PID *pid,float reference,float feedback) { //更新数据 pid->lastError=pid->error; pid->error=reference-feedback; //计算微分 pid->output=(pid->error-pid->lastError)*pid->kd; //计算比例 pid->output+=pid->error*pid->kp; //计算积分 pid->integral+=pid->error*pid->ki; LIMIT(pid->integral,-pid->maxIntegral,pid->maxIntegral);//积分限幅 pid->output+=pid->integral; //输出限幅 LIMIT(pid->output,-pid->maxOutput,pid->maxOutput); } 3.1.3PID初始化 void PID_Init(PID *pid,float p,float i,float d,float maxI,float maxOut) { pid->kp=p; pid->ki=i; pid->kd=d; pid->maxIntegral=maxI; pid->maxOutput=maxOut; } 3.1.4 清空PID //清空一个pid的历史数据 void PID_Clear(PID *pid) { pid->error=0; pid->lastError=0; pid->integral=0; pid->output=0; } 3.2 串级PID 3.2.1 初始化串级PID结构体 typedef struct _CascadePID { PID inner;//内环 PID outer;//外环 float output;//串级输出,等于inner.output }CascadePID; 3.2.2 串级PID计算 //串级pid计算 void PID_CascadeCalc(CascadePID *pid,float angleRef,float angleFdb,float speedFdb) { PID_SingleCalc(&pid->outer,angleRef,angleFdb);//计算外环(角度环) PID_SingleCalc(&pid->inner,pid->outer.output,speedFdb);//计算内环(速度环) pid->output=pid->inner.output; } 4.PID的使用

STM32应用(九)编码器及其测速原理、L298N电机驱动控制编码器电机

在这篇博客的配置下,只需要修改部分代码。以单级PID为例子。

4.1 定义PID结构体并初始化 PID pid; void Motor_Init(void) { PID_Init(&pid,10,0,0,1000,1000); HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL); //开启编码器定时器 __HAL_TIM_ENABLE_IT(&htim1,TIM_IT_UPDATE); //开启编码器定时器更新中断,防溢出处理 HAL_TIM_Base_Start_IT(&htim6); //开启10ms定时器中断 HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); //开启PWM __HAL_TIM_SET_COUNTER(&htim1, 10000); //编码器定时器初始值设定为10000 motor.loopNum = 0; //防溢出 } 4.2 定义电机速度函数 void Motor_Send() { float output = 0; PID_SingleCalc(&pid, motor.targetSpeed, motor.speed); output = pid.output; if(output > 0) //正转 { __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, (uint32_t)output); IN1(1); IN2(0); } else //反转 { __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, (uint32_t)(-output)); IN1(0); IN2(1); } } 4.3 在检测霍尔码盘时发送速度给电机 if(htim->Instance==htim6.Instance) //10ms中断 { int16_t pluse = COUNTERNUM - RELOADVALUE/2; motor.totalAngle = pluse + motor.loopNum * RELOADVALUE/2; motor.speed = (float)(motor.totalAngle - motor.lastAngle)/(4*13*RR)*6000; //进行速度计算,根据前文所说的,4倍频,编码器13位,减速比30,再乘以6000即为每分钟输出轴多少转 motor.lastAngle = motor.totalAngle; //更新转过的圈数 Motor_Send();//发送速度 } 4.4 实验效果

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3