您的位置 首页 芯片行情

电机控制进阶1——PID速度控制

之前的几篇文章(电机控制基础篇),介绍的电机编码器原理、定时器输出PWM、定时器编码器模式测速等。

本篇在前几篇的基础上,继续来学习电机控制,通过PID算法,来进行电机的速度控制,并进行实验测试。\” />

<meta http-equiv=X-UA-Compatible content=\"IE=edge,chrome=1

之前的几篇文章(电机控制基础篇),介绍的电机编码器原理、定时器输出PWM、定时器编码器模式测速等。

本篇在前几篇的基础上,继续来学习电机控制,通过PID算法,来进行电机的速度控制,并进行实验测试。

PID基础

PID即:Proportional(比例)、Integral(积分)、Differential(微分)的缩写。

PID是经典的闭环控制算法,具有原理简单,易于实现,适用面广,控制参数相互独立,参数的选定比较简单等优点。

凡是需要将某一个物理量“保持稳定”的场合(比如维持平衡,稳定温度、转速等),PID都会派上大用场。

http://news.vvfanli.com/wp-content/uploads/2022/02/20220224060230-62171f766277e.pngPID算法分类

PID算法可分为位置式PID与增量式PID两大类。

在实际的编程应用中,需要使用离散化的PID算法,以适用计算机的使用环境,下面以电机转速控制为例,来看一下两种PID算法的基本原理。

位置式PID

位置式PID是当前系统的实际位置,与想要达到的预期位置的偏差,进行PID控制

http://news.vvfanli.com/wp-content/uploads/2022/02/20220224060232-62171f7812be3.png

比例P:e(k) 此次误差

积分I:∑e(i) 误差的累加

微分D:e(k) – e(k-1) 此次误差-上次误差

因为有误差积分 ∑e(i),一直累加,也就是当前的输出u(k)与过去的所有状态都有关系。

位置式PID算法的伪代码如下:

//位置式PID(伪代码)previous_err = 0;integral = 0;loop: //根据目标值与测量值(如电机的设定速度与读到的编码器转后后的速度),循环计算更新输出值(如PWM)error = setpoint - measured_value;          /*误差项:目标值-测量值*/integral += error * dt;                     /*积分项:误差项的累计*/    derivative = (error - previous_error) / dt; /*微分项:误差的变化率*/output = Kp*error + Ki*integral + Kd*derivative; /*三项分别乘以PID系数即为输出*/previous_err = err; //更新误差wait(dt); //等待固定的计算周期goto loop;

增量式PIDhttp://news.vvfanli.com/wp-content/uploads/2022/02/20220224060233-62171f79d3a4c.png

比例P:e(k) – e(k-1) 此次误差-上次误差

积分I:e(k) 此次误差d

微分D:e(k) – 2e(k-1)+e(k-2) 这次误差-2×上次误差+上上次误差

注意增量式PID首先计算的是Δu(k),然后与上次的输出相加,才是此次的输出结果。增量式PID没有误差累加,控制增量Δu(k)的确定仅与最近3次的采样值有关。

增量式PID算法的伪代码如下:

//增量式PID(伪代码)previous02_error = 0; //上上次偏差previous01_error = 0; //上次偏差integral = 0; //积分和pid_out = 0; //pid增量累加和loop:    error = setpoint − measured_value;  /*误差项:目标值-测量值*/    proportion = error - previous01_error;                            /*比例项:误差项-上次偏差*/    integral = error * dt;                                            /*积分项:误差项的累计*/    derivative = (error − 2*previous01_error + previous02_error) / dt;/*微分项:上次误差与上上次误差的变化率*/    /*或写成:derivative = ( (error − previous01_error)/dt - (previous01_error - previous02_error)/dt )*/    pid_delta = Kp × error + Ki × integral + Kd × derivative; //计算得到PID增量    pid_out = pid_out + pid_delta; //计算最终的PID输出    previous02_error = previous01_error; //更新上上次偏差    previous01_error = error; //更新上次偏差    wait(dt); //等待固定的计算周期    goto loop;

PID各项的作用

以这个弹簧为例(假设没有重力,只有空气阻力),先是在平衡位置上(目标位置),拉它一下,然后松手,这时它会震荡起来。

http://news.vvfanli.com/wp-content/uploads/2022/02/20220224060235-62171f7ba6b18.gifP 比例

P就是比例的意思。这里就类比弹簧的弹力(回复力):F=k*Δx

当物块距离平衡位置越远时,弹力越大,反之,离平衡位置越近,力越小。

当物块位于平衡位置上方时,弹性向下,当物块位于平衡位置下方时,弹性向上,即弹力总是使物块朝平衡位置施力。

D 微分/求导/变化率

只有P控制,物块一直在上下震荡,整个系统不是特别稳定。

