最近研究了一下PID,用C#實現了一下,搞的差不多明白了,和大家分享一下,感謝大家的關注。
項目源碼見文末。
下圖是測試效果:
前面只有P調節,後面加入I調節消除穩態誤差。
下面說一下測試過程,首先模擬一個被調節的設備。大家先可以假設這是一個水罐,我們通過Input口的注水和抽水調節液位Level,罐子本身有個Output口,排出水來干擾我們的控制。
class Device
{
public Device()
{
Task.Run(Running);
}
public double Input { get; set; }
public double Output { get; set; }
public double Level { get; set; }
public double MaxLevel { get; set; } = double.MaxValue;
public double MixLevel { get; set; } = 0d;
private void Running()
{
while (true)
{
Thread.Sleep(200);
if (Level < MaxLevel)
Level += Input*3;
if (Level > Output)
Level -= Output;
else
Level = 0;
LevelChange?.Invoke();
}
}
public event Action LevelChange;
}
然後就是PID控制的水泵
class PID
{
public double err; //偏差值
public double err_last; //上一個偏差值
public double err_last_last; //上上一個偏差值
public double Target; //調節目標
public double Output; //輸出
public double Maxout { get; set; } = 10000d;
public double Mixout { get; set; } = -10000d;
public double PID_realize(double target, double nowvalue, double Kp = 0.4, double Ki = 0.3, double Kd = 0.1)
{
if (target != Target) {
Output = Kp * err;
Target = target;
}
err = target - nowvalue;
Output += Kp * (err - err_last + Ki * err + Kd * (err - 2 * err_last + err_last_last)); //這是增量PID算法的公式
err_last_last = err_last;
err_last = err;
if (Output > Maxout) Output = Maxout;
if (Output < Mixout) Output = Mixout;
return Output;
}
}
其它就是一些界面的實現了,就不貼了,可以到我們碼雲下載我的開源項目。
https://gitee.com/tfarcraw/wpfnotes.git
是我平時學習wpf 的一個練手小項目集,這個示例在PrismMain項目中,不過我會經常更新,有時候就把這個項目整合掉了,這個我打包發到CSDN上吧。
https://download.csdn.net/download/tfarcraw/12584796