http://dientuvietnam.net/forums/show...?t=1406&page=5
bài 46.
Chào các bạn. Tôi đã làm xong bài tập lớn môn lý thuyết điều khiển tự động là thiết kế bộ điều khiển PID trên nền PIC.Bây giờ tôi xin đưa các đoạn code của bài tập lớn của tôi.
Đầu tiên là công việc là lấy đặc tính đáp ứng h(t) của động cơ để từ đó tính toán các tham số Kp, Ki, Kd. Đây là bước tính toán thô các giá trị của bộ PID sau đó mình mới tinh chỉnh lại sau ở một chương trình khác.
Vi điều khiển ứng dụng: PIC6F877A
Ngôn ngữ lập trình: HTPIC
Trong bài này tôi mục đích làm như sau: khi ấn "P" trên giao diện trên PC hay nói cách khác truyền kí tự P xuống chip thì nó nhận lệnh và cho động cơ hoạt động. Tôi điều chế một xung 15KHZ, ở đây cho độ rộng 100% luôn. Và từ đó liên tục đọc 500 giá trị và truyền lên PC.
Thời gian trích mẫu của hệ thống là 10ms. Tôi truyền số xung đo được lên PC, từ số liệu này sẽ tính toán ra tốc độ thực và vẽ được hàm h(t) của đối tượng. Tôi dùng chương trình Terminal (do lười nên không viết chương trình trên PC riêng) và lấy dữ liệu và cho vào Matlab để nội suy ra hàm quá độ h(t) . Tôi định viết một chương trình bằng Matlab nhận giao tiếp RS232 tính toán và đưa ra đồ thị luôn. Nhưng phải chờ tí đã, dạo này ôn thi nên hơi lười làm.
Chương trình Terminal và giao tiếp RS232 các bạn có thể xem tại
http://www.picvietnam.com/forum/show...p?t=274&page=2
Code chương trình trên Matlab: dùng nội suy Cubic
Code:
hold off;
x_rough= 0:0.01:5;
%x_fine= 0:0.05:0.8 ;% chon buoc noi suy tu xmin:0.1:xmax( voi xmin la gia tri nho nhat cua x_rough, xmax tuong tu;
x_fine = 0:0.001: 5;
data = [ ]; // Các giá trị số xung đo được 500 giá trị
data = data * 1000 /(10 * 100 *12);
% tính toán ra tốc độ thực và chia cho 12V để suy ra đáp ứng khi U = 1V vì coi động cơ DC là tuyến tính
% 100 là số lỗ /1 vòng của Encoder
inter_cubic= interp1(x_rough,data,x_fine,'cubic');
% noi suy theo phuong phap cubic
plot(x_fine,inter_cubic,'k','LineWidth',2);
grid on;
Code cho PIC6F877A
Code:
#include<pic.h>
# include "stdio.h"
__CONFIG(HS & PWRTEN & BOREN & LVPDIS & WDTDIS );
const unsigned char Font[]={ 0b00000011, 0b10011111, 0b00100101, 0b00001101, 0b10011001,\
0b01001001, 0b01000001, 0b00011111, 0b00000001, 0b00001001};
# define Ts 10 // Thoi gian trich mau Ts (ms)
# define Encoder_resolution 100 // So lo cua Encoder/1 vong
# define Total_Point 500 // So diem can trich mau
// ham truyen du lieu
void putch(unsigned char byte)
{
/* output one byte */
while(!TXIF); /* set when register is empty */
// continue;
TXREG = byte;
}
//===== Ham khoi tao
void interrupt MyInt(void){
static volatile unsigned int i, Pulse_Encoder;
// i la so diem trich mau
// Pulse_Encoder = so xung do duoc tu Encoder
static volatile unsigned char allow,counter_Sampling;
// allow la bien cho phep bat dau trich mau
// counter_Sampling: bien dem de trich mau
unsigned char RC_USART; // gia tri doc duoc tu thanh ghi nhan du lieu USART
if(T0IF & T0IE){
TMR0 = 6;
T0IF = 0 ;// xoa co ngat
if((++counter_Sampling == Ts) && allow){ // Ts = 10 ms
Pulse_Encoder = (TMR1H << 8) | TMR1L;
// Toc do dong co = Pulse_Encoder * 1000 / (Encoder_resolution * Ts) (vong/s)
printf("%6d",Pulse_Encoder); // Truyen gia tri xung do tren Ts
counter_Sampling = 0;
if (i++ == Total_Point){
i = 0; // Neu trich duoc 500 diem thi dung dong co lai
CCPR1L = 0;
allow = 0;
};
};
};
if(RCIF){ // Neu co ngat nhan du lieu noi tiep
RC_USART = RCREG;
RCIF = 0; // Xoa co ngat RCIF
switch(RC_USART){
case 'P': // === Bat dau cho dong co chay cho do rong xung = 100%
TMR1ON = 0 ; // ngung Timer1
TMR1H = TMR1L = 0;
TMR1ON = 1 ; // bat lai Timer1
CCPR1L = PR2 + 1;
CCP1Y = CCP1X = 0;
allow = 1;
break;
};
};
}
//------------------------------------init
void init(void){
// Khoi tao cho USART
TRISC = TRISC | 0b11000000; // Bit 7,6 la RX va TX phai la Input
SPEN = 1 ; // Enable Serial Port communication.
SYNC = 0; // che do khong dong bo Asynchronous
// cho che do truyen
TXEN = 1; //enable truyen
TX9 = 0 ; // chon che do 8 truyen bit du lieu
BRGH = 1; // High - speed
SPBRG = 129; //Baud = 9600; voi HS, Baud Rate = Fosc/(16(X+1))
TXIE = 0; // khong dung ngat Truyen
// Che do nhan du lieu
RCIE = 1; // dung ngat nhan
PEIE = 1; // cho phep ngat ngoai vi
GIE = 1; // cho phep ngat toan cuc
RX9 = 0; // nhan 8 bit
CREN = 1; // lien tuc nhan du lieu; = 0 k lien tuc nhan du lieu
//===== init for PWM
// PWM Period = [ PR2 +1 ] x 4 x Tosc x (TMR2 Prescaler Value)
PR2 = 82; // Tan so = 15 KHz, TMR2 Prescaler Value = 4
// PWM Duty Cycle = [ CCPR1L : CCP1CON<5:4>) x Tosc x (TMR2 Prescaler Value)
// => CCPR1L : CCP1CON<5:4> = k% x (TMR2 + 1 ) x 4;
CCPR1L = 0;
TRISC2 = 0; // RC2 la output
RC2 = 1;
T2CON = 0b00000101; // Timer2 on, TMR2 Prescaler Value = 4
CCP1CON = 0b00001100; // CCP1 hoat dong trong che do PWM
//================= init for PORTs
OPTION = 0b00000000;
ADCON1 = 0b00000111;
TRISA = 0b00000000;
TRISD = 0b00000000;
PORTD = 0xFF;
//================ Khoi tao cho Timer0
GIE = 1;
T0IE = 1;
TMR0 = 6;
// ========= Khoi tao cho dem Timer1
TMR1CS = 1; // Timer1 hoat dong o che do Counter Mode
T1SYNC = 1; // TMR1 hoat dong o che do dem khong dong bo
T1OSCEN = 1; // Dem xung tu chan RC1/T1OSI/CCP2
T1CKPS1 = T1CKPS0 = 0; // Chon Prescaler = 1:1
TMR1H = TMR1L = 0;
TMR1IE = 0 ; // Khong dung ngat Timer1
TMR1ON = 1; // Bat Timer1
}
//------------------------------------MAIN
void main(){
init();
while(1);
}
// === Kết thúc
Chương trình đã test và cho đặc tính h(t) thí dụ với động cơ 12V của tôi như sau:
Hình bị mất, mình tìm lại upload sau
.
Chúc các bạn thành công.