示波器圖中,紫色線高點是3.5v,低點是1.5v
一一對應程序中的getset(350),getset(150)
仿真正確
此pid封裝成.c .h文件形式,可以直接調用
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
){{IP9PSZZ}XE7NL7A5T~EX.png (92.66 KB, 下載次數: 63)
下載附件
2021-7-23 16:10 上傳
(NH189WZLI)~ULF%R6@GYHW.png (175.05 KB, 下載次數: 44)
下載附件
2021-7-23 16:10 上傳
51hei.gif (181.28 KB, 下載次數: 46)
下載附件
2021-7-23 16:51 上傳
(1) 了解工業過程控制的一般情況;
(2) 掌握數字PID控制器程序設計方法;
2.實驗內容
設計單片機控制電路,采用TLC5615和LTC1292芯片采集電壓和輸出電壓,并編寫數字PI控制器程序,對直流電機進行控制,要求采樣周期100毫秒,對設定值轉速和實際轉速進行實時顯示。
PID采用增量式,定點計算,輸入要濾波,輸出要限幅。
3、預備知識
控制系統軟件的設計,一般必須有嚴格的時間限制,故必須基于定時中斷進行設計,在中斷中運行實時性要求的程序,如A/D采樣程序、PID控制程序、D/A輸出程序、數碼管顯示刷新程序和鍵盤掃描程序等。在主程序中進行一些實時性要求低的程序,如打印程序、數據輸入程序等。
4、實驗步驟
從D/A輸出點接一個二階慣性對象,將對象輸出接A/D輸入點。
在PC機輸入源程序并匯編,然后下載到單片機上,進行調試。
注意二階系統的電路需要與單片機共地
(1) 整理好實驗程序。
(2) 總結比例參數P積分參數I和采樣周期對控制系統性能的影響。
單片機源程序如下:
PID.C
- #include "pid.h"
- PID pid;
- void PIDParament_Init() //
- {
- pid.choose_model = MODEL_PID;
- pid.T=5; //采樣周期
- pid.set =280; //用戶設定值
- pid.Kp=20; //比例系數
- pid.Ti=100; //積分比例常數
- pid.Td=5; //微分時間常數
- pid.OUT0=0; //一個維持的輸出
- pid.pwmcycle = 280; //PWM的周期
- }
-
- void pid_calc() //pid計算
- {
- float dk1;float dk2;
- float t1,t2,t3;
- // if(pid.Tdata < (pid.T)) //最小計算周期未到
- // {
- // 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; //理解為第二個誤差
-
- 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計算
-
- break;
-
- case MODEL_PI: pid.Dout= t1+t2; //使用PI計算
-
- break;
-
- case MODEL_PID: pid.Dout= t1+t2+t3; //使用PID計算
- break;
- }
-
- pid.currpwm+=pid.Dout; //本次應該輸出的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;//輸出擴大,使效果明顯
- 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);
- }
復制代碼- #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計算后輸出
- {
- 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 //比例系數
- #define ki 1 //積分系數
- #define kd 15 //微分系數
- #define TIM -10000 //采樣周期
- int e0=0,e1=0,e2=0; //三個時刻
- int s; //增量式PID計算本次應該輸出的增量值
- uint r,y; //r是實際要求的輸出,Y是A/D傳過來的輸出
- 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);
-
- }
- }
復制代碼
仿真代碼資料51hei附件下載:
PID資料.7z
(106.09 KB, 下載次數: 78)
2021-7-23 16:48 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|