这是因为空气阻力太小,想象一下整个把它放到水里,物块应该很快会静止下来。这时因为阻力的作用。

D的作用就相当于阻力:

它与变化速度(单位时间内的变化量)有关,变化的越大,它施加的阻力也就越大

它的方向与目标值无关,比如,当物块从下到上经过平衡位置时,它的方向一直是朝下,

即先是阻止物块靠近平衡位置,再是阻止物块远离平衡位置(对比P的作用,始终阻止物块远离平衡位置)

它的作用就是减小系统的超调量了(减少系统在平衡位置震荡)

I 积分/误差累积

有了P的动力和D的阻力,这个物块就可以较快的稳定下来了,那I的作用是什么呢?

想象一下,如果有其它外力的影响,在某一时刻,物块将要到达平衡位置时,恰好P的动力与外力(与P的作用方向相反的恒定力)抵消,则之后物块将停在此处附近(因为此时D的力也趋近0,并很快变为0),一直到达不了平衡位置。

这时,I的误差积分作用就很有必要了:

它计算的误差的累计,只要有误差,它就一直增加,开始可能很小,但只要没要到达平衡位置,该值就会越来越大

它的作用就是消除系统的静态误差了

PID参数整定

实际应用,进行PID参数调节时,一般使用试凑法,PID参数整定口诀如下:

参数整定找最佳,从小到大顺序查,

先是比例后积分,最后再把微分加,

曲线振荡很频繁,比例度盘要放大,

曲线漂浮绕大湾,比例度盘往小扳,

曲线偏离回复慢,积分时间往下降,

曲线波动周期长,积分时间再加长,

曲线振荡频率快,先把微分降下来,

动差大来波动慢,微分时间应加长,

理想曲线两个波,前高后低4比1,

一看二调多分析,调节质量不会低。

电机PID速度控制

上面介绍了PID的基础知识,接下来就使用位置式PID来实现对直流电机转速的控制。

程序自定义PID结构体

