|
unsigned char aa[]={'T','a','r','g','e','t',' ',' ',' ',' ',' ','r','/','m','i','n'}; //目標(biāo)轉(zhuǎn)速。Target r/min
unsigned char cc[]={'A','c','t','u','a','l',' ',' ',' ',' ',' ','r','/','m','i','n'}; //實(shí)測轉(zhuǎn)速: Actual r/min
uchar flag;
uchar i=0;
sbit PWM_FC=P3^3;
sbit IN1=P3^6;
sbit IN2=P3^7;
int e ,e1 ,e2 ;//pid 偏差
float uk ,uk1 ,duk ;//pid輸出值
float Kp=0.36,Ki=0.05,Kd=0.016;//pid控制系數(shù) 0.1 0.05 0.016
/*
PID的參數(shù)設(shè)置可以參照以下來進(jìn)行:
參數(shù)整定找最佳,從小到大順序查;
先是比例后積分,最后再把微分加;
曲線振蕩很頻繁,比例度盤要放大;
曲線漂浮繞大灣,比例度盤往小扳;
曲線偏離回復(fù)慢,積分時(shí)間往下降;
曲線波動(dòng)周期長,積分時(shí)間再加長;
曲線振蕩頻率快,先把微分降下來;
動(dòng)差大來波動(dòng)慢。微分時(shí)間應(yīng)加長;
理想曲線兩個(gè)波,前高后低4比1 ;
一看二調(diào)多分析,調(diào)節(jié)質(zhì)量不會(huì)低;
*/
int out=0;
uint SpeedSet=300;
uint cnt=0;
uint Inpluse=0,num=0,zs;//脈沖計(jì)數(shù)
uint PWMTime=100;//脈沖寬度
void PIDControl();
void SystemInit();
void delay(uchar x);
void PWMOUT();
void SetSpeed();
/**************主函數(shù)************/
void main()
{
SystemInit();
init();
LCD_Write_String(0,0,aa);
zs=1;
while(1)
{
if(flag==1)
{
flag=0;
LCD_Write_String(0,0,aa);
}
if(zs==1)
{
zs=0;
cc[7]=num/1000+'0';
cc[8]=num/100%10+'0';
cc[9]=num/10%10+'0';
cc[10]=num%10+'0';
LCD_Write_String(0,1,cc);
}
}
}
void PIDControl() //pid偏差計(jì)算
{
e=SpeedSet-num;
duk=(Kp*(e-e1)+Ki*e+Kd*(e-2*e1+e2));
uk=uk1+duk;
out=(int)uk;
if(out>1000)
{
out=1000;
}
else if(out<0)
{
out=0;
}
uk1=uk;
e2=e1;
e1=e;
PWMTime=out;
}
void delay(uchar x)
{
uint i,j;
for(i=x;i>0;i--)
for(j=50;j>0;j--);
}
void PWMOUT()
{
if(cnt<PWMTime)
{
PWM_FC=1;
}
else
{
PWM_FC=0;
}
if(cnt>1000) cnt=0;
}
void SystemInit()
{
TMOD=0X21; //t1用來串口t2定時(shí)
TH0=THC0;
TL0=TLC0;
TH1=0xC0;
TL1=0XC0;
ET1=1;
ET0=1;
TR0=1;
TR1=1;
EX0=1; //中斷0用來測量轉(zhuǎn)速
IT0=1;
EA=1;
e =0;
e1=0;
e2=0;
IN1=1;
IN2=1;
}
uchar Key_Scan(void)
{
static uchar State_Cnt=0;//靜態(tài)變量,用于改變狀態(tài)過程
uchar Key_State = 0;//用于存儲(chǔ)鍵值碼
switch(State_Cnt)
{
case 0x00:P1 = 0x1f;//先往P3(1到4獨(dú)立按鍵)口送0001 1111
if(P1 != 0x1f)//有無按鍵被按下
{
State_Cnt = 0x01;//改變狀態(tài)
break;
}
case 0x01:
if(P1 != 0x1f)//經(jīng)過定時(shí)器延時(shí)后,再次判斷按鍵是否按下
{
State_Cnt = 0x02;//改變狀態(tài)
Key_State = P1;//把鍵值保存下來
P1 = 0x1f;//恢復(fù)P3,以便下次按下重新保存鍵值
break;
}
else
{
State_Cnt = 0x00;//改變狀態(tài)
break;
}
case 0x02:
if(P1 == 0x1f)//判斷按鍵釋放
{
State_Cnt = 0x00;//改變狀態(tài)
break;
}
default:break;
}
return Key_State;//返回鍵值
}
void Display_Key(uchar key_value)
{
switch(key_value)
{
case 0x1e:
IN1=0;
IN2=1;break;//鍵值改變時(shí),做出相應(yīng)的動(dòng)作(用戶自定義動(dòng)作)
case 0x1d:
IN1=1;
IN2=1;break;
case 0x1b:
IN1=~IN1;
IN2=~IN2;
break;
case 0x17:
SpeedSet+=10;
if(SpeedSet>3500)
{
SpeedSet=3500;
}
break;
case 0x0f:
SpeedSet-=10;
if(SpeedSet<0) SpeedSet=0;
break;
}
}
void int0() interrupt 0
{
Inpluse++;
}
void t0() interrupt 1
{
static unsigned int time=0,time1=0;
TH0=THC0;
TL0=TLC0;
time++; //轉(zhuǎn)速測量周期
time1++;
if(time1>=5)
{
time1=0;
flag=1;
Display_Key(Key_Scan());//按鍵按下,鍵值碼送入函數(shù),以便做相應(yīng)動(dòng)作
aa[7]=SpeedSet/1000+'0';
aa[8]=SpeedSet/100%10+'0';
aa[9]=SpeedSet/10%10+'0';
aa[10]=SpeedSet%10+'0';
}
if(time>500)
{
zs=1;
time=0;
num=Inpluse; //計(jì)算式中是仿真時(shí),碼盤數(shù)60時(shí)的情況,如果碼盤數(shù)n=10時(shí),num=Inpluse*60/n=Inpluse*6;
Inpluse=0;
PIDControl();
}
PWMOUT();
}
void timer_1() interrupt 3
{
cnt++; //cnt越大占空比越高2.5Khz
}
|
評分
-
查看全部評分
|