PID庫與PID基本優化(四)


本系列旨在以我自己寫的PID lib為例,講一下PID的幾點基本優化,PID的基本原理網上有很多資料,因此本系列將不會涉及PID的基本實現原理,在這里特別推薦Matlab tech talk的PID教程:https://ww2.mathworks.cn/videos/series/understanding-pid-control.html。

由於筆者大一在讀,還沒有學習自動控制原理等課程,因此本系列將不會從自控原理角度展開,相反的,本系列將試圖從“直覺”展開,通過直觀的描述讓大家從直覺上感受並理解PID的一些包括微分先行、積分分離等基礎的優化。

由於筆者水平有限,文中難免存在一些不足和錯誤之處,誠請各位批評指正。

1 積分抗飽和

1.1 問題

我們都知道PID只適用於線性非時變的控制場合,但執行器或者被控對象很少可以做到嚴格線性,在對控制效果要求較高的場合,我們只能選取工作范圍中近似線性的部分。又或者單純的限制執行器的作用量,以此來保護系統的安全,如閥門的限位、電機的限速等。無論出於以上哪一個目的,我們都需要對PID的輸出量進行限制,我們一般稱之為輸出限幅。

但在某些情況下,輸出限幅的存在或者執行器本身的限制導致了被控對象無法達到我們的期望值,這就意味着誤差將會持續存在,持續存在的誤差會使積分項過分積累,從而導致我們在下調期望值使誤差反向時,積分項需要一段時間來下降至最大輸出一下,這段過程中PID的輸出將會持續保持最大,從而導致響應的嚴重滯后,我們將這種情況稱之為積分飽和(integral windup)。圖像上可以看到,積分飽和導致的響應滯后和我的PID庫與PID基本優化(三)結尾提到的情況非常相似(后期備注,這張圖有些問題,應該是當時跑的時候PID輸出被錯誤限幅在0.8了,就當作目標信號幅值為0.8就可以了):

1.2 解決方案

我們一般通過對積分限幅的方式實現積分抗飽和,為了解決積分飽和問題,我們需要先分析是什么導致了積分的過度積累,是輸出限幅導致的無法消除的誤差。因此一種思路便是在PID輸出達到輸出限幅時停止積分過程。考慮到過大的積分項會導致系統的超調和不穩定,因此我們也可以設定一個合適的積分閾值,來通過這個閾值對積分進行限幅。這兩種方式相互獨立互不影響,因此我們可以在積分抗飽和中同時采用以上兩種策略。

經過積分抗飽和處理后,我們可以看到系統響應的滯后已經被大幅改善(后期備注,這張圖有些問題,應該是當時跑的時候PID輸出被錯誤限幅在0.8了,就當作目標信號幅值為0.8就可以了):

1.3 代碼實現

static void f_Integral_Limit(PID_TypeDef *pid)
{
    float temp_Output, temp_Iout;
    temp_Iout = pid->Iout + pid->ITerm;
    temp_Output = pid->Pout + pid->Iout + pid->Dout;
    if (ABS(temp_Output) > pid->MaxOut)
    {
        if (pid->Err * pid->Iout > 0)
        {
			//在取消積分作用前,同樣需要先判斷當前周期內積分是否積累
            //如果積分為減小趨勢則不需要限制其減小
            //原因與(三)中相同。
            pid->ITerm = 0;
        }
    }
    
    if (temp_Iout > pid->IntegralLimit)
    {
        pid->ITerm = 0;
        pid->Iout = pid->IntegralLimit;
    }
    if (temp_Iout < -pid->IntegralLimit)
    {
        pid->ITerm = 0;
        pid->Iout = -pid->IntegralLimit;
    }
}

本系列關於PID基本優化策略不出意外的話就到此結束了,在系列結束的前最后我再扯一下我的電機堵轉保護的實現,庫中剩余部分不再單獨講解了,全部代碼已經發布在Github中,鏈接在我的PID庫與PID基本優化(一)

2 電機堵轉保護

1.1 思路分析

電機堵轉保護實現的關鍵和前提就在准確判斷電機是否堵轉,識別太嚴苛或者太寬松都會嚴重影響實際應用,因此我們需要盡可能的提高識別的准確性,而提高識別准確性的關鍵又在准確提取電機堵轉發生的典型特征。

電機堵轉發生時,電機轉速會非常小或者直接為零,同時電機溫度會上升,考慮到大多數電機內沒有集成溫度傳感器,我並沒有選擇應用溫度上升這一特征。這樣就只能從轉速極小這一特征入手:

最簡單的方式是判斷轉速是否小於一個閾值,但是用腳趾頭想一想就知道這個思路不可行,因為電機本身目標速度為零的時候就會被誤判為堵轉,這是我們不希望看到的。那既然上一個思路在目標速度為零的時候會發生誤判,那我們就可以將目標速度納入判斷。

思路進行到這里,我們不難想到,如果電機的實際轉速與目標轉速相差很遠,這就是電機堵轉的一個重要特征。但在電機起轉時,電機實際轉速與目標轉速相差很遠,這顯然不是堵轉。因此只有這樣的狀態持續一段時間,一段遠比電機起轉所需時間要長的時間,這樣我們我們離精准判斷只差最后一步,在PID輸出本身就不大的時候,電機因為正常的負載導致無法旋轉,這顯然也沒有必要當作堵轉處理,因此我們還需要將這種情況挑出來。不過這種情況不常出現,因為即使電機的目標轉速很小,PID算法中的積分項也會使電機保持目標轉速。

下面我們直接上代碼:

2.2 代碼實現

static void f_PID_ErrorHandle(PID_TypeDef *pid)
{
    //排除PID輸出本身很小的情況
    if (pid->Output < pid->MaxOut * 0.01)
        return;
	
    //考慮到該判斷策略的靈活性,0.9這個常數的選取是很靈活的
    if ((ABS(pid->Target - pid->Measure) / pid->Target) > 0.9f)
    {
        //電機堵轉計數
        pid->ERRORHandler.ERRORCount++;
    }
    else
    {
        pid->ERRORHandler.ERRORCount = 0;
    }

    if (pid->ERRORHandler.ERRORCount > 1000)
    {
        //上述現象持續一段時間則被認定為電機堵轉
        pid->ERRORHandler.ERRORType = Motor_Blocked;
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM