|
示波器圖中,紫色線高點(diǎn)是3.5v,低點(diǎn)是1.5v
一一對(duì)應(yīng)程序中的getset(350),getset(150)
仿真正確
此pid封裝成.c .h文件形式,可以直接調(diào)用
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
(1) 了解工業(yè)過(guò)程控制的一般情況;
(2) 掌握數(shù)字PID控制器程序設(shè)計(jì)方法;
2.實(shí)驗(yàn)內(nèi)容
設(shè)計(jì)單片機(jī)控制電路,采用TLC5615和LTC1292芯片采集電壓和輸出電壓,并編寫(xiě)數(shù)字PI控制器程序,對(duì)直流電機(jī)進(jìn)行控制,要求采樣周期100毫秒,對(duì)設(shè)定值轉(zhuǎn)速和實(shí)際轉(zhuǎn)速進(jìn)行實(shí)時(shí)顯示。
PID采用增量式,定點(diǎn)計(jì)算,輸入要濾波,輸出要限幅。
3、預(yù)備知識(shí)
控制系統(tǒng)軟件的設(shè)計(jì),一般必須有嚴(yán)格的時(shí)間限制,故必須基于定時(shí)中斷進(jìn)行設(shè)計(jì),在中斷中運(yùn)行實(shí)時(shí)性要求的程序,如A/D采樣程序、PID控制程序、D/A輸出程序、數(shù)碼管顯示刷新程序和鍵盤(pán)掃描程序等。在主程序中進(jìn)行一些實(shí)時(shí)性要求低的程序,如打印程序、數(shù)據(jù)輸入程序等。
4、實(shí)驗(yàn)步驟
從D/A輸出點(diǎn)接一個(gè)二階慣性對(duì)象,將對(duì)象輸出接A/D輸入點(diǎn)。
在PC機(jī)輸入源程序并匯編,然后下載到單片機(jī)上,進(jìn)行調(diào)試。
注意二階系統(tǒng)的電路需要與單片機(jī)共地
(1) 整理好實(shí)驗(yàn)程序。
(2) 總結(jié)比例參數(shù)P積分參數(shù)I和采樣周期對(duì)控制系統(tǒng)性能的影響。
單片機(jī)源程序如下:
PID.C
- #include "pid.h"
- PID pid;
- void PIDParament_Init() //
- {
- pid.choose_model = MODEL_PID;
- pid.T=5; //采樣周期
- pid.set =280; //用戶設(shè)定值
- pid.Kp=20; //比例系數(shù)
- pid.Ti=100; //積分比例常數(shù)
- pid.Td=5; //微分時(shí)間常數(shù)
- pid.OUT0=0; //一個(gè)維持的輸出
- pid.pwmcycle = 280; //PWM的周期
- }
-
- void pid_calc() //pid計(jì)算
- {
- float dk1;float dk2;
- float t1,t2,t3;
- // if(pid.Tdata < (pid.T)) //最小計(jì)算周期未到
- // {
- // return ;
- // }
- // pid.Tdata = 0;
- pid.curr=LTC1292(); //A/D輸入值
-
- pid.En=pid.set-pid.curr; //本次誤差
-
-
- dk1=pid.En-pid.En_1; //本次誤差與上次誤差之差
- dk2=pid.En-2*pid.En_1+pid.En_2; //理解為第二個(gè)誤差
-
- t1=pid.Kp*dk1; //比例
-
- t2=(pid.Kp*pid.T)/pid.Ti; //積分
- t2=t2*pid.En;
-
- t3=(pid.Kp*pid.Td)/pid.T; //微分
- t3=t3*dk2;
-
- switch(pid.choose_model)
- {
- case MODEL_P: pid.Dout= t1; //僅使用P計(jì)算
-
- break;
-
- case MODEL_PI: pid.Dout= t1+t2; //使用PI計(jì)算
-
- break;
-
- case MODEL_PID: pid.Dout= t1+t2+t3; //使用PID計(jì)算
- break;
- }
-
- pid.currpwm+=pid.Dout; //本次應(yīng)該輸出的PID
- // if(pid.currpwm>pid.pwmcycle) //判斷本次輸出的PID在輸出要求之間
- // {
- // pid.currpwm=pid.pwmcycle;
- // }
- // if(pid.currpwm<0)
- // {
- // pid.currpwm=0;
- // }
- if(pid.currpwm>1023*15) pid.currpwm=1023*15;//輸出擴(kuò)大,使效果明顯
- if(pid.currpwm<0) pid.currpwm=0;
- pid.En_2=pid.En_1;//每次更新的交換,先交換e2的值,再交換e1
- pid.En_1=pid.En;
- //此處輸出PWM
- TLC5615(pid.currpwm/15);
- }
復(fù)制代碼- #include <reg52.h>
- #include <pid.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define ulong unsigned long
- //sfr AUXR =0x8E;
- sbit ADAT=P2^5;
- sbit ACLK=P2^6;
- sbit ACS =P2^7;
- sbit Set=P3^7;
- uint LTC1292(void) //輸入值
- {
- uint i,x;
- ACLK=0; ADAT=1; ACS=0;
- for(i=0;i<14;i++)
- {
- ACLK=1;
- x<<=1;
- if(ADAT==1) x++;
- ACLK=0;
- }
- ACS=1;
- return (x&0xfff);
- }
- sbit DDAT = P3^4;
- sbit DCS = P3^3;
- sbit DCLK = P3^2;
- void TLC5615(uint j) //輸出值,PID計(jì)算后輸出
- {
- uchar i;
- DCLK=0; DCS=0;
- j=j<<6;
- for(i=0;i<12;i++)
- {
- j=j<<1; DDAT=CY;
- DCLK=0; DCLK=1;
- }
- DCLK=0; DCS=1;
- }
- #define kp 20 //比例系數(shù)
- #define ki 1 //積分系數(shù)
- #define kd 15 //微分系數(shù)
- #define TIM -10000 //采樣周期
- int e0=0,e1=0,e2=0; //三個(gè)時(shí)刻
- int s; //增量式PID計(jì)算本次應(yīng)該輸出的增量值
- uint r,y; //r是實(shí)際要求的輸出,Y是A/D傳過(guò)來(lái)的輸出
- long u;
- void PID_in() interrupt 3
- {
- // float dk1,dk2;
- // float t1,t2,t3;//分別為比例、積分、微分
- TH1=TIM>>8; TL1=TIM&0Xff;
- // y=LTC1292(); //A/D輸入值
- // e2=e1=e0;
- // e0=r-y; //本次誤差
- //
- // dk1 = e0-e1;//上一次誤差
- // dk2 = e0-2*e1+e2;//上上次誤差
- //
- // u+=dk1*kp+e0*ki+dk2*kd;
- // if(u>1023*kd) u=1023*kd;
- // if(u<0) u=0;
- // s=u/kd;
- // TLC5615(s);
- pid_calc();
- }
- uint GetSet(ulong x)
- {
- ulong m;
- m=x*4095;
- return m/500;
- }
- void main()
- {
- IE=0x88;TMOD=0X11;
- TH1=TIM>>8; TL1=TIM&0xff;TR1=1;
- PIDParament_Init();
- while(1)
- {
-
- if(Set) pid.set=GetSet(350);
- else pid.set=GetSet(150);
-
- }
- }
復(fù)制代碼
仿真代碼資料51hei附件下載:
PID資料.7z
(106.09 KB, 下載次數(shù): 78)
2021-7-23 16:48 上傳
點(diǎn)擊文件名下載附件
|
評(píng)分
-
查看全部評(píng)分
|