深入浅出PID控制算法(三)———增量式与位置式PID算法的C语言实现与...

深⼊浅出PID控制算法(三)————增量式与位置式PID算法的C语⾔实现与
电机控制经验总结
前⽂对PID算法离散化和增量式PID算法原理进⾏来探索,之后⼜使⽤Matlab进⾏了仿真实验,对PID三个参数⼜有了更深⼊的认识,接下来我们来使⽤C语⾔进⾏PID算法实现,并且结合控制电机的项⽬来深⼊学习。
1、PID 算法C 语⾔原代码
先贴上⼀种常见的⽐较通⽤的C语⾔增量式PID算法吧
typedef struct PID
增量式光电编码器{
intSetPoint; //设定⽬标 DesiredValue
longSumError; //误差累计
doubleProportion; //⽐例常数Proportional Const
doubleIntegral; //积分常数 IntegralConst
doubleDerivative; //微分常数Derivative Const
intLastError; //Error[-1]
intPrevError; //Error[-2]
} PID;
static PID sPID;
static PID *sptr = &sPID;
/
*=============================================================
=======
InitializePID Structure PID 参数初始化
=============================================================
======*/
void IncPIDInit(void)
{
sptr->SumError= 0;
sptr->LastError= 0; //Error[-1]
sptr->PrevError= 0; //Error[-2]
sptr->Proportion= 0; //⽐例常数Proportional Const
sptr->Integral= 0; //积分常数IntegralConst
sptr->Derivative= 0; //微分常数Derivative Const
sptr->SetPoint= 0;
}
/
*=============================================================
======= 增量式PID 计算部分
=============================================================
=======*/
int IncPIDCalc(int NextPoint)
{
registerint iError, iIncpid; //当前误差
iError= sptr->SetPoint - NextPoint; //增量计算
iIncpid= sptr->Proportion * iError //E[k]项
-
sptr->Integral * sptr->LastError //E[k-1]项
+sptr->Derivative * sptr->PrevError; //E[k-2]项
//存储误差,⽤于下次计算
sptr->PrevError= sptr->LastError;
sptr->LastError= iError;
//返回增量值
return(iIncpid);
}
2、PID 整定⼝诀
参数整定最佳,从⼩到⼤顺序查。
先是⽐例后积分,最后再把微分加。
曲线振荡很频繁,⽐例度盘要放⼤。
曲线漂浮绕⼤弯,⽐例度盘往⼩扳。
曲线偏离回复慢,积分时间往下降。
曲线波动周期长,积分时间再加长。
曲线振荡频率快,先把微分降下来。
动差⼤来波动慢,微分时间应加长。
理想曲线两个波,前⾼后低四⽐⼀。
⼀看⼆调多分析,调节质量不会低。
说实话整定⼝诀对于初学者来说,其实根本就看不懂,只有从实际整定过程中才能慢慢发觉其中的奥秘。
3、项⽬原理
学到这⾥对PID算法的理解只是停留在理论,那么我们来结合实际看看,这⾥我参考的是平衡⼩车之家的资料,不得不说确实浅显易懂,先从电机的简单控制开始理解吧!
3.1直流电机
简单来说就是,把+和-分别接到电池的正极和负极,电机即可转动;
如果是把的+和-分别接到电池的负极和正极,则电机会反⽅向转动。电机的转速可以理解为和外接的电压是正相关的(实际是由电枢电流决定)。
3.2.减速器
⼀般直流电机的转速都是⼀分钟⼏千上万转的,所以⼀般需要安装减速器。减速器是⼀种相对精密的机械零件,使⽤它的⽬的是降低转速,增加转矩。减速后的直流电机⼒矩增⼤、可控性更强。按照传动级数不同可分为单级和多级减速器;按照传动类型可分为齿轮减速器、蜗杆减速器和⾏星齿轮减速器。
3.3电机驱动
要实现电机调试和换向功能,我们可以使⽤单⽚机实现的,但是单⽚机IO 的带负载能⼒较弱,⽽直流电机是⼤电流感性负载,所以我们需要功率放⼤器件,在这⾥,我们选择了 TB6612FNG。
TB6612FNG 是东芝半导体公司⽣产的⼀款直流电机驱动器件,它具有⼤电流MOSFET-H桥结构,双通道电路输出,可同时驱动 2 个电机。也许⼤家更熟悉被⽤烂的L298N,其实这两者的使⽤基本⼀致的。⽽且,相⽐ L298N 的热耗性和外围⼆极管续流电路,它⽆需外加散热⽚,外围电路简单,只需外接电源滤波电容就可以直接驱动电机,利于减⼩系统尺⼨。对于 PWM 信号输⼊频率范围,⾼达 100 kHz 的频率更是⾜以满⾜我们⼤部分的需求了。
3.4编码器
编码器是⼀种将⾓位移或者⾓速度转换成⼀连串电数字脉冲的旋转式传感器,我们可以通过编码器测量到底位移或者速度信息。编码器从输出数据类型上分,可以分为增量式编码器和绝对式编码器。
从编码器检测原理上来分,还可以分为光学式、磁式、感应式、电容式。常见的是光电编码器(光学式)和霍尔编码器(磁式)。
这⾥使⽤增量式输出的霍尔编码器。编码器有 AB 相输出,所以不仅可以测速,还可以辨别转向。根据上图的接线说明可以看到,我们只需给编码器电源5V 供电,在电机转动的时候即可通过 AB 相输出⽅波信号。编码器⾃带了上拉电阻,所以⽆需外部上拉,可以直接连接到单⽚机IO读取。
那么单⽚机如何采集编码器数据?
因为编码器输出的是标准的⽅波,所以我们可以使⽤单⽚机(STM32 STM8 51等)直接读取。在软件中的处理⽅法是分两种,⾃带编码器接⼝的单⽚机如STM32,可以直接使⽤硬件计数。⽽没有编码器接⼝的单⽚机如 51 单⽚机,可以通过外部中断读取,⽐如把编码器 A 相输出接到单⽚机的外部中断输⼊⼝,这样就可通过跳变沿触发中断,然后在对应的外部中断服务函数⾥⾯,通过 B 相的电平来确定正反转。如当 A 相来⼀个跳变沿的时候,如果 B 相是⾼电平就认为是正转,低电平就认为是反转。
4、电机速度闭环控制
4.1原理
速度闭环控制就是根据单位时间获取的脉冲数测量电机的速度信息,并与⽬标值进⾏⽐较,得到控制偏差,然后通过对偏差的⽐例、积分、微分进⾏控制,使偏差趋向于零的过程。
需要说明的是,这⾥速度控制 20ms ⼀次,⼀般建议 10ms 或者 5ms,因为在这⾥电机是使⽤ USB 供电,速度⽐较慢,20ms 可以延长获取速度的单位时间,提⾼编码器的采值。
⾸先由于需要知道速度,所以⼀般都需要带编码器的电机,编码器输出有ab相,可以通过单⽚机定时器的捕获模式来得到速度,之后在单⽚机内部进⾏PID算法的运算,得到输出所需要的速度,通过控制占空⽐来输出PWM波,控制电机的速度,这⾥⽤的主控是STM32c8t6。
4.2核⼼代码
/**************************************************************************
函数功能:增量PI控制器
⼊⼝参数:编码器测量值,⽬标速度
返回值:电机PWM
根据增量式离散PID公式
pwm+=Kp[e(k)-e(k-1)]+Ki*e(k)+Kd[e(k)-2e(k-1)+e(k-2)]
e(k)代表本次偏差
e(k-1)代表上⼀次的偏差以此类推
pwm代表增量输出
在我们的速度控制闭环系统⾥⾯,只使⽤PI控制
pwm+=Kp[e(k)-e(k-1)]+Ki*e(k)
**************************************************************************/
int Incremental_PI (int Encoder,int Target)
{
float Kp=20,Ki=30;
static int Bias,Pwm,Last_bias;        //相关内部变量的定义。
Bias=Encoder-Target;                //求出速度偏差,由测量值减去⽬标值。
Pwm+=Kp*(Bias-Last_bias)+Ki*Bias;  //使⽤增量 PI 控制器求出电机 PWM。
Last_bias=Bias;                      //保存上⼀次偏差
return Pwm;                        //增量输出
}
这⾥可以看到使⽤的是增量式⽐例积分控制器,Kp和Ki的值在函数中临时设置,完全按照公式编写,简单易懂。
4.3定时控制
int Target_velocity=50;  //设定速度控制的⽬标速度为50个脉冲每10ms
int TIM3_IRQHandler(void)
{
if(TIM3->SR&0X0001)//10ms定时中断
{
TIM3->SR&=~(1<<0);                                      //===清除定时器1中断标志位
Encoder=Read_Encoder(2);                                //===读取编码器的值,M法测速,输出为每10ms的脉冲数
Led_Flash(100);                                          //===LED闪烁;指⽰单⽚机正常运⾏
Moto1=Incremental_PI(Encoder,Target_velocity);          //===速度PI控制器
Xianfu_Pwm();                                            //===PWM限幅
Set_Pwm(Moto1);                                          //===赋值给PWM寄存器
}
return0;
}
这⾥控制周期设定的是每10ms控制⼀次,设置在10ms的中断中进⾏,得到控制量后,在经过简单的赋值和去绝对值来输出给驱动的PWM控制器。
4.4其他代码

本文发布于:2024-09-22 04:28:21,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/3/353445.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:编码器   速度   电机   输出   控制
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议