博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
手把手教你看懂并理解Arduino PID控制库——采样时间
阅读量:6700 次
发布时间:2019-06-25

本文共 2022 字,大约阅读时间需要 6 分钟。

hot3.png

引子

在《》中已经简单介绍过Brett Beauregard大神所提供的ArduinoPID控制库,此库不仅仅可以在Arduino使用,稍作简单的修改即可移植到别的平台。那么下面针对7个问题的第一个问题进行说明。

问题定义

一般来说,PID控制都是周期性调用(也就是意味着,每次计算的间隔都是固定的常量),但或多或少,由于各种需求会被奇葩的非周期调用。如果非得修改采样时间,对PID控制进行非周期调用,那么这样会导致以下问题:

观察这个“可恶”的方程

130434_KP4o_3162997.png

如果采样时间变化了,那么对于积分项和微分项(也就是KI和KD对应的项),这两项是和采样时间间隔有关的,那么则需要进行额外的微积分运算(不能再按照原来写好的代码进行运算,必须对时间参数进行调整)。

解决方案

如果算法被固定的周期间隔调用,那么运算将会变得很简单,并且也能够周期性的获取到精确的运算结果。那么朝着这个思路。需要想办法将已经被改变的采样周期让PID控制器认为没有改变,依旧沿用原来的运算过程。

代码

/*working variables*/unsigned long lastTime;double Input, Output, Setpoint;double errSum, lastErr;double kp, ki, kd;int SampleTime = 1000; //1 secvoid Compute(){   unsigned long now = millis();   int timeChange = (now - lastTime);   if(timeChange>=SampleTime)   {      /*Compute all the working error variables*/      double error = Setpoint - Input;      errSum += error;      double dErr = (error - lastErr);       /*Compute PID Output*/      Output = kp * error + ki * errSum + kd * dErr;       /*Remember some variables for next time*/      lastErr = error;      lastTime = now;   }} void SetTunings(double Kp, double Ki, double Kd){  double SampleTimeInSec = ((double)SampleTime)/1000;   kp = Kp;   ki = Ki * SampleTimeInSec;   kd = Kd / SampleTimeInSec;} void SetSampleTime(int NewSampleTime){   if (NewSampleTime > 0)   {      double ratio  = (double)NewSampleTime                      / (double)SampleTime;      ki *= ratio;      kd /= ratio;      SampleTime = (unsigned long)NewSampleTime;   }}

观察SetTunings和SetSampleTime两个函数,这两个函数完成了适应采样间隔改变功能。其中SetSampleTime在采样间隔改变后,按照比例放大/缩小了与采样间隔改变相同的倍数。在SetTunings做归一化处理。为什么这里只对Ki和Kd进行处理在前面已经说过了,那么大家可能又会存在这样的疑问:

如果Ki变化了,那么和经典的PID控制公式结果不是会差很大吗?答案是差别不大!!

观察积分项,并改写为离散形式:

如果在调节过程中,Ki是一个常量的话,那么可以进一步改写为:

上式的第一项分别观察Ki 及 e(t),改变采样间隔后,e(t)受采样间隔影响会产生对应时间内的变化,而ki等比例反向放大/缩小,效果相当,证必。

结论

无论调用PID算法多么频繁,此算法还是仅仅会周期性的计算。这样的好处是,PID控制器可以按照它熟悉的路子走到底。

这里需要说明的是,系统必须在timechange溢出前进行维护。或者 说,可以增加一个简单的保护机制,在越界后,将时间计数重新计数。当然unsigned int 为32位整型,已经能够容忍差不多50天运行,足够啦。

NOTE:如有不足之处请告知‘

下一章节将分析设定值的变化对微分项的影响^.^

PS:转载请注明出处:

转载于:https://my.oschina.net/u/3162997/blog/809738

你可能感兴趣的文章
Spark RDD算子介绍
查看>>
Vue渲染函数
查看>>
stl的优先级队列
查看>>
【NOIP考前模拟赛】纯数学方法推导——旅行者问题
查看>>
对象之int介绍
查看>>
Django的models操作
查看>>
Linux用户管理
查看>>
矩阵连乘积 ZOJ 1276 Optimal Array Multiplication Sequence
查看>>
BZOJ2425:[HAOI2010]计数——题解
查看>>
spring集成多个rabbitMQ
查看>>
Hibernate 中配置属性详解(hibernate.properties)
查看>>
使用面向对象技术创建高级 Web 应用程序
查看>>
ubuntu命令收集
查看>>
Django templates 和 urls 拆分
查看>>
VBS使文本框的光标位于所有字符后
查看>>
Spring boot 配置tomcat后 控制台不打印SQL日志
查看>>
shell比较运算符
查看>>
Screen Painter 程序设计
查看>>
Python--day48--ORM框架SQLAlchemy操作表
查看>>
[转] 一文弄懂神经网络中的反向传播法——BackPropagation
查看>>