PID控制算法是工业控制领域使用最广泛的算法之一,嵌入式系统是工业领域和生活中最常见的智能控制系统之一。本文以单片机控制两个带编码器的直流电机使二者转速保持一致为例讲PID算法与直流电机的PWM技术控制。本文围绕下面几个问题展开:

什么是PID控制算法?

  PID控制算法即比例、积分、微分控制算法。PID控制分为两种:模拟PID和数字PID,前者处理的是连续信号,后者处理的是离散信号。因为单片机只能处理离散信号,本文主要谈后者。对于后者,又分为两种常用的算法即增量式数字PID和位置式数字PID,其中增量式用的更多,所以本文以增量式数字PID为例。PID控制的数学原理比较复杂,限于作者水平,大家可以点击这里进一步了解其控制原理。另外,根据实际控制需求,PID控制算法不一定三个环节都要用,一般常用的还有PI控制、PD控制。

典型的闭环控制系统结构图

PID控制算法的典型的结构图

  PID控制算法的设计过程中最重要的一个环节就是确定三个参数值的大小的确定,即PID参数整定。为了方便叙述,我们直接用上面的链接里的思路,即确定三个系数A、B、C的大小。其中 :

A = Kp + Ki + Kd,B = Kp + 2 * Kd,C = Kd。 ------- (1)
Kp,Ki,Kd分别是PID控制器的三个参数。

注:上图直接从链接中截取
   从本人实际的调试经历中,对于电机控制,我一般设置三个参数的大小关系为:Kp>>Kd,Ki,至于具体的数值以及Kp,Ki的相对大小需要根据控制需求和调试过程中输出的情况做一些调整,必要的话,还可能需要做一些算法上的调整,下面分情况详述:

  1. 先定性分析比例、积分、微分三个环节的控制作用:
    比例环节:即时成比例地反应控制系统的偏差信号e(t),偏差一旦产生,控制器立即产生控制作用以减小误差。当偏差e=0时,控制作用也为0。因此,比例控制是基于偏差进行调节的,即有差调节。
    积分环节:能对误差进行记忆,主要用于消除静差,提高系统的无差度,积分作用的强弱取决于积分时间常数Ti,Ti越大,积分作用越弱,反之则越强。值得注意的是,积分作用不宜设置过强,否则控制器输出振荡,会出现两个电机一个转另一个不转或转的慢并轮流交替循环这种极端现象,如果这两个电机是某个小车的两个转向轮,那么小车将会一直走“S”曲线。
    微分环节:能反映偏差信号的变化趋势(变化速率),并能在偏差信号值变得太大之前,在系统中引入一个有效的早期修正信号,从而加快系统的动作速度,减小调节时间。微分系数同样不能太大,否则会降低系统的稳定性。按照上面举的小车的例子,微分作用过大表现在处于稳定状态(即小车保持直线行驶)的小车受到一点点扰动就需要花很长的时间调整回来甚至再也调整不回来了。
       从时间的角度讲,比例作用是针对系统当前误差进行控制,积分作用则针对系统误差的历史,而微分作用则反映了系统误差的变化趋势,这三者的组合是“过去、现在、未来”的完美结合。
  2. 根据上面的定性分析,可以把两个电机的转速差(有正负之分)以一定的频率记录下来并绘制响应曲线(即输出-时间曲线),这个过程可以在上位机上完成,只需要打开单片机的串口,把输出的数据发给上位机即可。然后根据响应曲线调节,三个环节的调节顺序是:先调Kp是输出曲线表现为等幅振荡或近似等幅振荡,然后加上Ki,使输出曲线收敛,最后加上Kd,使响应曲线完全达到控制要求(一般响应快、稳定时无误差、超调小为宜)。
  3. 讲一些特殊情况下的控制算法调整。
    1)控制器的输出溢出,这种情况可能控制作用过强导致,这时要按Ki,Kd,Kp的顺序一个一个地适当减小三个系数,极端情况下可使Ki=0,Kd=0,Kp很小,然后 再看输出曲线。
    2)输出一直在振荡,怎么调控制参数都没用,这时要考虑硬件的问题,或者其他软件问题。
    3)除了上面两种常见的情况,也可以事先了解一下常用的PID控制器的改进方法,比如:死区控制法、遇限削弱积分法、积分分离法、有效偏差法、微分先行法等。再复杂的情况,比如大滞后,可以用串级PID控制算法,对于某一种强扰动也可加上前馈控制算法等。
直流编码电机的控制与转速的检测

先上图看一下它长什么样子:

带编码器的直流减速电机

  编码器:所谓编码,就是它可以把电机的角位移或者角速度信号转换为电脉冲信号,通过对脉冲信号的检测可以确定电机的转速。在上面的结构图中,编码器就是传感器,它将电机转速经测量变速传给单片机。
