完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
(O)关于程序BUG说明,看最后面的红色字体,视频和源代码中都没有说明
(一)PID控制算法(P:比例 I:积分 D:微分) (二)首先先说明原理,使用的是数字PID算法,模拟PID算法在计算机这样的系统中是不能够直接使用的,数字PID算法又分为位置式PID控制算法和增量式PID控制算法,那么下面从原理上说明这两种算法 (三)原理分析如图 (四)从上面图中我们可以得到定义 定义变量 用户设定值: SV 当前值(实际值): PV 偏差: E = SV - PV (五)如果我们在一段时间内就从传感器读取一个值,那么我们就可以得到一个实际值的数据序列,,那么我们也会得到一个偏差值的序列 读取时间: t(1) t(2) ------ t(k-1) t(k) 读取到的值: X(1) X(2) ------ X(k-1) X(k) 偏差值: E(1) E(2) ------ E(k-1) E(k) 那么我们从偏差值中可以知道: E(X) 》 0 说明未达标 E(X) = 0 说明正好达标 E(X) 《 0 说明超标 (六)比例控制(P),作用:对偏差起到及时反映的作用,一旦产生偏差,控制器立即做出反映… 定义: 比例系数:Kp (根据系统进行调节) 比例输出:POUT = Kp * E(k) POUT = Kp * E(k) + OUT0 OUT0说明:OUT0是防止E(K) = 0 时候比例控制不作用,所以添加个OUT0进去,OUT0可以根据系统定义大小 Kp说明:如果我们得到一个偏差之后,将偏差进行放大或者缩小来让控制器进行控制 (七)积分控制(I),作用:消除静差… 从上面我们得到偏差序列: 偏差值: E(1) E(2) ------ E(k-1) E(k) 定义,历史偏差值之和:S(k) = E(1) + E(2) + 。。.。 + E(k-1) + E(K) 定义,积分输出: IOUT = Kp * S(k) + OUT0 (八)微分控制(D),作用:反映偏差信号的变化趋势… 从上面我们得到偏差序列: 偏差值: E(1) E(2) ------ E(k-1) E(k) 定义,偏差之差:D(k) = E(k) - E(k-1) 定义,微分输出:DOUT = Kp * D(k) + OUT0 (九)那么我们从上面就能得出PID的控制算法 PIDOUT = POUT + IOUT + DOUT = (Kp * E(k) + OUT0) + (Kp * S(k) + OUT0) + (Kp * D(k) +OUT0) = Kp * (E(k) + S(k) + D(k)) + OUT0 OUT0防止PIDOUT = 0 时候算法还有输出,防止失去控控制 比例(P):考虑当前 积分(I):考虑历史 微分(D):考虑未来 (十)位置式PID,上面只是简单的说明了一下原理,那么实际的数字PID控制算法中,额,那个变换公式打不出来,自行百度,这里就直接打出结果 Ti:积分常数 TD:微分常数 T:计算周期 上面两个是变化后的积分和微分的那个,那么我们把上面的两个替换到第九点中,我们就得到位置上PIDOUT的公式,两个式子是一样的 (十一)增量式PID,本次基础上加上多少偏差:△OUT /分割线**/ (十二)上面的只是PID的原理说明,那么数字PID的公式是 (十三)那么我们将上面的公式通过通过C语言写出来 位置式PID #ifndef _pid_ #define _pid_ #include “stm32f10x_conf.h” #define MODEL_P 1 #define MODEL_PI 2 #define MODEL_PID 3 typedef struct { u8 choose_model; //使用哪个模式调节 float Sv; //用户设定值 float Pv; //当前值,实际值 float Kp; //比例系数 float T; //PID计算周期--采样周期 u16 Tdata; //判断PID周期到没到 float Ti; //积分时间常数 float Td; //微分系数 float Ek; //本次偏差 float Ek_1; //上次偏差 float SEk; //历史偏差之和 float Iout; //积分输出 float Pout; //比例输出 float Dout; //微分输出 float OUT0; //一个维持的输出,防止失控 float OUT; //计数最终得到的值 u16 pwmcycle;//pwm周期 }PID; extern PID pid; //存放PID算法所需要的数据 void PID_Calc(void); //pid计算 void PID_Init(void); //PID初始化 #endif #include “pid.h” #include “PWM_Config.h” #include “USART_Config.h” //USART设置 PID pid; //存放PID算法所需要的数据 void PID_Init() { pid.choose_model = MODEL_PID; pid.T=330; //采样周期,定时器使用1ms,则最小执行PID的周期为330ms pid.Sv=280; //用户设定值 pid.Kp=0.5; //比例系数 pid.Ti=180; //积分时间 pid.Td=1; //微分时间 pid.OUT0=0; //一个维持的输出 pid.pwmcycle = 330; //PWM的周期 } void PID_Calc() //pid计算 { float DelEk; //本次和上次偏差,最近两次偏差之差 float ti,ki; float td; float kd; float out; if(pid.Tdata 《 (pid.T)) //最小计算周期未到 { return ; } pid.Tdata = 0; pid.Ek=pid.Sv-pid.Pv; //得到当前的偏差值 pid.Pout=pid.Kp*pid.Ek; //比例输出 pid.SEk+=pid.Ek; //历史偏差总和 DelEk=pid.Ek-pid.Ek_1; //最近两次偏差之差 ti=pid.T/pid.Ti; ki=ti*pid.Kp; pid.Iout=ki*pid.SEk*pid.Kp; //积分输出 /*注意:上面程序中多了个pid.Kp,原程序中有,请自动删除,正确的应该是pid.Iout=ki*pid.SEK */ td=pid.Td/pid.T; kd=pid.Kp*td; pid.Dout=kd*DelEk; //微分输出 switch(pid.choose_model) { case MODEL_P: out= pid.Pout; printf(“使用P运算rn”) ; break; case MODEL_PI: out= pid.Pout+ pid.Iout; printf(“使用PI运算rn”) ; break; case MODEL_PID: out= pid.Pout+ pid.Iout+ pid.Dout; printf(“使用PID运算rn”) ; break; } printf(“PID算得的OUT:t%drn”,(int)out) ; // /*判断算出的数是否符合控制要求*/ if(out》pid.pwmcycle) //不能比PWM周期大,最大就是全高吗 { pid.OUT=pid.pwmcycle; } else if(out《0) //值不能为负数 { pid.OUT=pid.OUT0; } else { pid.OUT=out; } printf(“实际输出使用的pid.OUT:t%drn”,(int)pid.OUT) ; pid.Ek_1=pid.Ek; //更新偏差 Turn_Angle((int)pid.OUT); //输出PWM } 2.增量式PID #ifndef _pid_ #define _pid_ #include “stm32f10x_conf.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 PIDParament_Init(void); /*增量式PID初始化*/ void pid_calc(void); /*pid计算 并输出*/ #endif #include “pid.h” #include “PWM_Config.h” #include “USART_Config.h” //USART设置 PID pid; void PIDParament_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() //pid?? { 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: pid.Dout= t1; printf(“使用P运算rn”) ; break; case MODEL_PI: pid.Dout= t1+t2; printf(“使用PI运算rn”) ; break; case MODEL_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之间,不然的话PWM怎么输出 { 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; Turn_Angle(pid.currpwm); //输出PWM } (十五)上面我们贴出来位置式PID算法和增量式PID算法的核心部分了,但是上面的理论上可以直接移植,添加一些还没有定义的变量就好了,下面是具体的演示工程 024——PID算法整定 (一)首先在使用PID算法之前先进行基础的设置 PWM正脉冲控制输出开 传感器曲线随着PWM占空比越大而越大 传感器在环境下情况下最低数据 ,和最高数据。 设定值不能超过这两个范围 (二)凑试法的基本方法是:对参数实行先比例,后积分,再微分的整定步踩具体步骤如下: 1)首先先只整定比例部分。将比例系数Kp由小变大,观察系统响应的变化情况,直到得到反应快、超调小的响应曲线。如果系统没有静差或静差小到允许的范围内,那么只需要比例控制器即可满足要求。 2)整定积分时间常数。在比例控制下系统的静差不满足设计要求时,则需要采用积分环节来消除静差。整定时,首先置积分时间Ti为一较大值,并将经第一步整定很到的比例系数略为缩小(如缩小为原值的4/5),观察系统响应的情况,然后根据观察的情况来减小积分时间常数,同时比例系数也可能缩小,使系统消除静差的同时能够获得良好的动态性值在此过程中,在此过程可根据响应曲线的好坏反复改变比例系数与积分时间常数,以期得到满意的控制过程与整定参数。 3)整定微分时间常数。若使用比例积分控制器消除了静差,但动态过程经反复调胜仍不能满意(主要是响应速度达不到要求),则可加人微分环节,构成PID控制器。整定时先置。较小的微分时间常数,同时比例系数略微减小、 积分时间常数略微增大,观察系统师应的情况。然后加大微分时间常数,比例系数、积分时间常数相应调整,反复调整,直到得满意的控制过程和整定参数。 (三)总结试凑法 比例系数有小到大,然后找出超调小的Kp 积分时间常数Ti由大变小,适当调整Kp 微分时间常数Td由小变大,适当调整Ti和Kp (四)实验总结 KP设定,最初使用1,假如控制之后实际值比设定值小不够,那就增大。反之就减少。 TI设定,数据先很大。看效果 1)。 如果TI加进去之后数据很久才变化到目标值就逐渐减小。如果TI减少到执行几次都是比设定值大的时候那就逐渐增大 2)。 如果刚加进去变化很快,并且超调很高,就增大来调节 积分就看情况调节 (五)增量式PID控制与位置式PID控制比较,有如下优点: 1)由式增量式PID控制与位置式PID可见,增量式PID控制算式只需要现时刻以及前两个时刻的偏差采样值,计算量和存储量都小,且计算的是增量,当存在计算误差或精度不足时,对控制量计算的影响较小。而位置式PID控制算式每次计算均与整个过去的状态有关,需要过去所有的偏差采样值参与累积计算,容易产生较大的积累误差,存储量和计算量较大。 2)增量式PID控制容易实现无扰动切换。增量式PID控制算法是对前一一时刻控制量的增量式变化,对执行机构的冲击小。位置式PID控制算法则是对前一稳定运行点控制量的绝对大小的变化,变化大,对执行机构容易产生冲击。 3)增量式PID控制本质上具有更好的抗干扰能力。若某个时刻采样值受到干扰,对于位置式PID控制,这个干扰会一直影响系统的整个运行过程;而增量式PID控制算式只需要现时刻以及前两个时刻的偏差采样值,干扰最多影响3个采样时间,其他时间不受该干扰的影响。 4)位置式PID控制比增量式PID控制更容易产生积分饱和。 5)在实际控制中,增量式PID控制算法比位置式PID控制算法应用更为广泛。 【故事】我和PID控制之六:采样周期惹的祸 注意:视频中有一些地方口误,记得识别,如毫秒可能会读成微妙,额。。。。没办法 注意:关于位置式PID算法中程序积分公式那里多了个pid.Kp,记得删除,具体的位置看上面的位置式PID 程序中有注解,资料下载下来的程序没有删除,记得删除!!!!!! |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1792 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1626 浏览 1 评论
1094 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
732 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1682 浏览 2 评论
1943浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
740浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
577浏览 3评论
600浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
562浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-26 05:20 , Processed in 0.727391 second(s), Total 77, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号