- UID
- 373967
- 帖子
- 9008
- 主題
- 2609
- 精華
- 0
- 積分
- 1003
- 楓幣
- 0
- 威望
- 980
- 存款
- 35891
- 贊助金額
- 0
- 推廣
- 0
- GP
- 1205
- 閱讀權限
- 70
- 在線時間
- 460 小時
- 註冊時間
- 2023-1-12
- 最後登入
- 2024-12-22
|
製作PID控制器所需的零件如下:
PIC16F877微控制器
16x2液晶顯示器
電位計
電容
電阻
電晶體
繼電器
電源供應器
PIC16F877微控制器的引腳連結如下:
VDD連接至電源正極
VSS連接至電源負極
RA0連接至電位計輸出
RA1連接至繼電器控制腳
RA2連接至液晶顯示器RS腳
RA3連接至液晶顯示器EN腳
RC0連接至液晶顯示器D4腳
RC1連接至液晶顯示器D5腳
RC2連接至液晶顯示器D6腳
RC3連接至液晶顯示器D7腳
以下是PIC16F877製作PID控制器的程式碼,使用的開發環境是MPLAB IDE和XC8編譯器:
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 20000000
// PID參數
float Kp = 1.0;
float Ki = 0.0;
float Kd = 0.0;
float last_error = 0.0;
float integral = 0.0;
// 目標值
float target = 50.0;
void main(void) {
// 設定I/O
TRISA = 0b00000001; // RA0為輸入
TRISC = 0b00000000; // RC為輸出
// 設定液晶顯示器
Lcd_Init();
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Write_String("Temperature: ");
// 設定ADC
ADC_Init();
// 設定計時器
TMR1_Init();
while(1) {
// 讀取溫度值
float temp = ADC_Read(0);
temp = temp * 0.4887; // 轉換為攝氏溫度
// 計算誤差
float error = target - temp;
// 計算PID輸出
float Pout = Kp * error;
integral += error;
float Iout = Ki * integral;
float derivative = error - last_error;
float Dout = Kd * derivative;
float output = Pout + Iout + Dout;
last_error = error;
// 限制輸出範圍
if(output > 255) {
output = 255;
} else if(output < 0) {
output = 0;
}
// 控制繼電器
if(output > temp) {
PORTAbits.RA1 = 1;
} else {
PORTAbits.RA1 = 0;
}
// 顯示溫度和PID輸出
Lcd_Set_Cursor(1, 14);
Lcd_Write_Char(temp/10 + '0');
Lcd_Write_Char(temp%10 + '0');
Lcd_Write_String("C ");
Lcd_Set_Cursor(2, 1);
Lcd_Write_String("PID Output: ");
Lcd_Set_Cursor(2, 13);
Lcd_Write_Char(output/100 + '0');
Lcd_Write_Char((output/10)%10 + '0');
Lcd_Write_Char(output%10 + '0');
__delay_ms(500);
}
}
// 設定ADC
void ADC_Init() {
ADCON0 = 0b00000001; // 設定RA0為輸入和啟用ADC
ADCON1 = 0b00000000; // 設定VDD和VSS為參考電壓
__delay_us(20);
}
// 讀取ADC
float ADC_Read(unsigned char ch) {
if(ch > 7) {
return 0;
}
ADCON0 = (ch<<2) | 0b00000001;
__delay_us(20);
GO_DONE = 1;
while(GO_DONE);
return ADRESH * 256 + ADRESL;
}
// 設定計時器
void TMR1_Init() {
T1CON = 0b00000111; // 設定為16位元計時器、Fosc/256、啟用計時器
}
// 設定液晶顯示器
void Lcd_Init() {
Lcd_Port = 0x00;
__delay_ms(20);
Lcd_Command(0x03);
__delay_ms(5);
Lcd_Command(0x03);
__delay_ms(11);
Lcd_Command(0x03);
Lcd_Command(0x02);
Lcd_Command(0x28);
Lcd_Command(0x0c);
Lcd_Command(0x06);
Lcd_Command(0x01);
}
// 寫入液晶顯示器指令
void Lcd_Command(unsigned char cmd) {
Lcd_Port = cmd;
RS = 0;
EN = 1;
__delay_ms(4);
EN = 0;
}
// 寫入液晶顯示器字符
void Lcd_Write_Char(unsigned char data) {
Lcd_Port = data;
RS = 1;
EN = 1;
__delay_us(40);
EN = 0;
}
// 寫入液晶顯示器字串
void Lcd_Write_String(char *str) {
int i;
for(i=0;str[i]!='\0';i++) {
Lcd_Write_Char(str[i]);
}
}
// 設定液晶顯示器游標位置
void Lcd_Set_Cursor(unsigned char row, unsigned char col) {
if(row == 1) {
Lcd_Command(0x80 + col - 1} else if(row == 2) {
Lcd_Command(0xc0 + col - 1);
}
}
// 計算PID輸出
int PID_Controller(float set_point, float process_variable) {
static float integral = 0;
static float derivative = 0;
static float last_error = 0;
float error = set_point - process_variable;
integral += error * TIME_INTERVAL;
derivative = (error - last_error) / TIME_INTERVAL;
last_error = error;
return (int)(KP * error + KI * integral + KD * derivative);
}
關於連結腳位,請參考PIC16F877的資料手冊,其中包括了PIC16F877的腳位圖和對應的功能,以及每個腳位的電氣特性和建議的連接方法。
|
|