编码器的驱动:我们用stm32f10xxx系列的单片机作为主控芯片,stm32单片机的定时器外设资源丰富,并且它的通用定时器本身就带有控制编码电机的工作模式,简直就是“量身定做”!
   直流电机的控制:直流电机的转速控制用PWM技术实现,调节PWM的占空比可以线性地改变电机两端的电压,从而控制电机的转速,控制结构图如下:

直流电机的控制流程

  上面的电机驱动本质是一个功率放大器,将单片机产生的、一定占空比的PWM矩形波转为一定电压电流的模拟信号,进而驱动电机。

程序实现的问题

程序流程如下:

下面挑重要的几步讲一下,然后总的源代码程序工程会以压缩包的形式共享出来。

1. 初始化
   初始化这一步主要完成一些全局变量、外设的赋值和配置工作。具体是:PID控制相关参数的初始化,定时器、串口等其他辅助性的外设的配置:

 delay_init(); //延时函数初始化TIM5_PWM_Init(1000,9); //PWM初始化 8KHz TIM3_ENC_Init();  //编码器初始化TIM4_ENC_Init();  //编码器初始化NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级配置pid_init();uart_init(115200); //初始化串口,波特率设置为115200

2. PID参数设置

 do //下面的循环语句是为了调节PID参数,串口接收到'0',跳出循环{switch(go) //注意大小写{case 'P': mts.Kp += val; go = 0; break;case 'I': mts.Ki += val; go = 0; break;case 'D': mts.Kd += val; go = 0; break;case 'p': mts.Kp -= val; go = 0; break;case 'i': mts.Ki -= val; go = 0; break;case 'd': mts.Kd -= val; go = 0; break;default: break;}delay_ms(10);}while(go != '0');

  这一步是为了后面程序复位后方便调整PID参数,即便于PID参数整定。
3. 循环体

 while(1){detPID_PWM_out();//调用PID函数,计算控制增量if(sendFlag) //每刷新一次控制输出,往上位机发一次数据{send_intData(mts.detPWM_out); sendFlag = 0;}TIM_SetCompare1(TIM5,BASE_SPEED - mts.detPWM_out);  //注意电机的正反转,这里的4个通道可以控制两个电机正反转TIM_SetCompare2(TIM5,BASE_SPEED + mts.detPWM_out);     TIM_SetCompare3(TIM5,0); //通道3、4为0,此时假设两个电机刚好往同一个方向转,如果转向不一致,请对调硬件或再修改代码,这里只举例说明TIM_SetCompare4(TIM5,0);}
}

  循环体里面计算控制输出,并根据控制输出调整PWM矩形波的占空比。
4. 中断

