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

2023-11-05

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

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

PID基础

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

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

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

PID算法分类

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

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

位置式PID

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

  • 比例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;

增量式PID

  • 比例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各项的作用

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

P 比例

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调节时的电机转速曲线。

实验演示

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

先调节P

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

P I D
10 0 0

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

P I D
100 0 0

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

再调节I

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

P I D
100 0.2 0

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

P I D
100 1.0 0

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

P I D
100 3.0 0

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

P I D
100 6.0 0

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

最后调节D

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

P I D
100 6.0 3.0

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

P I D
100 6.0 3.0

演示视频

PID-电机速度控制

总结

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

电机控制进阶——PID速度控制 的相关文章

  • ODrive踩坑(三)AS5047P磁编码器的ABI接口

    前两篇已经介绍过ODrive在Windows下的使用环境搭建 以及TLE5012B ABI编码器闭环运动的基本配置 ODrive教程资源导航 ODrive踩坑 一 windows下使用环境的搭建 odrivetool及USB驱动的安装 OD
  • 连载---《自动调节系统解析与PID整定》之一

    原创连载 自动调节系统解析与PID整定 之一 360doc com
  • PID整定之临界比例度法

    概述 在闭环的控制系统中 激励为阶跃信号 将调节器置于纯比例作用下 从小到大逐渐改变调节器比例度的大小 直到出现等幅振荡的过渡过程 此时的比例度称为临界比例度 r 1 K p 相邻两个波峰间的距离称为临界振荡周期T r 比例增益K Pr 图
  • 深入浅出PID控制算法(三)————增量式与位置式PID算法的C语言实现与电机控制经验总结

    前文对PID算法离散化和增量式PID算法原理进行来探索 之后又使用Matlab进行了仿真实验 对PID三个参数又有了更深入的认识 接下来我们来使用C语言进行PID算法实现 并且结合控制电机的项目来深入学习 1 PID 算法C 语言原代码 先
  • 什么是死区时间

    死区时间是PWM输出时 为了使H桥或半H桥的上下管不会因为开关的关断延迟问题发生同时导通而设置的一个保护时段 通常也指pwm响应时间 由于IGBT 绝缘栅极型功率管 等功率器件都存在一定的结电容 所以会造成器件导通关断的延迟现象 一般在设计
  • 电机磁链和反电动势系数辨识

    电机磁链和反电势系数关系 电机磁链和反电动势系数辨识 电机dq坐标系下电压方程 u d
  • # Arduino小车PID调速——整定参数初试水

    Arduino小车PID调速 整定参数初试水 在实现了小车较为可靠的测速基础上 便可以正式开展PID调速实验了 本文是基于使用Arduino平台上由Brett Beauregard大神写的PID库进行参数整定的 侧重于在对PID算法有基本了
  • 【STM32CubeMX】位置式PID调节控制输出电压(超详解)

    本文将借助STM32CubeMX来配置ADC DMA DAC USART 并利用PID位置式算法实现对输出电压进行AD采集通过PID算法调节DAC 获取到我们想要的电压值 讲解的主要知识 何为PID以及为何需要PID STM32CubeMX
  • PID算法理论,运用,代码编写详解

    什么是PID 我相信能来看这篇文章的应该都知道什么是PID PID就是一种控制算法 利用比例运算 P 积分运算 I 和微分运算 D 一起控制某一事件 当然也可以只运用其中一个也可以两两结合 运用举例 比如我们家里都会有的那个电热水器 有点热
  • 步进电机驱动器细分原理_步进驱动器细分设置表说明

    步进驱动器细分控制原理 在步进电机步距角不能满足使用要求时 可采用细分驱动器来驱动步进电机 细分驱动器的原理是通过改变A B相电流的大小 以改变合成磁场的夹角 从而可将一个步距角细分为多步 步进电机最常见的分为两相步进电机 1 8 或者三相
  • 如何以编程方式获取 OS X 上给定 PID 的打开文件描述符列表?

    我所看到的一切都说要使用lsof p 但我正在寻找不需要 fork exec 的东西 例如 在 Linux 上 人们可以简单地步行 proc pid fd You can use proc pidinfo与PROC PIDLISTFDS枚举
  • multiprocessing.Pool 与 maxtasksperchild 产生相同的 PID

    我需要在一个与所有其他内存完全隔离的进程中运行一个函数多次 我想用multiprocessing为此 因为我需要序列化来自函数的复杂输出 我设置了start method to spawn 并使用一个游泳池maxtasksperchild
  • 如何获取生成的 java 进程的 PID

    我正在编写几个 java 程序 在完成我想做的任何事情后 需要在单独的 JVM 中杀死 清理 为此 我需要获取我正在创建的 java 进程的 PID jps l可在 Windows 和 Unix 上运行 您可以使用 java 程序调用此命令
  • 在Qt中fork后获取进程的PID

    我正在创建一个成功分叉的 Qt C 控制台应用程序 当我在 fork 之前调用 QCoreApplication applicationPid 然后在 fork 之后 在子进程中 调用 QCoreApplication applicatio
  • C++ 在 Windows 中发送简单信号

    Windows 上是否有相当于kill 的函数 int kill pid t pid int sig 如果没有 是否可以根据进程的 PID 来测试进程是否正在运行 Thanks Windows 没有 Unix 意义上的信号 您可以使用Ope
  • 以编程方式获取另一个进程的父进程pid?

    我尝试谷歌 但发现getppid 它获取的父pidcurrent过程 我需要类似的东西getppid some other pid 有这样的事吗 基本上获取某个进程的 pid 并返回父进程的 pid 我认为最简单的事情是打开 proc 并解
  • 子进程和父进程ID

    只是与子进程块中的父 pid 值混淆了 我的程序如下 int main int argc char argv pid t pid pid fork if pid 1 perror fork failure exit EXIT FAILURE
  • IIS应用程序池PID

    有谁熟悉获取与进程 ID 关联的应用程序池的方法吗 我正在使用 Win32 Process 查询 W3WP 服务并返回 PID 现在我正在尝试获取与其关联的应用程序池 在 Windows Server 2008 上 情况发生了变化 in s
  • 使用批处理查找java PID

    我需要从 Windows 批处理控制台知道 java 进程 PID echo off set p CD FOR F tokens 1 A IN JAVA HOME bin jps exe v find p DO SET str A echo
  • 如何通过MATLAB命令获取外部程序(由MATLAB调用)的PID?

    我很好奇如何获取 MATLAB 在 Windows 中 调用的外部程序的 PID 例如 我通过命令调用 MATLAB 中的记事本 记事本 exe or 系统 记事本 exe 我想在调用此记事本后立即获取它的PID 由于一台计算机上可能会同时

