完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
基于stm32的PID算法粗略讲解
一、PID算法的分类 增量式与位移式的区别 1.输出不同:位置PID控制的输出与整个过去状态有关,并且使用了误差的累加值;而增量PID的输出仅与当前拍和前两拍的误差有关,因此位置PID控制的累积误差相对较大。 2.是否有积分部分:增量PID控制输出为控制量增量,没有积分功能,因此该方法适用于带有积分部分的对象,例如步进电机等。 ,但位置PID适用于执行没有积分部件的对象,例如电动液压伺服阀。 3.是否具有记忆功能:由于增量PID输出是控制量增量,因此,如果计算机出现故障,则故障影响较小,执行器本身具有记忆功能,该功能仍可保留且不会严重影响系统的工作,而位置输出直接对应于对象的输出,因此对系统影响较大。 但通常情况下使用增量式 二、PID的三个参数 1. kP比例 成比例地反映控制系统的偏差信号e(t),偏差一旦产生,控制器立即产生控制作用,以减小偏差。当仅有比例控制时系统输出存在稳态误差(Steady-state error)。 P参数越小比例作用越强,动态响应越快,消除误差的能力越强。通常将P参数由大向小调,以能达到最快响应又无超调(或无大的超调)为最佳参数。 2. kI积分 为消除静差,提高系统的无差度。积分作用的强弱取决于积分时间常数T,T越大,积分作用越弱,反之则越强。 3. KD微分 反映偏差信号的变化趋势,并能在偏差信号变得太大之前,在系统中引入一个有效的早期修正信号,从而加快系统的动作速度,减少调节时间。在微分控制中,控制器的输出与输入误差信号的微分(即误差的变化率)成正比关系。 D越大,微分作用越强,D越小,微分作用越弱。系统调试时通常把D从小往大调,具体参数由试验决定。 三.增量式程序 /************************** .h文件******************************/ #ifndef _pid_H #define _pid_H #define MODEL_P 1 #define MODEL_PI 2 #define MODEL_PID 3 typedef struct { u8 choose_model; //使用哪个模式调节,以方便分布调试 float curr; //当前值 float set; //设定值 float En; //当前时刻误差值 float En_1; //前一时刻误差值 float En_2; //前二时刻误差值 float Kp; //比例系数 float T; //每隔T控制器输出一次PID运算结果 u16 Tdata; //判断PID周期到没到 float Ti; //积分时间常数 float Td; //微分时间常数 float Dout; //增量PID计算本次应该输出的增量值-本次计算的结果 float OUT0; //一个维持的输出,防止失控 short currpwm; //当前的pwm宽度 u16 pwmcycle; //pwm周期 }PID; extern u8 STATUS; extern PID pid; void PID_Init(void); //增量式PID初始化 void pid_calc(void); //pid计算 并输出 /************************** .c文件******************************/ #endif #include "pid.h" #include "PWM_Config.h" #include "USART_Config.h" //USART设置 PID pid; void PID_Init() // { pid.choose_model = MODEL_PID; pid.T=330; //采样周期,定时器使用1ms,则最小执行PID的周期为330ms pid.set =280; //用户设定值 pid.Kp=0.5; //比例系数 pid.Ti=40; //微分系数常数 pid.Td=10; //积分时间常数 pid.OUT0=0; //一个维持的输出 pid.pwmcycle = 330; //PWM的周期 } void pid_calc() { float dk1;float dk2; float t1,t2,t3; if(pid.Tdata < (pid.T)) //最小计算周期未到 { return ; } pid.Tdata = 0; pid.En=pid.set-pid.curr; //本次误差 dk1=pid.En-pid.En_1; //本次偏差与上次偏差之差 dk2=pid.En-2*pid.En_1+pid.En_2; t1=pid.Kp*dk1; //比例 t2=(pid.Kp*pid.T)/pid.Ti; //积分 t2=t2*pid.En; t3=(pid.Kp*pid.Td)/pid.T; //微分 t3=t3*dk2; switch(pid.choose_model) { case MODEL_P: //仅用P pid.Dout= t1; printf("使用P运算rn") ; break; case MODEL_PI: //仅用PI pid.Dout= t1+t2; printf("使用PI运算rn") ; break; case MODEL_PID: //用PID pid.Dout= t1+t2+t3; printf("使用PID运算rn") ; break; } pid.currpwm+=pid.Dout; //本次应该输出的PWM printf("PID算得的OUT:t%drn",(int)pid.currpwm) ; if(pid.currpwm>pid.pwmcycle) //确保值在0-pid.pwmcycle之间 { pid.currpwm=pid.pwmcycle; } if(pid.currpwm<0) { pid.currpwm=0; } printf("实际输出使用的OUT:t%drn",(int)pid.currpwm) ; pid.En_2=pid.En_1; pid.En_1=pid.En; } 总结 1首先整定比例部分。将比例系数Kp由小变大 2置积分时间Ti为一较大值,并将经第一步整定很到的比例系数略为缩小(如缩小为原值的4/5),观察系统响应的情况 3 比例系数由小到大,然后找出超调小的Kp 4 积分时间常数Ti由大变小,适当调整Kp 5 微分时间常数Td由小变大,适当调整Ti和Kp 6 KP设定,最初使用1,假如控制之后实际值比设定值小不够,那就增大。反之就减少。 7 TI设定,数据先很大。看效果 8 如果TI加进去之后数据很久才变化到目标值就逐渐减小。如果TI减少到执行几次都是比设定值大的时候那就逐渐增大 9如果刚加进去变化很快,并且超调很高,就增大来调节 10 积分就看情况调节。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1614 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1541 浏览 1 评论
970 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
682 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1592 浏览 2 评论
1863浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
644浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
515浏览 3评论
531浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
504浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-21 19:20 , Processed in 0.803393 second(s), Total 79, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号