typedef struct{float target_val;   //目标值float err;          //偏差值float err_last;     //上一个偏差值float Kp,Ki,Kd;     //比例、积分、微分系数float integral;     //积分值float output_val;   //输出值}PID;

PID算法实现(位置式PID)

float PID_realize(float actual_val){/*计算目标值与实际值的误差*/pid.err = pid.target_val - actual_val;/*积分项*/pid.integral += pid.err;/*PID算法实现*/pid.output_val = pid.Kp * pid.err +      pid.Ki * pid.integral +      pid.Kd * (pid.err - pid.err_last);/*误差传递*/pid.err_last = pid.err;/*返回当前实际值*/return pid.output_val;}

周期调用PID计算

//周期定时器的回调函数void AutoReloadCallback(){int sum = 0;/*编码器值(PID输入)*/int res_pwm = 0;/*PWM值(PID输出)*/    /*读取编码器测量的速度值*/sum = read_encoder();    /*进行PID运算,得到PWM输出值*/    res_pwm = PID_realize(sum);/*根据PWM值控制电机转动*/set_motor_rotate(res_pwm);    /*给上位机通道1发送实际值*/set_computer_value(SEND_FACT_CMD, CURVES_CH1, &sum, 1); }

上位机

这里使用野火多功能调试助手的\”PID调试助手“来进行实验,用于显示PID调节时的电机转速曲线。

http://news.vvfanli.com/wp-content/uploads/2022/02/20220224060236-62171f7c90fa7.png实验演示

目标速度值设为50(这里的目标值50使用的是编码器10ms捕获的脉冲数),通过体调节PID的参数,来测试电机能否较快的达到目标速度。

先调节P

P值先使用10看看效果,从速度曲线可以看出,达不到目标速度,且与目标速度相差较大。

P I D

1000

http://news.vvfanli.com/wp-content/uploads/2022/02/20220224060237-62171f7dd6d25.png

P值加大到100,从速度曲线可以看出,还是达不到目标速度。

P I D

10000

http://news.vvfanli.com/wp-content/uploads/2022/02/20220224060238-62171f7ec0e65.png

只使用P,会存在静差,始终达到不了目标值,这时就要使用积分项来消除静差了。

再调节I

P保持100,I使用0.2,从速度曲线可以看出,可以达到目标速度,但跟随的速度较慢。

P I D

1000.20

http://news.vvfanli.com/wp-content/uploads/2022/02/20220224060239-62171f7fbf508.png

P保持100,加大I,使用1.0,从速度曲线可以看出,可以达到目标速度,跟随的速度加快了。

P I D

1001.00http://news.vvfanli.com/wp-content/uploads/2022/02/20220224060240-62171f8099355.png

P保持100,继续加大I,使用3.0,从速度曲线可以看出,可以达到目标速度,跟随的速度进一步加快了。

P I D

1003.00http://news.vvfanli.com/wp-content/uploads/2022/02/20220224060241-62171f81dae0e.png

P保持100,再继续加大I,使用6.0,从速度曲线可以看出,可以达到目标速度,跟随速度也很快,但有一点过冲。

P I D

1006.00http://news.vvfanli.com/wp-content/uploads/2022/02/20220224060242-62171f82b4e8a.png

对于过冲,可以再加入微分试试,微分D相当于阻力的效果

最后调节D

P保持100,I保持6.0,D使用3.0,从速度曲线上,好像看不出明显的变化。

P I D

1006.03.0http://news.vvfanli.com/wp-content/uploads/2022/02/20220224060243-62171f83ba015.png

P保持100,I保持6.0,D加大到6.0,从速度曲线上看,过冲幅度减小了点。

P I D

1003.06.0http://news.vvfanli.com/wp-content/uploads/2022/02/20220224060244-62171f84cf816.png演示视频

https://www.bilibili.com/video/BV18Q4y1R7e8?spm_id_from=333.999.0.0

http://news.vvfanli.com/wp-content/uploads/2022/02/20220224060245-62171f85b161c.png总结

本篇简单介绍了PID的基础原理与参数整定,若想把PID参数调节好,还需要不断的实践与调试。

<!–

免责声明:文章内容不代表本站立场,本站不对其内容的真实性、完整性、准确性给予任何担保、暗示和承诺,仅供读者参考,文章版权归原作者所有。如本文内容影响到您的合法权益(内容、图片等),请及时联系本站,我们会及时删除处理。

作者: admin

为您推荐

如何使用GPU编程优化模型/代码

  使用 Python 和 NumPy 库开发的 HIM 模型在 hackathon 开始时没有并行或 GPU 计算。在活动期间, THINKLAB 团队使用 CuPy 为了使他们的代码在 GPU 上并行运行,然后重点将用户定义的 CUDA 内核应用于参数。结果是 672 倍加速,计算时间从 2 周缩短到大约 30 分钟。\” />

<meta http-equiv=X-UA-Compatible content=\"IE=edge,chrome=1

NVIDIA驱动程序支持OpenCL和Vulkan进行互操作

  OpenCL 和 Vulkan 之间的互操作在移动和桌面平台上都有很强的需求。 NVIDIA 与 Khronos OpenCL 工作组密切合作,发布了一套临时跨供应商的 KHR 扩展。这些扩展使应用程序能够在 OpenCL 和 Vulkan 等 API 之间高效地共享数据,与使用隐式资源的前一代互操作 API 相比,灵活性显著提高。\” />

<meta http-equiv=X-UA-Compatible content=\"IE=edge,chrome=1

准备去元宇宙过第二人生?小心别被骗了

准备去元宇宙过第二人生?小心别被骗了   电子发烧友网报道(文/黄山明)随着元宇宙在近期的大火,相信大家对于这一技术已不陌生。但元宇宙因为其特性,也需要建立合适的网络安全防护措施,来应对这项技术带来的独特挑战。并且在元宇宙想要得以持续,需要用去中心化的平权式共享机制与共治机制来作为保障,既要做大“蛋糕”,也要分好“蛋糕”。但问题在于,去中心化的元宇宙,在安全问题上也将面临更大的挑战。     先简单解释一下元\” />

<meta http-equiv=X-UA-Compatible content=\"IE=edge,chrome=1

代工巨头再次换帅,中芯国际高管频频离职,业绩喜人之下原因为何?

电子发烧友网(文/黄山明)3月17日,中芯国际发出公告,公司代理董事长高永岗博士,获委任为中芯国际董事长,自2022年3月17日生效。而在半年前辞去中芯国际董事长职位的“芯片泰斗”周子学最终以身体原因为由,辞去了执行董事一职。   对于这一次的交接,有业内人士称这是一次完美的交接,对中芯国际乃至中国半导体产业都有着重要的影响。不过另一方面,自周子学辞任中芯国际董事长之后,其股价便一路走低,从半年前的21.1港元降至如今的\” />

<meta http-equiv=X-UA-Compatible content=\"IE=edge,chrome=1

电子测量仪器企业普源精电上市!年营收超3亿,募资7.6亿加速自研芯片项目

电子发烧友网报道(文/莫婷婷)4月8日,普源精电在科创板上市,发行价格60.88元/股,公开发行股份约3032.74万股,占公司发行后总股本的比例为25%。该股上市当日开盘即破发,截至今日收盘,普源精电报39.78元,跌幅34.66%,总市值48.26亿元。   图源:东方财富   在上市之前,普源精电在招股书的风险因素中提到,“公司无法保证未来几年内实现盈利,公司上市后亦可能面临退市的风险”。2020年、2021年上半年,普源精电分别亏损2716.6万元、2036.48万元,连\” />

<meta http-equiv=X-UA-Compatible content=\"IE=edge,chrome=1

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

返回顶部