文档章节

手把手教你看懂并理解Arduino PID控制库——采样时间

欧阳天华
 欧阳天华
发布于 2016/12/21 16:40
字数 900
阅读 2135
收藏 1

引子

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

问题定义

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

观察这个“可恶”的方程

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

解决方案

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

代码

/*working variables*/
unsigned long lastTime;
double Input, Output, Setpoint;
double errSum, lastErr;
double kp, ki, kd;
int SampleTime = 1000; //1 sec
void 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:如有不足之处请告知‘

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

NEXT

PS:转载请注明出处:欧阳天华

© 著作权归作者所有

共有 人打赏支持
欧阳天华
粉丝 11
博文 8
码字总数 8615
作品 0
松江
程序员
加载中

评论(1)

G
Gioray
写的非常好!希望博主继续更新。
手把手教你看懂并理解Arduino PID控制库——引子

介绍 本文主要依托于Brett Beauregard大神针对Arduino平台撰写的PID控制库Arduino PID Library及其对应的帮助博客Improving the Beginner’s PID。在没有Brett Beauregard帮助之前,也尝试过...

欧阳天华
2016/12/21
2.7K
3
手把手教你看懂并理解Arduino PID控制库——微分冲击

引子 本文将分析《手把手教你看懂并理解Arduino PID控制库》中第二个问题:设定值改变对微分项的影响。语文不好,原文中叫做Derivative Kick,实在是想不出好的名字,暂且称为微分冲击。 问题...

欧阳天华
2016/12/21
806
1
手把手教你做智能LED灯(二) 硬件端的开发

第2节 硬件端的开发 现在,我们开始实现智能LED灯硬件相关部分的设计。 2.1 硬件连接 选择了Arduino MEGA 、HC-06蓝牙模块、LED灯模块和三引脚按钮开关以后,我们就需要把它们组合起来,为我...

anddlecn
2016/09/13
0
0
手把手教你智能硬件开发(三) 控制LED灯

第3节 控制LED灯 现在我们开始尝试用代码控制一个真正的直观的硬件设备。 第一个例子:让Arduino开发板上的一个LED小灯周期性的打开、关闭。 第二个例子:让LED灯亮度逐渐的变亮变暗。 3.1 ...

anddlecn
2016/09/06
0
0
手把手教你玩转直流电机PID双环控制

原文地址: http://bbs.elecfans.com/jishu5453201_1.html 1.速度闭环控制 我们一般在速度闭环控制系统里面,使用增量式PI控制。而在我们的微处理器里面,因为控制器是通过软件实现其控制算法...

Iammalt
2017/08/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Asus RamPage VI Extreme开不了机

Asus RamPage VI Extreme 的机器突然关机,然后就再也开不了机,没有任何反应。有人说是BIOS问题,可是这个连Bios都进不去的,按后面的刷新Bios、清除CMOS等都没有什么效果,没有任何反应。 ...

openthings
38分钟前
1
0
ubuntu 18.04 desktop 截图快捷键

如图,点击下方的 add shortcut 为这个快捷键命名 输入截图 command gnome-screenshot -a 设置快捷键 常用为 Ctrl - Alt + a 参考 http://os.51cto.com/art/200903/113091_all.htm...

公孙衍
47分钟前
0
0
一个六年Java程序员的从业总结:比起掉发,我更怕掉队

恍然间,发现自己在这个行业里已经摸爬滚打了五、六年了,原以为自己就凭已有的项目经验和工作经历怎么着也应该算得上是一个业内比较资历的人士了,但是今年在换工作的过程中却遭到了重大的挫...

老道士
49分钟前
18
2
Spacemacs快捷键

由于Spacemacs快捷键太多,为方便使用,将常用的快捷键记录在此。 以下快捷键都是在emacs的evil模式下 Buffers操作 创建名称为<buffer-name>的buffer SPC b b <buffer-name> 从已打开的buf...

yxmsw2007
54分钟前
1
0
GO冒泡,二分查找

package mainimport("fmt")func main() {var arr [5]int = [5]int{11,13,9,2,25}maopao(&arr)fmt.Println("arr = ", arr) //[2 9 11 13 25]findIndex := binaryFind(&arr, 0......

汤汤圆圆
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部