當前位置:編程學習大全網 - 編程語言 - c語言 程序 倒立擺 求助 pid應用

c語言 程序 倒立擺 求助 pid應用

#include "stc12.h"

#include <intrins.h>

#include"pid.h"

typedef unsigned char uint8;

typedef unsigned int uint16;

typedef unsigned long int uint32;

/*********************************函數聲明******************

結構體設定

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

typedef struct PIDValue

{

uint32 Ek_Uint32[3]; //差值保存,給定和反饋的差值

uint8 EkFlag_Uint8[3]; //差值標誌位符號,1則對應的為負數,0為對應的為正數

uint8 KP_Uint8; //比例系數

uint8 KI_Uint8; //積分系數

uint8 KD_Uint8; //微分顯示

uint16 Uk_Uint16; //上壹時刻的控制電壓

uint16 RK_Uint16; //設定值

uint16 CK_Uint16; //實際值

uint8 Vaule_Flag; //輸出的值正負標誌位,0為正,1為負

}PIDValueStr;

PIDValueStr PID; //定義壹個結P構體

uint16 out ; // 加熱輸出(PID運算後的輸出值)

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

增量型PID算式:PID :Uk=KP*[E(k)-E(k-1)]+KI*E(k)+KD*[E(k)-2E(k-1)+E(k-2)]

函數入口: RK(設定值),CK(實際值),KP,KI,KD PID比例參數

函數出口: U(K)

PID運算函數

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

uint16 PID_Calc(uint16 PIDinput)

{

uint32 Temp[3]; //中間臨時變量

uint32 PostSum; //正數和

uint32 NegSum; //負數和

Temp[0] = 0; //給儲存中間臨時變量賦初值

Temp[1] = 0;

Temp[2] = 0;

PostSum = 0; //給存儲所有的正數變量賦初值

NegSum = 0; //給存儲所有的負值變量賦初值

PID.RK_Uint16=180; //設定值為180

PID.CK_Uint16=PIDinput; //輸入值

if( PID.RK_Uint16 > PID.CK_Uint16 ) //如果設定值大於實際值,就是當前的值比設定值小

{

if( PID.RK_Uint16 - PID.CK_Uint16 >10 ) //計算偏差是否大於 piancha=10 ( 這裏的10由 piancha 來設定大小,根據實際情況設定)

//if( PID.RK_Uint16 - PID.CK_Uint16 >piancha )

{ //如果偏差大於 piancha=10 不在設定的PID調控範圍之內就全速加熱

out = 100; //偏差大於piancha=10為上限幅值輸出(全速加熱)

// PID.Uk_Uint16 = full_speed; //全速時的加熱值,更具實際情況可自由設定 這裏full_speed=100;

}

else //如果偏差小於 piancha=10 再調節的範圍內就計算儲存起來

{ //下面就是PID算法

Temp[0] = PID.RK_Uint16 - PID.CK_Uint16; // 計算出當前偏差值E(k)

PID.EkFlag_Uint8[1]=0; //E(k)為正數 的標誌位 0為正,1為負

//數值移位

PID.Ek_Uint32[2] = PID.Ek_Uint32[1]; //存儲E(k-2)

PID.Ek_Uint32[1] = PID.Ek_Uint32[0]; //儲存E(k-1)

PID.Ek_Uint32[0] = Temp[0]; //存儲E(k)

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

if( PID.Ek_Uint32[0] >PID.Ek_Uint32[1] ) //E(k)>E(k-1) 為正數

{

Temp[0]=PID.Ek_Uint32[0] - PID.Ek_Uint32[1]; //E(k)-E(k-1) 保存

PID.EkFlag_Uint8[0]=0; // 設定標誌位 0為正,1為負

}

else //E(k)<E(k-1)

{

Temp[0]=PID.Ek_Uint32[1] - PID.Ek_Uint32[0]; //E(k)-E(k-1)為負數

PID.EkFlag_Uint8[0]=1;

}

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

Temp[2]=PID.Ek_Uint32[1]*2 ; // 2E(k-1)

if( (PID.Ek_Uint32[0]+ PID.Ek_Uint32[2])>Temp[2] ) //E(k-2)+E(k)>2E(k-1)

{

Temp[2]=(PID.Ek_Uint32[0]+ PID.Ek_Uint32[2])-Temp[2]; //E(k-2)+E(k)-2E(k-1)為正數

PID.EkFlag_Uint8[2]=0;

}

else //E(k-2)+E(k)-2E(k-1)為負數

{

Temp[2]=Temp[2]-(PID.Ek_Uint32[0]+ PID.Ek_Uint32[2]); //2E(k-1)-(E(k-2)+E(k))

PID.EkFlag_Uint8[2]=1;

}

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

Temp[0] = (uint32)PID.KP_Uint8 * Temp[0]; // KP*[E(k)-E(k-1)]

Temp[1] = (uint32)PID.KI_Uint8 * PID.Ek_Uint32[0]; // KI*E(k)

Temp[2] = (uint32)PID.KD_Uint8 * Temp[2]; // KD*[E(k-2)+E(k)-2E(k-1)]

/************************以下部分代碼是講所有的正數項疊加,負數項疊加**************************/

/**************************************KP*[E(k)-E(k-1)]********************************************/

if(PID.EkFlag_Uint8[0]==0)

PostSum += Temp[0]; //正數和

else

NegSum += Temp[0]; //負數和

/*************************************** KI*E(k)*************************************************/

if(PID.EkFlag_Uint8[1]==0)

PostSum += Temp[1]; //正數和

else

; //空操作,E(K)>0

/************************************KD*[E(k-2)+E(k)-2E(k-1)]*************************************/

if(PID.EkFlag_Uint8[2]==0)

PostSum += Temp[2]; //正數和

else

NegSum += Temp[2]; //負數和

/**********************************************U(K)*************************************************/

//PostSum += (uint32)PID.Uk_Uint16;

if(PostSum > NegSum ) // 是否控制量為正數

{

out= PostSum - NegSum;

PID.Vaule_Flag=0; //PID調節值是正值

}

else //控制量輸出為負數

{

out=NegSum-PostSum;

PID.Vaule_Flag=1; //PID調節值是負值

}

}

//return out;

}

else //如果設定值小於實際值,就是當前的值大於設定值,就不進行PID計算直接輸出 0

{

out = 0;

}

return out;

}

  • 上一篇:學生上網課用什麽設備比較好 用電腦還是平板
  • 下一篇:鼠標側鍵有什麽用?
  • copyright 2024編程學習大全網