Thứ Sáu, 17 tháng 7, 2009

Thiết kế bộ truyền nhận dữ liệu không dây qua cổng USB.

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

1. Tìm hiểu về nguyên lý thực hiện mạch truyền nhận dữ liệu không dây:
Giao tiếp wireless hiện nay được sử dụng rất nhiều , đặc biệt là trong các ứng dụng công nghiệp, và hơn nữa trong các máy tính xách tay chúng ta không còn thấy các cổng COM nữa mà dần dần được thay thế bởi cổng USB. Bài viết này hướng dẫn các bạn thực hiện bộ truyền nhận dữ liệu không dây qua cổng USB dựa trên Module Wireless UART sẵn có.
Nguyên lý thực hiện mạch:



Dựa vào nguyên lý trên chúng ta thấy rằng, cần thiết kế bộ giao tiếp: USB-UART làm nhiệm vụ cầu nối giữa module wireless và cổng USB của máy tính.
Vì thế các thiết bị sử dụng trong thiết kế:
- Module wireless UART tần số 915Mhz, tốc độ baud: 115K
- IC chuyển đổi USB – Com FT232 của hãng Future Technologies.
- Các linh kiện điện tử khác: điện trở, tụ điện, thạch anh... xem thêm trong sơ đồ mạch.

2. Sơ đồ mạch nguyên lý:

Giải thích các linh kiện sử dụng:
- FT232: IC chuyển đổi USB-Com.

FT232BM là IC giao tiếp Usb serial chuyển đổi từ UART sang USB với tốc độ cao tương thích chuẩn USB2.0,USB1.1 tốc độ baud có thể đạt tới 1Mbit/s, bộ nhớ hỗ trợ lớn 384 Byte Rx buffer/128 Byte Tx buffer, hỗ trợ hoạt động ở chế độ USB Bulk và Isochronous.
- 93C46: Eeprom lưu ID và các thông số cấu hình.
- Module wireless của Hoperf.

HM_TR wireless transceiver sử dụng công nghệ FSK, truyền bán song công, với độ ổn định cao, khoảng cách truyền lớn, ngõ ra theo chuẩn UART TTL thuận lợi cho giao tiếp với PC và MCU.
- Lưu ý: tụ điện C5 33nF có thể được thay thế bằng tự 47nF, hoặc 100nF.
Sau khi thực hiện xong mạch, các bạn có thể đóng hộp sản phẩm.
3. Một số hình ảnh tham khảo về module wireless USB:




4. Một số ứng dụng:

- Trao đổi dữ liệu trực tiếp giữa 2 PC.
- Điều khiển robot không dây sử dụng máy tính.
- Thu thập dữ liệu qua mạng không dây.
- .v..v..

Thứ Ba, 14 tháng 7, 2009

Xây dựng mạch điều khiển nhiệt độ sử dụng DS1820.

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

Phần 1: Tìm hiểu về IC nhiệt độ DS1820:
Mô tả tính năng của DS1820:
DS1820 là nhiệt kế số có độ phân giải 9-12bit giao tiếp với vi điều khiển trung tâm thông qua 1 dây duy nhất ( 1 wire communication). DS1820 hoạt động với điện áp từ 3V-5.5V có thể được cấp nguồn qua chân DQ- chân trao đổi dữ liệu. Nó có thể đo nhiệt độ trong tầm -55-125oC với độ chính xác +-0.5 oC. Mỗi DS1820 có một Serial code 64bits duy nhất, điều này cho phép kết nối nhiều IC trên cùng đường bus.
Chuẩn 1 wire có những đặc điểm sau:
- chỉ có một master trong hệ thống.
- Giá thành thấp.
- Tốc độ đạt dược tối đa 16kbps.
- Khoảng cách truyền xa nhất là 300m.
- Lượng thông tin trao đổi nhỏ.

