冰楓論壇

 找回密碼
 立即註冊
搜索
查看: 742|回覆: 0
打印 上一主題 下一主題

[討論] PIC16F877A

[複製鏈接]

2609

主題

0

好友

999

積分

高級會員

Rank: 4

UID
373967
帖子
8844
主題
2609
精華
0
積分
999
楓幣
0
威望
976
存款
34672
贊助金額
0
推廣
0
GP
1205
閱讀權限
50
在線時間
453 小時
註冊時間
2023-1-12
最後登入
2024-11-17

2023端午節紀念勳章 2023中秋節紀念勳章 2023聖誕節紀念勳章

跳轉到指定樓層
1
發表於 2023-4-27 06:28:00 |只看該作者 |倒序瀏覽
製作使用PIC16F877A微控制器的PID控制器
需要以下零件:

PIC16F877A微控制器
LCD顯示器
4x4矩陣按鈕
轉換器(例如:ADC0804)
電阻和電容(用於製作低通濾波器和電源電路)
直流電源供應器
電路板
電路連接線
訊號發生器

以下是PIC16F877A微控制器的腳位連結:

RA0 – 轉換器輸入

RA1 – 轉換器輸入

RA2 – 轉換器輸入

RA3 – 轉換器輸入

RA4 – 轉換器輸入

RA5 – 鍵盤輸入

RA6 – LCD顯示器數據線

RA7 – LCD顯示器數據線

RB0 – 轉換器輸入

RB1 – 轉換器輸入

RB2 – 轉換器輸入

RB3 – 轉換器輸入

RB4 – LCD顯示器選擇器

RB5 – LCD顯示器選擇器

RB6 – LCD顯示器選擇器

RB7 – LCD顯示器選擇器

RC0 – LCD顯示器使能信號

RC1 – LCD顯示器使能信號

RC2 – LCD顯示器使能信號

RC3 – LCD顯示器使能信號

RC4 – 訊號發生器輸入

RC5 – 訊號發生器輸入

RC6 – 訊號發生器輸入

RC7 – 訊號發生器輸入

以下是PID控制器的基本程式碼,可在MPLAB IDE中編譯和上傳到PIC16F877A微控制器中:


#include <pic.h>

#define RS RC0
#define EN RC1
#define D4 RC2
#define D5 RC3
#define D6 RC4
#define D7 RC5
#define Kp 1.0
#define Ki 0.5
#define Kd 0.2

void lcd_init();
void lcd_cmd(unsigned char);
void lcd_data(unsigned char);
void lcd_string(unsigned char *);
void delay_ms(unsigned int);
unsigned char read_adc(unsigned char);

void main() {
  unsigned char setpoint = 0, process_variable = 0, error = 0, previous_error = 0;
  float integral = 0, derivative = 0, output = 0;
  char buffer[16];
  
A0 = 1; // 將A/D轉換器輸入通道設置為RA0
A1 = 1;
A2 = 1;
A3 = 1;
A4 = 1;
TRISB = 0xF0; // 設置RB0-RB3為輸入,RB4-RB7為輸出
TRISC = 0x00; // 設置RC0-RC7為輸出

lcd_init(); // 初始化LCD顯示器

while(1) {
// 讀取設定點和過程變量
setpoint = read_adc(0);
process_variable = read_adc(1);

// 計算誤差和積分
error = setpoint - process_variable;
integral += error;
derivative = error - previous_error;
previous_error = error;

// 計算PID輸出
output = Kp * error + Ki * integral + Kd * derivative;

// 顯示PID輸出和其他信息
lcd_cmd(0x01); // 清屏
lcd_string("Setpoint: ");
sprintf(buffer, "%d", setpoint);
lcd_string(buffer);
lcd_cmd(0xC0); // 移到第二行
lcd_string("PV: ");
sprintf(buffer, "%d", process_variable);
lcd_string(buffer);
lcd_string("   ");
lcd_cmd(0x94); // 移到第三行
lcd_string("Output: ");
sprintf(buffer, "%.2f", output);
lcd_string(buffer);

delay_ms(1000); // 延遲1秒
}
}