/*下面是中断服务函数,定时器中断的优先级高于串口中断*/void USART1_IRQHandler(void)                 //串口1中断服务程序{if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d(回车) 0x0a(换行)结尾){if(sendFlag%2){val = USART_ReceiveData(USART1); //读取接收到的数据}else{go = USART_ReceiveData(USART1);    //读取接收到的数据      }sendFlag = ++sendFlag >= 255?1:sendFlag;                         }
} void TIM6_IRQHandler(void)   //TIM6中断
{if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 {TIM_ClearITPendingBit(TIM6, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源
//          (u_16) = TIM_GetCounter(TIM4);
//          (U_16) = TIM_GetCounter(TIM3);mts.Ek_2 = mts.Ek_1;mts.Ek_1 = mts.Ek;mts.Ek = TIM_GetCounter(TIM3) - TIM_GetCounter(TIM4); //计算偏差sendFlag = 1;}}

  程序中只用了两个中断,一个是串口接收中断,用于接收上位机的命令和数据,以便调试或者监控程序里面一些变量的变化;另一个是定时器中断,为了以50Hz的频率采集编码器反馈的速度信号,同时计算偏差。

总结

  本文只介绍了最简单的PID控制算法C语言实现,上面提到的那几种常用的PID改进算法每一个都可以单独拿出来讲一下如何实现,但限于篇幅且本文重点不是这个所以大家感兴趣的话可以先查查相关的文章,后面有机会我会再单独讲一下我个人对这些算法的理解和实际应用中的实现。本文的基于uKeil的C源码工程共享在公众号“24K纯学渣”上面,回复“PID电机控制”即可获取。另外,限于作者水平,如有描述错误或不妥之处,欢迎大家在下面评论指出。如果希望进一步的交流学习,可以在公众号上联系作者,任何学习上的交流本人都非常欢迎!

---------------------
作者:24K纯学渣
来源:CSDN
原文:https://blog.csdn.net/qq_42144047/article/details/103871970?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control

[转]PID算法与直流电机的PWM技术控制()相关推荐

  1. PID算法与直流电机的PWM技术控制

    PID控制算法是工业控制领域使用最广泛的算法之一,嵌入式系统是工业领域和生活中最常见的智能控制系统之一.本文以单片机控制两个带编码器的直流电机使二者转速保持一致为例讲PID算法与直流电机的PWM技术控 ...

  2. 基于ESP32四旋翼无人机如何根据PID算法进行电机的PWM duty补偿

    1.计算模型 电机位置和补偿输出的关系,需要求解的是C1,C2,C3,C4的电机输出补偿值.分别对应M1,M2,M3,M4四个电机. 2.推导过程(可以跳过不看,直接到第三步) 3. 四个电机的PID ...

  3. [单片机学习笔记](35):串级PID算法应用剖析、通过串口控制电机、MPU6050获取平衡车姿态、自制平衡车PID算法程序设计

    串级PID算法应用剖析 这是经过给队友讲解串级PID的程序的之后的进一步的理解总结. 内环的实际值,取决于你能测出什么值给内环.而内环的输入就是内环误差 内环的输出值,是内环误差(内环目标值-内环实际 ...

  4. PID算法优化(以平衡小车代码为例)

    PID控制 这篇文章是PID控制的进阶说明,如果没有看过PID控制(上)的读者,请先看看PID控制(上),以便更容易看懂这篇文章.关注微信公众号"电子搬砖师"即可阅读PID控制(上 ...

  5. 基于PID算法的STM32爬坡循迹智能小车的设计与实现

    目录 摘要 0 引言 1 需求分析 2 系统结构 3 硬件电路设计 3.1 整体硬件框架 3.2 主控制电路 3.3 电源模块 3.4 红外循迹 3.5 电机驱动 3.6 无线蓝牙控制 4 软件设计 ...

  6. 用Excel教会你PID算法

    01.引入PID 电机控制 这样是没有反馈的,也就是说我们完全相信输入的数字,且是理想化的模型,比如输入占空比为50%的25Kz的PWM,车轮速度为1m/s,实际产品中会受到各种这样的影响,比如地面阻 ...

  7. 【算法】通俗易懂的PID算法

    初识PID PID算法是连续系统中技术最为成熟.应用最为广泛的一种控制算法.该控制算法出现于20世纪30至40年代,PID 控制器以各种形式使用超过了 1 世纪,广泛应用在机械设备.气动设备 和电子设 ...

  8. 模拟电磁炮物体追踪的PID算法

    本文使用串口1DMA中断接收OpenMV传来的色块坐标,定时器2给舵机一个20ms的时基脉冲. 在main.c中包含所需的头文件: #include "stm32f1xx_hal.h&quo ...

  9. PID控制器开发笔记之一:PID算法原理及基本实现

           在自动控制中,PID及其衍生出来的算法是应用最广的算法之一.各个做自动控制的厂家基本都有会实现这一经典算法.我们在做项目的过程中,也时常会遇到类似的需求,所以就想实现这一算法以适用于 ...

最新文章

  1. C语言单链表求环,并返回环的起始节点
  2. mysql单机多实例主从_【转载】MySQL单机多实例安装并配置主从复制
  3. mysql 语句怎样修饰约束_MySQL中的约束,添加约束,删除约束,以及一些其他修饰讲解...
  4. 计算机网络中的时延有哪几部分,计算机网络中的四种延迟分别是什么?
  5. 求离散马尔科夫链的平稳分布+按照一定概率分布生成想要的样本
  6. js模拟form表单提交数据, js模拟a标签点击跳转,避开使用window.open引起来的浏览器阻止问题...
  7. 调用另一个cpp的变量_再谈条件变量—从入门到出家
  8. php数组常用_PHP常用数组总结
  9. 【转】iOS 10 UserNotifications 使用说明
  10. html5画布作品,HTML5 canvas画布
  11. mysql怎么退出电脑_mysql的登陆和退出命令格式
  12. python免费教程视频-Python免费视频教程
  13. 学习笔记20 热传导方程
  14. 区块链:核心技术概览
  15. 【WiFi】WiFi安全类型
  16. turbo linux添加打印机,如何安装Turbo Linux(3)
  17. 5G WiFi的信号难题:穿墙性能太差
  18. if语句和三元运算符哪个效率更高
  19. 基于Flash播放器的P2P直播解决方案
  20. 24亿美金订单!今年黑五,这群人又赚翻了!

热门文章

  1. 信息系统监理师考试怎么备考?
  2. 产品 医疗健康app分析
  3. 魔改typecho系统函数和typecho后台界面
  4. 利用border属性画哆啦A梦
  5. 地铁bas服务器系统,地铁某线BAS系统项目
  6. c语言里的u代表什么_C语言中的0U或1U是什么意思?
  7. 用c语言算法统宗 李白沽酒,诗词中的数学问题 百羊问题与李白沽酒
  8. REST原则、RESTful架构
  9. bmc控制卡_服务器BMC技术调研
  10. 运维体系建设(第一章)