DS1820 thường được ứng dụng trong các bộ điều khiển HVAC, hệ thống giám sát nhiệt độ trong các tòa nhà, thiết bị máy móc…
DS1820 thường có 3 chân chức năng chính:
1. Chân GND: chân nối đất.
2. Chân DQ: chân trao đổi dữ liệu, đồng thời là chân cấp nguồn cho toàn bộ hoạt động của IC, nếu chân Vcc không sử dụng. Khi kết nối với vi điều khiển thì cần phải có điện trở kéo lên khoảng 4.7k.
3. Chân Vcc: chân cấp nguồn.


Hình – Sơ đồ khối IC điều khiển nhiệt độ DS1820.
Nguyên tắc hoạt động:
Bên trong DS1820 sẽ có bộ chuyển đổi giá trị nhiệt độ sang giá trị số và được lưu trong các thanh thi ở bộ nhớ scratchpad. Độ phân giải nhiệt độ đo có thể được cấu hình ở chế độ 9 bits, 10bits, 11bits, 12bits. Ở chế độ mặc định thì DS1820 hoạt động ở độ phân giải 12bits. Để bắt đầu quá trình đọc nhiệt độ, và chuyển đổi từ giá trị tương tự sang giá trị số thì vi điều khiển gửi lênh Convert T [44h], sau khi chuyển đổi xong thì giá trị nhiệt độ sẽ được lưu trong 2 thanh ghi nhiệt độ ở bộ nhớ scratchpad và IC trở về trạng thái nghỉ.
Nhiệt độ được lưu bên trong DS1820 được tính ở nhiệt độ Celcius nếu tính ở nhiệt độ Fahrenheit cần phải xây dựng thêm bảng chuyển đổi nhiệt độ.
Giá trị nhiệt độ lưu trong bộ nhớ gồm 2bytes-16bits: số âm sẽ được lưu dưới dạng bù 2. Bit cao nhất là bit dấu (S) nếu S=0 thì giá trị nhiệt độ dương và S=1 thì giá trị nhiệt độ âm.
Nếu cấu hình độ phân giải là 12bits thì tất cả các bit đều được sử dụng. Nếu độ phân giải 11bits thì bit 0 không được sử dụng. Tương tự nếu cấu hình là 10bits thì bit 1,0 không được sử dụng, nếu cấu hình là 9 bits thì bit 2,1,0 không được sử dụng.

Hình – Định dạng giá trị nhiệt độ lưu khi độ phân giải là 12bits.


Hình – Quan hệ giữa nhiệt độ và giá trị lưu trong bộ nhớ ở độ phân giải 12bits.

Nhiệt độ sau khi được lưu vào trong 2 thanh ghi bộ nhớ sẽ được so sánh với 2 thanh ghi ngưỡng nhiệt độ TH và TL. Các giá trị ngưỡng nhiệt độ do người dùng quy định, và nó sẽ không thay đổi khi mất điện.

Như vậy chỉ có phần nguyên, các bit 11-4 của giá trị nhiệt độ được so sánh với thanh ghi ngưỡng. Nếu giá trị nhiệt độ đọc về nhỏ hơn mức TL hoặc lớn hơn mức TH thì cờ báo quá nhiệt sẽ được bật lên, và nó sẽ thay đổi ở mỗi quá trình đọc nhiệt độ. Vi điều khiển có thể kiểm tra trạng thái quá nhiệt bằng lệnh Alarm Search [ECh]
Tổ chức bộ nhớ:
Mỗi IC DS1820 có một mã 64bit riêng biệt bao gồm: 8 bit Family code, 48 bit serial code và 8 bit CRC code được lưu trong Rom. Các giá trị này giúp phân biệt giữa các IC với nhau trên cùng 1 bus. Giá trị Family code của DS1820 là 28h và giá trị CRC là kết quả của quá trình kiểm tra 56 bits trước đó.
Tổ chức bộ nhớ Scratchpad:
Bộ nhớ DS1820 bao gồm 9 thanh ghi 8bits:

