改进初学者的PID-手自动切换

本文探讨了PID控制器在手动和自动模式下的工作原理,解释了如何在代码中实现这两种模式的切换,以避免输出突变的问题。通过合理设置,可以确保PID控制器在不同模式间平稳过渡。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助。作者Brett Beauregard的原文网址:http://brettbeauregard.com/blog/2011/04/improving-the-beginner’s-pid-onoff/

 

1、问题所在

有一个 PID 控制器虽然是很好的,但你并不是什么时候都需要它。

假设在程序中的某个时刻,您希望将输出强制为某个值 (例如 0),您当然可以在调用例程中执行此操作:

void loop()
{
    Compute();
    Output=0;
} 

这样,无论 PID 输出是什么,您只需覆盖其值。然而,这在实践中是一个可怕的想法。PID 会变得非常混乱:“我一直发送输出,但是什么都没有发生!到底发生了什么事? !我再发送一下。”因此,当您停止覆盖输出并切换回 PID 时,您可能会立即得到一个巨大的输出值改变。

2、解决方案

解决这个问题的办法是有办法关闭和打开 PID。这些状态的常用术语是 "手动" (我将手动调整输出值) 和 "自动" (PID 将自动调整输出)。让我们看看这是如何在代码中完成的。

3、代码

/*working variables*/
unsigned long lastTime;
double Input,Output,Setpoint;
double ITerm,lastInput;
double kp,ki,kd;
int SampleTime = 1000; //1 sec
double outMin,outMax;
bool inAuto = false;
#define MANUAL 0
#define AUTOMATIC 1
void Compute()
{
   if(!inAuto) return;
   unsigned long now = millis();
   int timeChange = (now - lastTime);
   if(timeChange>=SampleTime)
   {
      /*Compute all the working error variables*/
      double error = Setpoint - Input;
      ITerm+= (ki * error);
      if(ITerm> outMax) ITerm= outMax;
      else if(ITerm< outMin) ITerm= outMin;
      double dInput = (Input - lastInput);
      /*Compute PID Output*/
      Output = kp * error + ITerm- kd * dInput;
      if(Output > outMax) Output = outMax;
      else if(Output < outMin) Output = outMin;
      /*Remember some variables for next time*/
      lastInput = Input;
      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;
   }
}
void SetOutputLimits(double Min,double Max)
{
   if(Min > Max) return;
   outMin = Min;
   outMax = Max;
   if(Output > outMax) Output = outMax;
   else if(Output < outMin) Output = outMin;
   if(ITerm> outMax) ITerm= outMax;
   else if(ITerm< outMin) ITerm= outMin;
}
void SetMode(int Mode)
{
  inAuto = (Mode == AUTOMATIC);
}

一个相当简单的解决方案。如果您不在自动模式下,请立即离开计算函数,而不调整 "输出" 或任何内部变量。

4、最终结果

的确,您可以通过不象例程那样调用计算来实现类似的效果,但此解决方案保持PID所包含的工作原理,这是我们所需要的。通过保持事物的内部过程,我们可以跟踪处于哪种模式中,更重要的是,当我们改变模式时,它让我们知道有哪些工作需要进行。这就引出了下一期.....。

欢迎关注:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值