Thứ Hai, 13 tháng 7, 2009

Điều khiển tốc độ động cơ DC sử dụng giải thuật điều khiển PID số với PIC18F4331

  • Người thực hiện: Lâm Quốc Hưng.


Thân chào các bạn, giải thuật điều khiển PID là một giải thuật điều khiển kinh điển. Theo thống kê thì giải thuật này chiếm khoảng 70% trong các bộ điều khiển sử dụng trong công nghiệp. Chính vì vậy, việc tiếp cận và xây dựng thuật toán điều khiển PID cho vi xử lý là một đề tài rất hay, được nhiều kĩ sư, sinh viên quan tâm. Bài viết này mình xin trình bày giải thuật PID để điều khiển vận tốc động cơ DC trên KIT phát triển của SUNO.

Để thực hiện đề tài này, mình đã sử dụng các công cụ sau:

1. KIT phát triển PIC của SUNO.



2. Module điều khiển động cơ DC SUNO.


3. Mạch nạp PIC SUNO.


4. Động cơ DC 12V - encoder 360 xung /vòng.

5. Trình biên dịch MikroC.


Nội dung của bài viết bao gồm các phần sau:

1. Lí thuyết về thuật toán PID:

2. Xây dựng mạch điều khiển tốc độ động cơ DC:

3. Viết chương trình cho vi điều khiển PIC 18F4431 trên SUNO PIC KIT:

4. Viết chương trình VB xây dựng giao diện điều khiển và giám sát:

5. Kết quả:

Nội dung chi tiết:

1. Lí thuyết về thuật toán PID:

2. Xây dựng mạch điều khiển tốc độ động cơ DC:
Mạch sử dụng vi điều khiển PIC 18F4331, tích hợp module giao tiếp với encoder, thuận lợi cho việc đọc vận tốc của động cơ DC.

Module lái động cơ DC được sử dụng có công suất khoảng 50W, và động cơ sử dụng với điện áp 12V – 1A.




3. Viết chương trình cho vi điều khiển PIC 18F4431 trên SUNO PIC KIT:

Đoạn chương trình bên dưới có các nhiệm vụ sau:

- Đọc vận tốc động cơ DC, sau thời gian lấy mẫu 200ms ( có thể thay đổi ).

- Hiển thị vận tốc ra LCD16x2.

- Tính toán giá trị PWM để điều khiển động cơ DC từ thuật toán PID.

- Gửi giá trị lên PC, và nhận giá trị vận tốc đặt từ PC.

Chương trình điều khiển:

//----------------------------------------------------------------------------//

// Chuong trinh dieu khien dong co - su dung giai thuat PID so //

// Dieu khien toc do - hien thi LCD 16x2 //

// Nguoi lap trinh: Lam Quoc Hung //

// Cong ty: Sun JSC //

// Version 1.0 - Ngay: 1/6/2009 //

//----------------------------------------------------------------------------//

#define DIR PORTC.F4

#define Umax 50000

// Khai bao bien //

unsigned int Vmotor=0,Vdat=50;

char text[6];

long tam;

unsigned char status_control=0,j=0,i,dutyc=0,value_pwm=0;

unsigned int Kp,Kd,Ki,T;

signed int e0,e1,e2;

signed int u0,u1;

unsigned int heso0,heso1,heso2;

// Chuong trinh con //

void uint2str(unsigned int uint){

unsigned char tam;

text[0]=uint/10000;

uint=uint-text[0]*10000;

text[1]=uint/1000;

uint=uint-text[1]*1000;

text[2]=uint/100;

uint=uint-text[2]*100;

text[3]=uint/10;

text[4]=uint-text[3]*10;

for(i=0;i<=4;i++){

text[i]+=0x30;

}

text[5]='\0';

}

void LCD_Display(void){

Lcd_Config(&PORTD,0,2,1,7,6,5,4);

Lcd_Cmd(LCD_CURSOR_OFF);

LCD_Out(1,2,"SUN JSC PIC KIT");

LCD_Out(2,4,"www.suno.vn");

Delay_ms(1000);

Lcd_Cmd(LCD_CLEAR);

LCD_Out(1,2,"Vdat = ");

LCD_Out(2,2,"Vmotor=");

}

void Display_Vmotor(void){

uint2str(Vmotor);

Lcd_Out(2,10,text);

uint2str(Vdat);

Lcd_Out(1,10,text);

}