Byte 0 và 1 lưu giá trị nhiệt độ chuyển đổi.
Byte 2 và 3 lưu giá trị ngưỡng nhiệt độ. ( giá trị này được lưu khi mất điện).
Byte 4 là thanh ghi cấu hình cho hoạt động của DS1820.
Byte 5,6 và 7 không sử dụng.
Byte 8 là thanh ghi chỉ đọc lưu giá trị CRC từ byte 0 đến byte 7.
Dữ liệu trong byte 2,3,4 được ghi thông qua lệnh Write Scratchpad [4Eh] và dữ liệu được truyền đến DS1820 với bit LSB của byte 2, sau khi ghi dữ liệu có thể được đọc lại thông qua lệnh Read Scratchpad [BEh], và khi đọc Scratchpad thì bit LSB của byte 0 sẽ được gửi đi trước – Tất cả các byte đều được đọc, nhưng chỉ ghi được byte 2,3 và 4. Để chuyển giá trị TH và TL từ bộ nhờ vào EEPROM thì cần gửi lệnh Copy Scratchpad [48h] đến DS1820. Và dữ liệu từ EEPROM cũng có thể được chuyển vào thanh ghi TH,TL thông qua lệnh Recall E2 [B8h].
Trao đổi dữ liệu giữa vi điều khiển và DS1820 thông qua ba bước sau:
1. Khởi tạo.
Quá trình khởi tạo bao gồm 1 xung reset do vi điều khiển master gửi đến slave DS1820, sau đó là xung presence từ DS1820 gửi đến vi điều khiển, để chỉ ra sự hiện diện của vi điều khiển và DS1820 và quá trình hoạt động trao đổi dữ liệu có thể bắt đầu.
2. Lệnh điều khiển ROM.
Các lệnh này làm việc với 64bits serial code ROM, lệnh này được phát ra sau quá trình khởi tạo. Lệnh cho phép vi điều khiển biết có bao nhiêu thiết bị và thiết bị loại gì trên bus. Có 5 lệnh điều khiển ROM:
a. SEARCH ROM [F0h]
Khi hệ thống bắt đầu hoạt động, thì vi điều khiển sử dụng lệnh này để kiểm tra code ROM của tất cả các thiết bị có trên bus cho phép vi điều khiển biết được số thiết bị và loại của thiết bị trên bus. Nếu trên bus chỉ có 1 thiết bị thì có thể sử dụng lệnh Read_ROM thay cho lệnh Search_ROM. Sau mỗi quá trình Search_ROM thì cần phải quay lại quá trình khởi tạo để reset hệ thống.
b. READ ROM [33h]
Lệnh này được sử dụng khi chỉ có 1 thiết bị trên bus. Lệnh này cho phép vi điều khiển đọc 64bit ROM code của thiết bị. Nếu trên bus có nhiều thiết bị thì lệnh này sẽ gây ra sự xung đột bus dữ liệu giữa các thiết bị.
c. MATCH ROM [55h]
Lệnh này theo sau bởi 64 bit ROM code cho phép vi điều khiển định địa chỉ thiết bị cần giao tiếp. Chỉ thiết bị có ROM code phù hợp sẽ trả lời, các thiết bị còn lại sẽ đợi xung reset tiếp theo.
d. SKIP ROM [CCh]
Lệnh này cho phép vi điều khiển gửi đồng thời đến tất cả các thiết bị trên bus mà không cần bất cứ thông tin nào về ROM Code. Ví dụ, muốn gửi lệnh Convert_T đến tất cả các thiết bị trên bus, thì đầu tiên ta gửi lệnh Skip_ROM sau đó tiếp theo là gửi lệnh Convert_T.
Tương tự như vậy, nếu theo sau lệnh Skip_ROM là lệnh Read_Scratchpad thì dữ liệu trên DS1820 được đọc về, và lưu ý rằng lệnh này chỉ thực hiện được khi trên bus có 1 thiết bị, nếu trên bus có nhiều thiết bị thì sẽ gây ra xung đột bus.
e. ALARM SEARCH [ECh]
Lệnh này gần giống với lệnh Search_ROM, nhưng lệnh này chỉ tác động đến thiết bị mà cờ alarm được bật lên sẽ trả lời. Lệnh này cho phép xác định các thiết bị mà ở đó nhiệt độ đo được vượt qua ngưỡng nhiệt độ, và sau khi lệnh này được thực thi thì vi điều khiển phải lập lại quá trình khởi tạo – quay lại bước 1.
3. Lệnh điều khiển DS1820.
Sau khi vi điều khiển định địa chỉ thiết bị cần giao tiếp thông qua các lệnh ROM, vi điều khiển sẽ gửi các lệnh điều khiển hoạt động của DS1820. Những lệnh này cho phép vi điều khiển ghi và đọc dữ liệu từ bộ nhờ Scratchpad của DS1820, bắt đầu quá trình chuyển đổi nhiệt độ, và xác định chế độ cấp nguồn.