void lcd_init() {
lcd_cmd(0x02); // 返回首位
lcd_cmd(0x28); // 4位數據線,2行顯示,5x8點陣字型
lcd_cmd(0x0C); // 顯示器開啟,光標不顯示
lcd_cmd(0x06); // 光標右移,字符不移動
}

void lcd_cmd(unsigned char cmd) {
RS = 0; // 選擇命令模式
D4 = ((cmd >> 4) & 0x01);
D5 = ((cmd >> 5) & 0x01);
D6 = ((cmd >> 6) & 0x01);
D7 = ((cmd >> 7) & 0x01);
EN = 1;
delay_ms(1);
EN = 0;
D4 = (cmd & 0x01);
D5 = ((cmd >> 1) & 0x01);
D6 = ((cmd >> 2) & 0x01);
D7 = ((cmd >> 3) & 0x01);
EN = 1;
delay_ms(1);
EN = 0;
}

void lcd_data(unsigned char data) {
RS = 1; // 選擇數據模式
D4 = ((data >> 4) & 0x01);
D5 = ((data >> 5) & 0x01);
D6 = ((data >> 6) & 0x01);
D7 = ((data >> 7) & 0x01);
EN = 1;
delay_ms(1);
EN = 0;
D4 = (data & 0x01);
D5 = ((data >> 1) & 0x01);
D6 = ((data >> 2) & 0x01);
D7 = ((data >> 3) & 0x01);
EN = 1;
delay_ms(1);
EN = 0;
}

void lcd_string(char *str) {
while(*str) {
lcd_data(*str++);
}
}

int read_adc(unsigned char channel) {
unsigned int result;
ADCON0 = (channel << 2) | 0x01; // 選擇通道,啟動A/D轉換器
delay_us(10);
GO_DONE = 1; // 啟動轉換
while(GO_DONE); // 等待轉換完成
result = ADRESH;
result = (result << 8) | ADRESL;
return result;
}

void delay_ms(unsigned int ms) {
unsigned int i, j;
for(i = 0; i < ms; i++) {
for(j = 0; j < 1000; j++);
}
}

void delay_us(unsigned int us) {
unsigned int i;
for(i = 0; i < us; i++) {
_delay(5); // 使用5個指令進行延遲
}
}

void _delay(unsigned char n) {
while(n--);
}

最後是PID控制器的主要程式碼:

void pid_control() {
int current_value = read_adc(0); // 讀取目前的測量值
int error = set_point - current_value; // 計算誤差值
integral += error; // 累加誤差值
int derivative = error - last_error; // 計算誤差變化率
last_error = error; // 更新上一次的誤差值
int output = Kp * error + Ki * integral + Kd * derivative; // 計算輸出值
output = constrain(output, 0, 255); // 限制輸出值在0~255之間
PWM = output; // 設定PWM輸出
}

上述程式碼中的read_adc函式會讀取ADC轉換器的值,這個值是模擬信號經過轉換器轉換後得到的數字,代表著模擬信號的大小。

接下來計算誤差值、累加誤差值、計算誤差變化率,並根據PID公式計算輸出值。

最後將輸出值限制在0~255之間,並設定PWM輸出。
收藏收藏0 推0 噓0


把本文推薦給朋友或其他網站上,每次被點擊增加您在本站積分: 1彩票
複製連結並發給好友,以賺取推廣點數
簡單兩步驟,註冊、分享網址,即可獲得獎勵! 一起推廣文章換商品、賺$$
高級模式
B Color Image Link Quote Code Smilies |上傳

廣告刊登意見回饋關於我們管群招募本站規範DMCA隱私權政策

Copyright © 2011-2024 冰楓論壇, All rights reserved

免責聲明:本網站是以即時上載留言的方式運作,本站對所有留言的真實性、完整性及立場等,不負任何法律責任。

而一切留言之言論只代表留言者個人意見,並非本網站之立場,用戶不應信賴內容,並應自行判斷內容之真實性。

小黑屋|手機版|冰楓論壇

GMT+8, 2024-11-17 06:50

回頂部