如何使用PID控制器?

10

我目前正在开发一个温度控制器。

我有一个Temperature_PID()函数,它返回操作变量(即P、I和D项的总和),但我该如何处理这个输出?

温度是通过PWM控制的,所以0%的占空比表示加热器关闭,而100%的占空比表示加热器打开。

到目前为止,我尝试过:

Duty_Cycle += Temperature_PID();
if(Duty_Cycle > 100) Duty_Cycle = 100;
else if(Duty_Cycle < 0) Duty_Cycle = 0;

对我来说这个方法不起作用,因为I项基本上使得这个系统非常不稳定。想象一下,你在积分一个区域时,添加另一个小数据点,再次积分该区域并将它们相加。一遍又一遍地做这件事。这意味着每个数据点都会让这个控制方案指数级恶化。

我想尝试的另一件事是

Duty_Cycle = Expected_Duty_Cycle + Temperature_PID();

Expected_Duty_Cycle是控制器达到稳定点后应该设定的温度,Temperature_PID()为0。但是这也行不通,因为预期占空比将始终根据加热器的条件而变化,例如不同的天气。

所以我的问题是我该如何处理PID的输出?我不明白如何基于PID输出来分配占空比。理想情况下,它将保持100%的占空比,直到温度接近设定点,并开始下降到较低的占空比。但是使用我的第一种方法(将I增益设置为零),它只在超调之后开始降低占空比。

这是我的第一篇帖子。希望我能找到答案。谢谢stackoverflow。

编辑: 以下是我的PID函数。

double TempCtrl_PID(PID_Data *pid)
{
    Thermo_Data tc;
    double error, pTerm, iTerm, dTerm;

    Thermo_Read(CHIP_TC1, &tc);

    pid->last_pv = pid->pv;
    pid->pv = Thermo_Temperature(&tc);
    error = pid->sp - pid->pv;
    if(error/pid->sp < 0.1)
        pid->err_sum += error;

    pTerm = pid->kp * error;
    iTerm = pid->ki * pid->err_sum;
    dTerm = pid->kd * (pid->last_pv - pid->pv);

    return pTerm + iTerm + dTerm;
}

编辑2: 以前从未使用过,如果链接失效请告诉我。 https://picasaweb.google.com/113881440334423462633/January302013

很抱歉,当我尝试重命名轴或标题时,Excel会崩溃。请注意:系统中还没有风扇,因此我无法像加热那样快速冷却加热器,因此与设定点相比,在设定点以下度过的时间非常短。 第一张图片是简单的开关控制器。 第二张图片是我的PD控制器。如您所见,温度下降需要更长时间,因为它不会在温度超调之前进行减法运算,而是等到温度超调后再从占空比中进行减法运算,并且这样做得太慢了。我应该如何告诉我的控制器在达到最高温度之前降低占空比?


以下是一些不错的链接:http://en.wikipedia.org/wiki/PID_controllerhttp://www.expertune.com/tutor.aspxhttp://www.library.cmu.edu/ctms/ctms/pid/pid.htm - OldProgrammer
1
所以情况有点复杂。你需要阅读PID(http://en.wikipedia.org/wiki/PID_controller)的相关知识。这是一个反馈环控制系统。你需要做的是改变占空比,读取实际温度(在那篇维基百科文章中称为PV),将误差计算为目标温度(维基百科中的SP)与实际温度之间的差异,并将误差反馈到PID控制器中。请注意,你可以调整参数来改变PV随时间变化的行为(http://en.wikipedia.org/wiki/File:Change_with_Kp.png)。 - thang
你能发一下你的TemperaturePID()函数吗?听起来你需要对PID参数进行一些调整。 - amarcy
请查看此链接:http://igor.chudov.com/manuals/Servo-Tuning/PID-without-a-PhD.pdf - kol
1
问题就在这里。它取决于你的PID实现了什么,但输出应该是占空比。 - thang
显示剩余7条评论
3个回答

11

PID的输出是占空比。必须调整kpkikd,使PID的输出在Duty_Cycle的范围内,例如0到100。通常最好在PID函数本身中显式限制输出。

你应该分步“调整”你的PID控制器。

  1. 关闭积分和微分项(将kikd设为零)

  2. 缓慢增加kp,直到10%的设定值变化使输出振荡

  3. kp减小30%左右,这应该可以消除振荡

  4. ki设置为kp的一部分,并根据期望的过冲量与到达设定点所需的时间进行调整

  5. 希望不需要kd,但如果需要,也要尽可能减小它


哦,好的。你的第一句话解释了一切。这样就更有意义了。谢谢。我将我的PID输出增益设置为简单的小分数,所以我认为如果我将它们相加,将得到占空比。看来我搞砸了哈哈。 - thecooltodd

3

你的PID控制器输出应该直接设置占空比(duty cycle)的值。

基本上,你将根据实际温度与温度设定值之间的差异来控制加热器设置。

你需要调整PID参数的值以获得你要求的性能。

首先,将I和D设置为零,并输入一个P的值,比如从2开始。

更改设定点,并观察响应情况。增加P并再次更改设定点,看看会发生什么。最终,你会看到温度一致振荡,并且永远不会达到任何稳定值。这个值被称为“极限增益”。同时注意振荡的频率。将P设置为极限增益的一半。

从1.2(极限增益)/(振荡频率)的值开始设置I并更改设定点。从这些值开始调整P和I的值,跟踪过程并查看增加或减少值是否可以改善事物。

一旦你有了P和I,就可以处理D,但是根据过程动态给出D的值可能会使你的生活更糟。

Ziegler-Nichols方法为PID值提供了一些指导,这将使你更接近目标。从那里开始调整以获得更好的性能。

你需要权衡没有超调和温度达到新设定点所需的时间之间的选项。温度调整得越快,超调就越大。没有超调将大大增加时间。


谢谢!我想Doug稍早就回答了我的问题,所以我投了他的最佳答案,但我也给了你点赞。我会记住这个调整方法的,因为我肯定想要尽量减少超调,因为当前没有风扇的系统无法快速冷却,这意味着尽量减少超调将会更快地稳定下来。 - thecooltodd
没关系,很乐意帮助。基本上归结为反复试错,但上面的链接中有许多不同的方法,可以为您提供指导,告诉您从哪里开始。 - amarcy

2
一些建议:
  • 您似乎正在进行两次集成。一次在TempCtrl_PID 函数内部,一次在外部。Duty_Cycle + = 。所以现在您的P项实际上是I项。
  • 仅使用P项并逐渐增加它,直到系统变得不稳定。然后退却(例如,使用变得不稳定的值的1/2至1/4)并开始添加I项。从I项上非常低的值开始,然后逐渐增加。这个过程是调整环路的一种方法。由于系统可能具有相当长的时间常数,因此可能需要耗费时间...
  • 您可以像您建议的那样添加一些前馈(给定设定点的期望占空比-通过设置占空比并让系统稳定来映射它)。如果该项不完美,也没有关系,因为环路会消除剩余误差。您还可以简单地将一些恒定偏差添加到占空比中。请记住,恒定值实际上不会产生任何影响,因为积分器会将其消除。它只会影响冷启动。
  • 确保此环路具有某种固定的时间基准。例如每10ms进行一次调整。
  • 目前不必担心D项。对于大多数应用程序,PI控制器应该已经足够好了。

我没有考虑到你的第一个要点。这肯定是我带有I项的系统非常不稳定的原因。虽然你没有回答我最初的问题,但我非常感谢你提供的调优建议。 - thecooltodd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接