Sử dụng thư viện Onewire của MikroC:
Ow_Reset
Cú pháp unsigned short Ow_Reset(unsigned short *port, unsigned short pin);
Trị trả về 0 nếu trong hệ thống có DS1820 , and 1 nếu không có DS1820.
Mô tả Gửi tín hiệu Reset đến DS1820. Thông số PORT và PIN cấu hình chân kết nối với DS1820.
Issues OneWire reset signal for DS1820. Parameters PORT and pin specify the location of DS1820.
Yêu cầu Chỉ làm việc với Dallas DS1820.
Ví dụ Reset DS1820 được kết nối qua chân RA5:
Ow_Reset(&PORTA, 5);
Ow_Read
Cú pháp unsigned short Ow_Read(unsigned short *port, unsigned short pin);
Trị trả về Dữ liệu được đọc từ thiết bị trên bus Onewire.
Mô tả Đọc 1 byte dữ liệu trên bus Onewire.
Yêu cầu Không
Ví dụ unsigned short tmp;
...
tmp = Ow_Read(&PORTA, 5);
Ow_Write
Cú pháp void Ow_Write(unsigned short *port, unsigned short pin, unsigned short par);
Trị trả về Không.
Mô tả Ghi 1 byte dữ liệu thông qua bus Onewire.
Yêu cầu Không.
Ví dụ Ow_Write(&PORTA, 5, 0xCC);

Phần 2: Sơ đồ phần cứng mạch điều khiển nhiệt độ:









Phần 3: Chương trình điều khiển nhiệt độ:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Project: Dieu khien nhiet do su dung Sensor nhiet do DS1820. //
// Thiet lap TEMP_RESOLUTION tuong ung voi do phan giai cua DS18x20: //
// 18S20: 9bits //
// 18B20: 12bits (Cau hinh mac dinh co the la 9,10,11 hay 12) //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define Relay_on PORTD.F4=0
#define Relay_off PORTD.F4=1


const unsigned short TEMP_RESOLUTION = 12;

const int RES_FACTOR_1[4] = {5000, 2500, 1250, 625};
const unsigned int RES_FACTOR_2[4] = {0x0001, 0x0003, 0x0007, 0x000F};
const unsigned int RES_FACTOR_3[4] = {0x8000, 0xC000, 0xE000, 0xF000};