随机推荐

  • Go语言学习13-类型转换

    类型转换 引言 类型转换 1 概念 2 数值类型之间的转换 3 与string类型相关的转换 4 别名类型值之间的转换 结语 引言 在上一篇博文中 我们介绍了 Go 语言的 数据的使用 本篇博文 我们将介绍 Go 语言的类型转换 类型转换
  • HTTP头的Expires与Cache-control

    1 概念 Cache control用于控制HTTP缓存 在HTTP 1 0中可能部分没实现 仅仅实现了Pragma no cache 数据包中的格式 Cache Control cache directive cache directiv
  • 程序员的十个等级

    转载自 http blog csdn net fx0000001 article details 50397265 如果你还迷茫请看这里 如果你很牛逼请看这里 如果你很自傲请看这里 总有你想学会的 自西方文艺复兴以来 中国在自然科学方面落后
  • 不带头结点的单链表

    建立结构体 和带头结点但单链表一样 按需建立即可 我以建立一个储存学生信息的链表举例 typedef struct node char name 20 int number struct node next Node LinkList 单链
  • 探索全桥电机驱动模块:实现精确控制与高效驱动

    全桥电机驱动模块是一种在现代工程应用中广泛使用的电机驱动方式 对于需要精确控制和高效驱动的场景 如机器人 无人机 电动车等 全桥电机驱动模块提供了理想的解决方案 本文将介绍全桥电机驱动模块的原理和实际应用场景 并对几种常见的全桥驱动芯片进行
  • csdn的Markdown行首缩进的两种方法,非常全

    csdn的行首缩进 鉴于不同编辑器的Markdown语法略微不同 故缩进也略不同 1 特殊占位符 不缩进 行首缩进 nbsp 行首缩进 160 四分之一中文占位符 行首缩进 8197 四分之一中文占位符 行首缩进 ensp 行首缩进 819
  • Spring中Bean的生命周期

    Spring Bean的生命周期是从Bean 实例化之后 即通过反射创建出对象之后 到Bean成为一个完整对象 最终存储到单例池中 这个过程被称为Spring Bean的生命周期 Spring Bean的生命周期大体上分为四个阶段 实例化
  • vue2.0项目调用多个IP接口

    项目中经常遇到跨域问题 最简单的方式就在本地配置代理 可偶尔遇到一个页面里面需要调用来自两个以上不同IP段的接口 多个IP要怎么配置代理呢 请往下看 在项目目录 config index js文件配置代理 module exports de
  • pytest

    一 pytest是单元测试框架 单元测试 对软件开发中 对软件的最小单位 函数 方法 进行正确性检查测试 java框架 jnuit和testing python框架 unittest和pytest 流程 i 测试发现 从多个文件中找到测试用
  • 英俊飘逸气宇轩昂——同人立绘征集大赛凤九天·金奖

    导语 本期介绍的作品是由来自江西科技师范大学的计世平设计的凤九天形象 荣获了本次大赛凤九天组别的金奖 2020年12月22日 由首都版权协会联合全国部分高等院校和链游玩家及部分企业共同举办的 2020同人立绘征集大赛 正式启动 并于2021
  • 详解pop()和push()方法

    pop 是移除堆栈顶部的元素并且返回它的值 push 是把对象压入堆栈的顶部 这里的堆栈不是特指栈 是LinkedList中特有的方法 LinkedHashset和LinkedHashMap ArrayList中没有此方法 下面是个小李子
  • Unity UV 水效果实现

    Unity UV 水效果实现 Unity Water Shader 组件搭载 基本参数调节 所需图片 效果呈现 Unity Water Shader Shader Custom SeaWave Properties WaterTex 水纹理
  • 潘周聃之Python分聃 -----数字雨加入潘周聃运动曲线

    作者 勇敢di牛牛 个人项目地址 englishlearningapp 个人简介 有一年工作经验的大学生 工作 汽车系统应用开发 阿里集团 个人网站 牛牛 小窝 独学而无友 则孤陋而寡闻 前言 相信各位同学最近一定被潘周聃刷屏和洗脑了 互联
  • seaborn可视化——一文搞懂heatmap参数

    文章目录 data cmap linewidths linecolor square ax annot 指定为True 指定为同形状数组 vmax vmin annot kws mask xticklabels yticklabels 设置
  • linux 命令 ls 与 ls -lrt 的区别

    ls lrt 表示按修改时间倒序列出当前工作目录下的文件 ls l 表示按名称顺序正序列出当前工作目录下的文件 1 ls 表示列出当前目录下的文件 后面的 lrt 是这个命令的一些选项补充 lrt 实际上是代表了 l r t 这三个选项集合
  • 对sklearn中transform()和fit_transform()的深入理解

    在用机器学习解决问题时 往往要先对数据进行预处理 其中 z score归一化和Min Max归一化是最常用的两种预处理方式 可以通过sklearn preprocessing模块导入StandardScaler 和 MinMaxScaler
  • k8s--基础--21--Statefulset

    k8s 基础 21 Statefulset 1 概念 StatefulSet是为了解决有状态服务的问题而设计 对应Deployments和ReplicaSets是为无状态服务 1 1 应用场景 稳定的持久化存储 即Pod重新调度后还是能访问
  • linux增大交换空间,Linux系统增加交换空间的方法

    Linux系统增加交换空间有两种方法 严格的说 在系统安装完后只有一种方法可以增加swap 那就是本文的第二种方法 至于第一种方法应该是安装系统时设置交换区 1 使用分区 在安装OS时划分出专门的交换分区 空间大小要事先规划好 启动系统时自
  • 【事业单位笔试】zrzyb信息中心-社会招聘-笔试记录

    写在前面的话 虽然说本人在21年校招时有北京银行 农银金科 中信银行研发 京东发 邮储银行 中软 郑州铁路局等的offer 奈何个人原因还是选择了有北京户口的现在的工作单位 虽然只有两年 但也是时候准备考虑一下今后的发展了 感谢大家支持 我
  • 电机控制进阶——PID速度控制

    之前的几篇文章 电机控制基础篇 介绍的电机编码器原理 定时器输出PWM 定时器编码器模式测速等 本篇在前几篇的基础上 继续来学习电机控制 通过PID算法 来进行电机的速度控制 并进行实验测试 PID基础 PID即 Proportional