unsigned int Read_Enc(void){

unsigned int enc;

i=POSCNTH;

enc=i*255+POSCNTL;

if(enc>=200)

return enc;

}

void Clear_Enc(void){

POSCNTH = 0x00;

POSCNTL = 0x00;

}

void Read_Velo(void){

unsigned long tam;

Vmotor=Read_Enc(); // Doc gia tri Enc

tam=Vmotor;

tam=tam*60/1000;

Vmotor=tam;

Clear_Enc(); // Xoa gia tri Enc

}

void Init_Dual_PWM(void){

// first determine frequency

// 8 mHz clock >> 2.000.000 cycles

// PR of 200 results in ~10 kHz PWM-frequency

// postscaler div 10 results in 1 kHz interrupt's if enabled

PORTC.f1 = 0;

PORTC.f2 = 0;

TRISC.f1 = 0;

TRISC.f2 = 0;

PR2 =200;

CCPR1L= 0;

CCPR2L = 0;

T2CON = 0b01001101; // T2 on , prescaler div 4 , postscaler / 10 to be used at 32 mHz

//T2CON := %01001100; // T2 on , prescaler off , postscaler / 10 to be used at 8 mhz

CCP1CON = 0b00001100; // pwm mode

CCP2CON = 0b00001100; // pwm mode

}

void set_pwm1(unsigned short duty ){ // range 0..200

ccpr1l = duty;

}

void set_pwm2(unsigned short duty ){ // range 0..200

ccpr2l = duty;

}

/// chuong trinh khoi dong ////////

//----------------------------------------------------------------------------//

void Init_PID(void) {

Kp=1;

Ki=1;

Kd=1;

T=1;

heso0=(float)Kp+(float)Kd/(float)T+(float)Ki*(float)T/2; //heso0=Kp+Kd/T+Ki*T/2;

heso1=(float)Ki*(float)T/2-(float)Kp-2*(float)Kd/(float)T; //heso1=-Kp -2*Kd/T+Ki*T/2;

heso2=(float)Kd/(float)T; //heso3=Kd/T;

//chu ki lay mau T=2

u0=0;

u1=0;

e0=0;

e1=0;

e2=0;

}

// Chuong trinh dieu khien vi tich phan ti le //

//----------------------------------------------------------------------------//

void PID_DC(void){

float tam;

char tam1;

e0=Vdat-Vmotor; //tham so k=0-2, tuong ung voi tung vung lo

if (e0>-200 && e0<200){

u0=u1+heso0*e0+heso1*e1+heso2*e2;//u0[k]=u1[k]+heso0*e0[k]+heso1*e1[k]+heso2*e2[k];//calcule signal control

if (u0>Umax){

u0=Umax;

}

if (u0<=0){

u0=0;

}

}

else if (e0>=200){

u0=Umax;

}

else if (e0<=-200){

u0=0;

}

tam=u0;

tam=tam*255/Umax ;

value_pwm=(char)tam;

set_pwm1(255-value_pwm);

u1=u0;

e2=e1;

e1=e0;

Usart_Write(Vmotor);

}

void Initial(void){

ANSEL0=0;

TRISA =0xFF; // PORTA as input

TRISC =0; // PORTC as output

TRISD =0; // PORTD as output

// Cau hinh Encoder

MAXCNTL=0xFF;

MAXCNTH=0xFF;

POSCNTH = 0x00;

POSCNTL = 0x00;

QEICON = 0b10101000;

DFLTCON = 0b00010011;//filter tren chan QEA clock devider 1:16

// PWM

set_pwm1(255);

set_pwm2(255);

DIR=0;

// UART

INTCON.PEIE=1; // cho phep ngat

INTCON.GIE=1;

PIE1.RCIE=1; // cho phep ngat nhan

Usart_Init(9600);

}

// Chuong trinh dieu khien chinh //

void main(void){

Init_Dual_PWM();

Initial();

Init_PID();

LCD_Display();

while(1){

Read_Velo();

PID_DC(); // Dieu khien van toc

Display_Vmotor();// Hien thi van toc ra LCD

Delay_ms(100);

}

}

// chuong trinh phuc vu ngat //

