完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
1、PID算法简介
PID(proportion integration differentiation)其实就是指比例,积分,微分控制。目前来说,PID控制算法是一种使用非常广泛的算法。比在平衡车、无人机等方面的应用。PID算法是简单,又能体现反馈思想的控制算法,可谓经典中的经典。 PID控制流程简单,通过误差信号控制被测量,并且控制器本身就是比例、积分、微分3个环节的加和。通过这三个的组合可有效地纠正被控制对象的偏差,从而使其达到一个稳定的状态。 PID控制规律: kp——比例增益,kp与比例度成倒数关系; T——积分时间常数; TD——微分时间常数; u(x)——PID控制器的输出信号; e(t)——给定值r(t)与测量值之差。 1.1、各个环节的作用 1、PID控制其实是对偏差的控制。 2、如果偏差为0,则比例环节不起作用,只有存在偏差时,比例环节才起作用。 3、积分环节主要是来消除静差,所谓静差,就是系统稳定后输出值和和设定值之间的差值,积分环节实际上就是偏差累计的过程,把累计的误差加到原来的所有系统上以抵消系统的静差。 4、微分信号则反应了偏差信号的变换规律,或者说变化趋势,根据偏差信号变化趋势来经行超前调节,增加系统的快速性。 2、位置型PID算法 2.1、离散表达形式: 2.2、位置型代码 核心算法部分。 main函数,按下开发板的KEY0,程序开始测试。 #include "led.h" #include "delay.h" #include "sys.h" #include "pid.h" #include "usart.h" #include "key.h" //PID算法测试 int main(void) { int count; u8 key; delay_init(); //延时函数初始化 LED_Init(); //初始化与LED连接的硬件接口 KEY_Init(); PID_init(); uart_init(9600); printf("System begin rn"); while(1) { key = KEY_Scan(0); while(count<1000) { float speed = PID_realize(200.0); printf("%f rr",speed); count++; } delay_ms(10); if(key == KEY0_PRES) { count =0; } } } pid.c 文件 统一初始化变量,尤其是Kp、Ki、Kd3个参数,对于要求的控制效果调试过程中,通过调试这个3个变量直接进行调参。 #include "pid.h" #include "usart.h" struct _pid { float SetSpeed; //定义设定值 float ActualSpeed; //定义实际值 float err ; // 定义偏差值 float err_last; //定义上一个偏差值 float Kp,Ki,Kd; //定义比例、积分、微分系数 float voltage; //定义电压值 控制器执行的变量 float integral; //定义积分值 }pid; void PID_init() { printf("Pid_init beginrn"); pid.SetSpeed = 0.0; pid.ActualSpeed = 0.0; pid.err = 0.0; pid.err_last = 0.0; pid.voltage = 0.0; pid.integral = 0.0; pid.Kp = 0.2; pid.Ki = 0.015; pid.Kd =0.2; printf("PID_init end rn"); } float PID_realize(float speed) { pid.SetSpeed = speed; pid.err = pid.SetSpeed - pid.ActualSpeed ; pid.integral += pid.err ; // 算法基本公式 没有考虑死区问题和上下限 pid.voltage = pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last); pid.err_last = pid.err; pid.ActualSpeed = pid.voltage*1.0; return pid.ActualSpeed; } pid.h 文件 #ifndef __PID_H #define __PID_H void PID_init(void); float PID_realize(float speed); #endif 2.3、测试效果 emsp; 一部分数据,可以看到,逐渐的趋近了200,设定值200,但是这个过程相对比较长。 3、增量型PID算法 3.1 、离散表达式: 3.2 增量型代码 核心算法部分。 main函数代码如下: #include "led.h" #include "delay.h" #include "sys.h" #include "pid.h" #include "usart.h" #include "key.h" //PID算法测试 int main(void) { int count; u8 key; delay_init(); //延时函数初始化 LED_Init(); //初始化与LED连接的硬件接口 KEY_Init(); PID_init(); uart_init(9600); printf("System begin rn"); while(1) { key = KEY_Scan(0); while(count<1000) { float speed = PID_realize(200.0); printf("%f rr",speed); count++; } delay_ms(10); if(key == KEY0_PRES) { count =0; } } } pid.c 代码如下: 统一初始化变量,尤其是Kp、Ki、Kd3个参数,对于要求的控制效果调试过程中,通过调试这个3个变量直接进行调参。 #include "pid.h" #include "usart.h" #include #include struct _pid { float SetSpeed; //定义设定值 float ActualSpeed; //定义实际值 float err ; // 定义偏差值 float err_next; //定义上一个偏差值 float err_last; //定义上上一个偏差值 float Kp,Ki,Kd; //定义比例、积分、微分系数 }pid; void PID_init() { printf("Pid_init beginrn"); pid.SetSpeed = 0.0; pid.ActualSpeed = 0.0; pid.err = 0.0; pid.err_next = 0.0; pid.err_last = 0.0; pid.Kp = 0.2; pid.Ki = 0.015; pid.Kd =0.2; printf("PID_init end rn"); } float PID_realize(float speed) { float incrementSpeed; pid.SetSpeed = speed; pid.err = pid.SetSpeed - pid.ActualSpeed ; // 算法基本公式 incrementSpeed = pid.Kp*(pid.err-pid.err_next)+pid.Ki *pid.err+pid.Kd*(pid.err-2*pid.err_next+pid.err_last); pid.ActualSpeed += incrementSpeed; pid.err_last = pid.err_next ; pid.err_next = pid.err ; return pid.ActualSpeed ; } pid.h 文件如下: #ifndef __PID_H #define __PID_H void PID_init(void); float PID_realize(float speed); #endif 3.3、效果展示 4、积分分离的PID控制算法 基本思路是,当被控制量与设定的值偏差较大时,取消积分作用,当被控量接近给定值时,引入积分控制,以消除静差,提高精度。 4.1、代码实现 main函数: #include "led.h" #include "delay.h" #include "sys.h" #include "pid.h" #include "usart.h" #include "key.h" //PID算法测试 int main(void) { int count; u8 key; delay_init(); //延时函数初始化 LED_Init(); //初始化与LED连接的硬件接口 KEY_Init(); PID_init(); uart_init(9600); printf("System begin rn"); while(1) { key = KEY_Scan(0); while(count<1000) { float speed = PID_realize(200.0); printf("%f rr",speed); count++; } delay_ms(10); if(key == KEY0_PRES) { count =0; } } } pid.c 文件 #include “pid.h” #include “usart.h” #include #include struct _pid { float SetSpeed; //定义设定值 float ActualSpeed; //定义实际值 float err ; // 定义偏差值 float err_last; //定义上一个偏差值 float Kp,Ki,Kd; //定义比例、积分、微分系数 float voltage; //定义电压值 控制器执行的变量 float integral; //定义积分值 }pid; void PID_init() { printf(“Pid_init beginrn”); pid.SetSpeed = 0.0; pid.ActualSpeed = 0.0; pid.err = 0.0; pid.err_last = 0.0; pid.voltage = 0.0; pid.integral = 0.0; pid.Kp = 0.2; //比例 pid.Ki = 0.04; //积分 pid.Kd =0.2; //微分 printf(“PID_init end rn”); } float PID_realize(float speed) { int index; pid.SetSpeed = speed; pid.err = pid.SetSpeed - pid.ActualSpeed ; pid.integral += pid.err ; // 算法实现过程 if(abs(pid.err)>200) //设定值 200 { index = 0; } else { index = 1; pid.integral += pid.err ; } pid.voltage = pid.Kp*pid.err+index*pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last); pid.err_last = pid.err; pid.ActualSpeed = pid.voltage*1.0; return pid.ActualSpeed; } 4.2、效果图 通过测试,系统数据达到199所用的时间为原来的1/2,系统的快速性得到提升。 |
|
|
|
只有小组成员才能发言,加入小组>>
3278 浏览 9 评论
2955 浏览 16 评论
3455 浏览 1 评论
8987 浏览 16 评论
4050 浏览 18 评论
1102浏览 3评论
570浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
568浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2301浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1856浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-21 21:49 , Processed in 1.090397 second(s), Total 49, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号