PID控制算法的c語言實現 附錄1 如何讓UK值與PWM佔空比值對應

 

看到有不少人問到底如何讓UK值與PWM佔空比值對應,進而實現佔空比輸出和輸出控制電壓對應。

(注意,我這裏討論的前提是輸出控制的是電壓,不是PWM方波。PWM輸出後要經過濾波整形再輸出控制。)

前提條件:

輸出電壓控制電壓範圍是0-10V。

給定、反饋、輸出電壓採樣輸入電壓範圍是0-5V(經過運放)。

使用單片機AD爲10位AD芯片。

那麼10位AD芯片電壓採集得到的數據範圍就是0-1024。

PWM爲 8位可調佔空比方波,0對應輸出佔空比爲0的方波,255對應輸出佔空比100%的方波,127對應輸出50%的方波。

比如當前給定是2.5V,反饋電壓是1V。(KP,KI,KD等係數略,關於PID算法的整數實現我在前文中有論述如何實現)。

那麼經過AD採樣

1、給定2.5V對應爲 512

2、反饋1V對應爲 205

假定經過PID計算得到的UK爲400

也就意味着輸出電壓應當爲(400*(UPWM峯值電壓))/1024

那麼UK對應的PWM佔空比是多少呢?

我們知道,UK=1024對應占空比爲100,也就是PWM的佔空比係數爲255。可知,PWM係數 = UK/4;

那麼400就應當對應係數 400/4=100。

也就是輸出電壓=400*10/1024=3.9V

同時,由於採樣精度以及PWM輸出佔空比精度控制的問題,將導致輸出電壓和期望值不是那麼線性,所以,我在項目內加入了輸出電壓採樣的控制。

採樣AD輸入爲0-5V,所以,對於輸出0-10V有一個縮小的比例。

輸出10V則採樣值對應爲255

輸出5V則採樣之對應127

可知,3.9V對應AD結果爲97

採樣輸出電壓值,可以針對性的調整一下佔空比輸出,從而得到誤差允許範圍內的一個控制輸出電壓。

同時,經過一些加速控制的手段。可以比較迅速的達到控制的目的。

下文中的UK控制方法是針對增量式PID控制而來做的。

/****************************************************/

void    PWMProcess(void)

{

    uint16 idata temp;

    uint16 idata UKTemp;

 temp = 0;

    UKTemp = 0;

    if( Pwm.ChangeFlag_Uint8 != 0 )   //判斷是否需要改變佔空比

 {                  //是否需要改變佔空比和你的被控系統特性有關

     Pwm.ChangeFlag_Uint8 = 0;

  UKTemp = PID.Uk_Uint16 + SwIn.AddValue_Uint16;  

 //計算UK控制量

 //控制量和計算值以及一個開關量有關,我這裏的開關量是系統需要的時候疊加在控制量上的一個變量。

  if(UKTemp>999)

  {

            UKTemp = 999;

  }

//這裏只所以是999封頂而不是1024是因爲我的系統PWM的峯值電壓是12V導致。

        while(1)                        //如果輸出電壓和期望電壓相差 Delta,則繼續調整佔空比,直到在誤差以內

        {

      ADChPro(UPWMADCH);          //測量輸出電壓

   if( ADPool.Value_Uint16[UPWMADCH] == UKTemp)

   {

                return;

   }

   if( ADPool.Value_Uint16[UPWMADCH] > UKTemp)   //如果當前電壓大於輸出電壓,減小佔空比

   {

       if( ( ADPool.Value_Uint16[UPWMADCH] - UKTemp ) > UDELTA )

    {

        temp = ADPool.Value_Uint16[UPWMADCH] - UKTemp;  //

     temp = temp / 2;       //下降可以加速下降,所以下降參數加倍

     if( Pwm.DutyCycle_Uint8 > temp )

     {

                        Pwm.DutyCycle_Uint8 = Pwm.DutyCycle_Uint8 - temp;

     }

     else

     {

                        Pwm.DutyCycle_Uint8 = 0;

     }

    }

    else

    {

                    return;

    }

   }

   else           //如果當前電壓小於輸出電壓

   {

       if( ( UKTemp - ADPool.Value_Uint16[UPWMADCH] ) > UDELTA )

    {

        temp = UKTemp - ADPool.Value_Uint16[UPWMADCH];

     temp = temp / 4;  //上升處理不要超調,所以每次只+一半

     if( (255-Pwm.DutyCycle_Uint8) > temp )

     {

                        Pwm.DutyCycle_Uint8 += (temp/2);

     }

     else

     {

                        Pwm.DutyCycle_Uint8 = 255;

     }

    }

    else

    {

                    return;

    }

   }

            DisPlayVoltage();

            PWMChangeDuty(Pwm.DutyCycle_Uint8);  //改變佔空比

   Delay(10,10);

 

        }

 }

}

/*****************************************************/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章