void interrupt(void){

if(PIR1.RCIF==1){ // ngat nhan USART

PIR1.RCIF=0;

Vdat=RCREG;

if(Vdat>=120) {

Vdat=120;

}

}

}

4. Viết chương trình VB xây dựng giao diện điều khiển và giám sát:

- Do van toc: hiển thị vận tốc đo được, nhận từ vi điều khiển.

- Dat van toc: đặt vần tốc cho động cơ ( giới hạn Vận tốc max khoảng 120rpm).

- Comm Port: chọn cổng Com.

- Connect: cho phép kết nối với cổng Com.

- Exit: thoát khỏi chương trình.

- Send: gửi giá trị vận tốc đặt cho vi điều khiển.

Chương trình VB6:

Option Explicit

Dim command As Byte

Dim status_receive As Byte

Dim StrRcv As String

Dim a As Integer

-----------------------------------------

Private Sub CWNTdat_ValueChanged(Value As Variant, PreviousValue As Variant, ByVal OutOfRange As Boolean)

If CWNTdat.Value >= 120 Then

CWNTdat.Value = 120

End If

If CWNTdat.Value <= 0 Then

CWNTdat.Value = 0

End If

End Sub

---------------------------------------------------

Private Sub Form_Load()

cmd_Send.Enabled = False ' disable send

End Sub

---------------------------------------------------

Private Sub cmd_Connect_Click()

On Error GoTo errlable

If MSComm1.PortOpen = True Then MSComm1.PortOpen = False

If MSComm1.PortOpen = False Then

---------------------------------------------------

' chon cong com

If cmb_Comport.ListIndex >= 0 Then

MSComm1.CommPort = cmb_Comport.ListIndex + 1

Else

MsgBox " Please select Comport.", vbInformation = vbOK, " Attention "

Exit Sub

End If

' MSComm1.CommPort = 1

' chon toc do baudrate

MSComm1.Settings = "9600,n,8,1"

MSComm1.PortOpen = True

MSComm1.InputLen = 0

MSComm1.InputMode = comInputModeText

MSComm1.RThreshold = 1

cmd_Connect.Caption = "Connected"

cmd_Connect.Enabled = False ' disable connect

cmd_Send.Enabled = True ' enable send

cmb_Comport.Enabled = False ' disable comport

MsgBox " Connected. "

End If

errlable:

If Err.Number = 8005 Then ' cong com da duoc mo

MsgBox "COM port are opened", vbInformation = vbOK, " Attention "

End If

If Err.Number = 8002 Then

MsgBox "Select difference COM port ", vbInformation = vbOK, "Attention "

End If

End Sub

---------------------------------------

Private Sub cmd_Exit_Click()

If MSComm1.PortOpen = True Then MSComm1.PortOpen = False

End

End Sub

---------------------------------------

Private Sub mnu_Disconnect_Click() ' dong cong com va cho phep chon lai thong so khac.

If MSComm1.PortOpen = True Then MSComm1.PortOpen = False ' dong cong com.

cmb_Comport.Enabled = True

cmd_Connect.Caption = "Connect"

cmd_Connect.Enabled = True

cmd_Send.Enabled = False ' disable send

End Sub

--------------------------------------

Private Sub mnu_Exit_Click()

If MSComm1.PortOpen = True Then MSComm1.PortOpen = False

End

End Sub

--------------------------------------

Private Sub MSComm1_OnComm()

Dim serialInput As Variant

CWKnob1.Value = Asc(MSComm1.Input)

End Sub

--------------------------------------

Private Sub cmd_Send_Click()

MSComm1.Output = Chr(CWNTdat.Value)

End Sub

5. Kết luận:

Chương trình điều khiển vận tốc với sai số gần như bằng 0 khi hệ thống xác lập. Để cho chất lượng của hệ thống tốt hơn, tìm ra bộ thông số PID thích hợp, chúng ta có thể sử dụng thêm các giải thuật thông minh khác.


Hình – Vận tốc đặt 100 rpm và vận tốc đo về 100 rpm.







  • Bản quyền thuộc về: lamquochung.blogspot.com
  • Liên hệ: Lâm Quốc Hưng Email: quochung11@gmail.com
  • HP: 0906.266.126

1 nhận xét:

  1. Bài viết rất hay và rất thiết thực, các bạn sinh viên đại học có thể chọn đề tài này để làm đồ án cũng rất tốt.

    Trả lờiXóa