本帖最后由 hzz156077851 于 2013-5-20 13:26 編輯
以下是我編好的調(diào)試好的可用的測速及顯示模塊,需要在此基礎(chǔ)上加上PID調(diào)速模塊。
要求如下:直流電機(jī)增量式PID的速度閉環(huán)控制。通過光電傳感器回饋的脈沖(電機(jī)沒轉(zhuǎn)得到2脈沖)測得當(dāng)前的電機(jī)轉(zhuǎn)速,通過PID調(diào)節(jié)得到當(dāng)前的輸出PWM占空比。4位的7段碼LCD顯示當(dāng)前速度。PID參數(shù)可我自己根據(jù)電機(jī)特性調(diào)整。(目前測速和顯示程序已經(jīng)編寫好)
我的聯(lián)系QQ:156077851,電話:15249237747
程序編寫要求:
測速和顯示程序已經(jīng)編好了,需要在此基礎(chǔ)上實(shí)現(xiàn)直流電機(jī)的PID閉環(huán)調(diào)速。是基于STC89C52單片機(jī)的程序。
不需要仿真和電路圖。
直流電機(jī)使用L298實(shí)現(xiàn)PWM調(diào)速的。由于單片機(jī)上沒有按鍵,要用循環(huán)語句讓電機(jī)以一個(gè)速度恒定的運(yùn)行8秒,8秒后通過軟件讓電機(jī)轉(zhuǎn)速增加一次并通過PID調(diào)速讓其穩(wěn)定在設(shè)定的轉(zhuǎn)速值(即軟件里面已經(jīng)事先通過循環(huán)語句(或table語句)寫好的轉(zhuǎn)速設(shè)定值)附近,然后再運(yùn)行個(gè)8秒之后電機(jī)速度再增加一次,如此直到增加9次后電機(jī)停止運(yùn)行。整個(gè)過程直流電機(jī)通過軟件實(shí)現(xiàn)PWM調(diào)速的。電機(jī)設(shè)定的轉(zhuǎn)速分別為40,50,60,70,80,90,100,110,120r/s,每個(gè)速度各運(yùn)行8秒。
至于P I D的參數(shù)KP(比例系數(shù)) KI(積分系數(shù)) KD(微分系數(shù))參數(shù)的設(shè)定我自己通過實(shí)驗(yàn)調(diào)試,說是PID調(diào)速,其實(shí)我們老師要求我們只要用PI調(diào)速就可以了。所以微分環(huán)節(jié)可以不用。
電機(jī)的轉(zhuǎn)速范圍在40-130r/s之間把,別太高,也別低于40,不然電機(jī)轉(zhuǎn)不動(dòng);
L298N:
en1:表示直流電機(jī)的 使能端 當(dāng)值為1(高電平)時(shí)有效,接在了單片機(jī)的P1.2引腳;
zhen1:表示直流電機(jī)的 正轉(zhuǎn)信號(hào)輸出端,當(dāng)值為1(高電平)時(shí)有效,接在了單片機(jī)的P1.0引腳;
fan1:表示直流電機(jī)的 反轉(zhuǎn)信號(hào)輸出端,當(dāng)值為1(高電平)時(shí)有效,接在了單片機(jī)的P1.1引腳;
光電測速傳感器的 脈沖信號(hào)輸出端 接的是P3.5引腳;
PWM一個(gè)周期是20ms;
下面是已經(jīng)編好的測試通過的可以測速和顯示速度的程序:
#include <REG52.H>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
uchar a,b,c,d;
#define LED_DAT P0
sbit pin_SpeedSenser = P3^5; //速度傳感器脈沖信號(hào)輸出端接在T1上
#define TIME_CYLC 100 //12M晶振,定時(shí)器10ms 中斷一次 我們1秒計(jì)算一次轉(zhuǎn)速,1000ms/10ms = 100
#define PLUS_PER 2 //碼盤的齒數(shù) ,這里假定碼盤上有2個(gè)齒,即傳感器檢測到2個(gè)脈沖,認(rèn)為1圈
#define K 1.0 //校準(zhǔn)系數(shù)
sbit zhen1=P1^0;
sbit fan1=P1^1;
sbit en1=P1^2;
uchar code loops[] = {0x7f,0xbf,0xdf,0xef}; //定義顯示位控制驅(qū)動(dòng)碼
uchar code table[]={0x14,0xd7,0x4c,0x45,0x87,0x25,0x24,0x57,0x04,0x05}; // 0,1,2,3,4,5,6,7,8,9 7段碼表,這個(gè)單片機(jī)開發(fā)板上的LED數(shù)碼管的接法和一般的有點(diǎn)不一樣,這個(gè)表是正確的,已經(jīng)測試過了
uint Tcounter = 0; //時(shí)間計(jì)數(shù)器
bit Flag_Fresh = 0; // 刷新標(biāo)志
bit Flag_clac = 0; //計(jì)算轉(zhuǎn)速標(biāo)志
bit Flag_Err = 0; //超量程標(biāo)志
//在數(shù)碼管上顯示一個(gè)四位數(shù)
void DisplayFresh();
//計(jì)算轉(zhuǎn)速,并把結(jié)果放入數(shù)碼管緩沖區(qū)
void ClacSpeed();
//初始化定時(shí)器
void init_timer();
//延時(shí)函數(shù)
void Delay(uint ms);
void it_timer0() interrupt 1 //定時(shí)器0中斷的響應(yīng)函數(shù)
{
TF0 = 0; //定時(shí)器 T0用于數(shù)碼管的動(dòng)態(tài)刷新
TH0 = 0xD8; //初始化
TL0 = 0xF0;
Flag_Fresh = 1;
Tcounter++;
if(Tcounter>TIME_CYLC)
{
Flag_clac = 1;//周期到,該重新計(jì)算轉(zhuǎn)速了
}
}
void it_timer1() interrupt 3 //中斷地址是0x001b
{
TF1 = 0; //定時(shí)器T1用于單位時(shí)間內(nèi)收到的脈沖數(shù),要速度不是很快,T1永遠(yuǎn)不會(huì)益處
Flag_Err = 1; //如果速度很高,我們應(yīng)考慮另外一種測速方法:脈沖寬度算轉(zhuǎn)速
}
void main(void)
{
init_timer();
while(1)
{
zhen1=1;
fan1=0;
en1=1;
Delay(30);
en1=0;
Delay(170);
if(Flag_Fresh)
{
Flag_Fresh = 0;
DisplayFresh(); // 定時(shí)刷新數(shù)碼管顯示
}
if(Flag_clac)
{
Flag_clac = 0;
ClacSpeed(); //計(jì)算轉(zhuǎn)速,并把結(jié)果放入數(shù)碼管緩沖區(qū)
Tcounter = 0;//周期定時(shí)清零
TH1=TL1 = 0x00;//脈沖計(jì)數(shù)清零
}
if(Flag_Err) //超量程處理
{
//數(shù)碼管顯示字母'EEEE',開機(jī)時(shí)初始化為0000
a = 0x2c;
b = 0x2c;
c = 0x2c;
d = 0x2c;
while(1)
{
DisplayFresh();//等待復(fù)位,不再測速
}
}
}
}
//在數(shù)碼管上顯示一個(gè)四位數(shù)
void DisplayFresh()
{
P2 =loops[0] ;
LED_DAT = table[a];
Delay(20);
P2 =loops[1] ;
LED_DAT = table;
Delay(20);
P2 =loops[2] ;
LED_DAT = table[c];
Delay(20);
P2 =loops[3] ;
LED_DAT = table[d];
Delay(20);
}
//計(jì)算轉(zhuǎn)速,并把結(jié)果放入數(shù)碼管緩沖區(qū)
void ClacSpeed()
{
uint speed ;
ulong PlusCounter;
PlusCounter = TH1*256 + TL1;
speed = K*(PlusCounter/PLUS_PER);//K是校準(zhǔn)系數(shù),如速度不準(zhǔn),調(diào)節(jié)K的大小
a = (speed/1000)%10;
b = (speed/100)%10;
c = (speed/10)%10;
d = speed%10;
}
void init_timer() //初始化
{
TMOD = 0x51; //定時(shí)10毫秒,TOT1選擇軟件門方式1,T0定時(shí),T1計(jì)數(shù),96頁可查
TH0 = 0xD8; //T0初始化
TL0 = 0xF0;
ET0=1; //T0中斷允許
EA=1; //T0中斷
TR0=1; //TO運(yùn)行
TH1 = 0x00; //T1初始化
TL1 = 0x00;
ET1=1; //T1中斷允許
TR1=1; //T1運(yùn)行
zhen1=1;
fan1=0;
}
void Delay(uint ms) //0.1ms延時(shí)函數(shù)
{
uchar x,y;
for(x=ms;x>0;x--)
for(y=11;y>0;y--);
}
|