int temp_setpoint;
unsigned temp;
unsigned short j, RES_SHIFT;
////////////////////////////////////////////////////////////////////
// Chuong trinh con hien thi gia tri nhiet do //
////////////////////////////////////////////////////////////////////
void Display_Temperature(unsigned int temp) {
const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;
unsigned int temp_whole, temp_fraction;
unsigned short i;
char text[8];

// Tach phan thap phan
temp_fraction = temp & RES_FACTOR_2[RES_SHIFT - 1];
temp_fraction = temp_fraction * RES_FACTOR_1[RES_SHIFT - 1];
// Luu lai gia tri nhiet do trom temp_whole.
temp_whole = temp;

// Kiem tra nhiet do <0.
if ((temp_whole & 0x8000) != 0u) i = 1; // Yes, i = 1
else i = 0; // No, i = 0
// Loai bo phan thap phan.
temp_whole >>= RES_SHIFT;

// Hieu chinh lai dau neu can.
if (i) temp_whole |= RES_FACTOR_3[RES_SHIFT - 1];

//Hien thi gia tri nhiet do ra LCD
IntToStr(temp_whole, text); // Chuyen nhiet do sang chuoi
Lcd_Out(2, 6, text); // hien thi phan nguyen ra LCD
Lcd_Chr_Cp('.'); // Hien thi dau "."


IntToStr(temp_fraction, text); // Chuyen phan thap phan sang chuoi

// Them so '0' vào vì chung ta hien thi 4 so le.
if (temp_fraction < 1000u) Lcd_Chr_Cp('0');
if (temp_fraction < 100u) Lcd_Chr_Cp('0');
if (temp_fraction < 10u) Lcd_Chr_Cp('0');

Lcd_Out_Cp(text); // Hien thi phan thap phan ra LCD.

Lcd_Chr_Cp(223); // Hien thi ki tu 'o'
Lcd_Chr_Cp('C'); // Hien thi ki tu 'C'
}
//////////////////////////////////////////////////////////////
// Chuong trinh con dieu khien nhiet do //
//////////////////////////////////////////////////////////////
void Control_Temperature(void){
// Kiem tra nhiet do <0.
if ((temp_whole & 0x8000) != 0u) i = 1; // Yes, i = 1
else i = 0; // No, i = 0
// Loai bo phan thap phan.
temp >>= RES_SHIFT;
// Hieu chinh lai dau neu can.
if (i) temp |= RES_FACTOR_3[RES_SHIFT - 1];
if (temp>=temp_setpoint) Relay_off; // ngat relay
if (temp< temp_setpoint) Relay_on; // dong relay
}
/////////////////////
// Chuong trinh chinh//
////////////////////
void main() {
ADCON1 = 0xFF; // Cau hinh chan RA5 la chan vao ra so - IO digital
PORTE = 0xFF;
TRISE = 0x0F; // PORTE la input
PORTB = 0;
TRISB = 0; // PORTB la output
PORTD = 0xFF;
TRISD = 0; // PORTD la output
temp_setpoint=68; // Nhiet do dat la 68 do C.
// Khoi tao hien thi LCD tren PORTB
Lcd_Init(&PORTB);
Lcd_Cmd(Lcd_CURSOR_OFF);
Lcd_Out(1, 1, " Temperature: ");

do { // main loop

Ow_Reset(&PORTE,2); // Gui tin hieu reset DS1820
Ow_Write(&PORTE,2,0xCC); // Gui lenh SKIP_ROM den DS1820
Ow_Write(&PORTE,2,0x44); // Gui lenh CONVERT_T
Delay_us(120);

Ow_Reset(&PORTE,2); // Reset lai DS1820
Ow_Write(&PORTE,2,0xCC); // Gui lenh SKIP_ROM den DS1820
Ow_Write(&PORTE,2,0xBE); // Gui lenh READ_SCRATCHPAD
Delay_ms(400); // Doi qua trinh doc

j = Ow_Read(&PORTE,2); // Doc LSB gia tri nhiet do
temp = Ow_Read(&PORTE,2); // Doc MSB gia tri nhiet do
temp <<= 8; temp += j; // Luu gia tri nhiet do vao bien temp.
Display_Temperature(temp); // Goi chuong trinh con hien thi nhiet do.
Control_Temperature(); // Goi chuong trinh con dieu khien nhiet do.
Delay_ms(500);
} while (1);

}



Bản quyền thuộc về: lamquochung.blogspot.com
Liên lạc: quochung11@gmail.com
HP:0906266126

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