引腳說明:
//定義MCU與LCD的接口
/*******************************
*D4---->PB8
*D5---->PB5
*D6---->PB6
*D7---->PB7
*RS---->PA8
*RW---->PA11
*EN---->PA12
LCD1602
VCC---->5V
GND---->GND
VO----->接對比度調節滑動變阻器- -->GND
LED+ -->5v
LED- -->GND
PWM輸出(12703半導體制冷片)
4A電機pwm驅動芯片
*制冷IN1---->PB10
*加熱IN2---->PB11
18B20數字溫度傳感器
18B20OUT---->PB9
按鍵
KEY1---->PB12
KEY1---->PB13
KEY1---->PB14
AT24C16
1(A0)---->GND
2(A1)---->GND
3(A2)---->GND
4(GND)---->GND
4(SDA)---->PC13---->4.7K(R)---->VCC
6(SCL)---->PC14---->4.7K(R)---->VCC
7(WP)---->GND---->104(C)---->VCC
8(VCC)---->VCC
功能說明:通過18B20檢測溫度,通過pwm輸出來調節控溫,未進行精準pid調試,恒溫時間大約在5min左右。
2021.8.25 :基本程序編寫完成。
2021.8.26:修改程序,既可以制熱也可以制冷。
2021.8.27:加入24c16用于存儲設定溫度和模式,優化lcd顯示。
制作出來的實物圖如下:
IMG_20210827_173553.jpg (3.77 MB, 下載次數: 72)
下載附件
2021-8-28 11:08 上傳
單片機源程序如下:
- #include "incrementpid.h"
- #include "usart.h"
- //增量式PID
- PID pid;
- u8 T_mode=1;//制冷(1)制熱(0)模式切換
- void PIDParament_Init() //
- {
- pid.choose_model = MODEL_PID;//調節模式
- pid.T=500; //采樣周期,定時器使用1ms,則最小執行PID的周期為500ms
- pid.set =25; //用戶設定值,攝氏度
- pid.Kp=0.6; //比例系數
- pid.Ti=100.0; //微分系數常數ms
- pid.Td=20.0; //積分時間常數ms
- pid.OUT0=0; //一個維持的輸出
- pid.pwmcycle = 1999; //PWM的周期
- }
-
- void pid_calc() //增量式PID調節函數
- {
- float dk1;float dk2;
- float t1,t2,t3;
-
- if(pid.Tdata < (pid.T)) //最小計算周期未到
- {
- return ;
- }
- pid.Tdata = 0;
-
- pid.En=pid.set-pid.curr; //本次誤差
- dk1=pid.En-pid.En_1; //本次偏差與上次偏差之差
- dk2=pid.En-2*pid.En_1+pid.En_2;
-
- t1=pid.Kp*dk1; //比例
-
- t2=(pid.Kp*pid.T)/pid.Ti; //積分
- t2=t2*pid.En;
-
- t3=(pid.Kp*pid.Td)/pid.T; //微分
- t3=t3*dk2;
-
- switch(pid.choose_model)
- {
- case MODEL_P: pid.Dout= t1; printf("使用P運算\r\n") ;
- break;
-
- case MODEL_PI: pid.Dout= t1+t2; printf("使用PI運算\r\n") ;
- break;
-
- case MODEL_PID: pid.Dout= t1+t2+t3; printf("使用PID運算\r\n") ;
- break;
- }
-
-
-
-
- if(T_mode==0)//制熱PID調節
- {
- pid.currpwm+=pid.Dout; //本次應該輸出的PWM
- printf("PID算得的OUT:\t%d\r\n",(int)pid.currpwm) ;
-
- /*判斷算出的數是否符合控制要求*/
- if(pid.currpwm>pid.pwmcycle) //算出的值取值,肯定是在0-pid.pwmcycle之間,不然的話PWM怎么輸出
- {
- pid.currpwm=pid.pwmcycle;
- }
- if(pid.currpwm<0)
- {
- pid.currpwm=0;
- }
- TIM_SetCompare4(TIM2,pid.currpwm); //pwm輸出函數
- TIM_SetCompare3(TIM2,0); //pwm輸出函數
- printf("實際輸出使用的OUT:\t%d\r\n",(int)pid.currpwm) ;
- }
- else if(T_mode==1)//制冷PID調節
- {
- pid.currpwm+=pid.Dout; //本次應該輸出的PWM
-
- printf("PID算得的OUT:\t%d\r\n",(int)pid.currpwm) ;
-
-
- if(-pid.currpwm>pid.pwmcycle)//算出的值取值,肯定是在0-pid.pwmcycle之間,不然的話PWM怎么輸出
- {
- pid.currpwm=-pid.pwmcycle; //pwm最大寬度
-
- }
- if(pid.currpwm>0)//當前的pwm寬度
- {
- pid.currpwm=0;
-
- }
- TIM_SetCompare3(TIM2,-pid.currpwm); //pwm輸出函數
- TIM_SetCompare4(TIM2,0);
- printf("實際輸出使用的OUT:\t%d\r\n",(int)pid.currpwm) ;
- }
-
- pid.En_2=pid.En_1;
- pid.En_1=pid.En;
- }
復制代碼
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
- #include "sys.h"
- #include "delay.h"
- #include "usart.h"
- #include "ds18b20.h"
- #include "LCD1602.h"
- #include "pwmout.h"
- #include "key.h"
- #include "timer3.h"
- #include "incrementpid.h"
- #include "24cxx.h"
- //float TM1;//存儲溫度值
- //s8 set_temp=30;//設定溫度
- uint8_t ucDs18b20Id[8];//存儲18b20數據
- u8 i;//循環讀取18b20ID次數
- u8 a,b,c=0;//lcd循環顯示
- u16 pwmval23=0,pwmval24=0;//占空比調節
- u8 cle_pwm1,cle_pwm2;//清除pwm顯示
- int main(void)
- {
- delay_init(); //延時函數初始化
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設置NVIC中斷分組2:2位搶占優先級,2位響應優先級
- uart_init(9600); //串口初始化為9600
- LCD_init();//lcd1206初始化
- PWM_Out_Init(); // 定時器輸出pwm初始化
- KEY_Input_Init();//GPIO IN初始化
- TIM3_Init(999,71); ////TIM2 1ms中斷
- PIDParament_Init() ;//增量式PID初始化
- AT24CXX_Init();//初始化IIC接口
-
-
- TIM_SetCompare3(TIM2,0); //pwm輸出函數
- TIM_SetCompare4(TIM2,0); //pwm輸出函數
-
- LCD_set_xy(1,2);//寫位置
- LCD_write_data('T'); //寫數據
- LCD_write_data('E'); //寫數據
- LCD_write_data('M'); //寫數據
- LCD_write_data('P'); //寫數據
- LCD_write_data(':'); //寫數據
- LCD_set_xy(1,1);//寫位置
- LCD_write_data('P'); //寫數據
- LCD_write_data('W'); //寫數據
- LCD_write_data('M'); //寫數據
- LCD_write_data(':'); //寫數據
- while( DS18B20_Init() ) //DS18B20初始化
- {
- printf("no ds18b20 exit\r\n");//初始化DS18B20,不初始化就等待這里?
- delay_ms(500);
- break;
- }
- DS18B20_ReadId(ucDs18b20Id); //讀取18b20的ID
- //LCD_write_cmd(0x0f);//寫命令
- for(i = 0;i < 8;i ++)
- {
- printf("DS18B20[%d] ID:%d \r\n ",i,ucDs18b20Id[i]); //讀取18b20的ID
- }
-
- while(AT24CXX_Check())//檢測不到24c02
- {
- printf("檢測不到24cXX\r\n") ;
- delay_ms(1000);
- break;
- }
-
- pid.set=AT24CXX_ReadOneByte_minus(0);//設定溫度數據讀取,在AT24CXX指定地址讀出一個數據
- T_mode=AT24CXX_ReadOneByte(4);//模式數據讀取,在AT24CXX指定地址讀出一個數據
-
- while(1)
- {
- /************************溫度設定*****************************************/
-
- if( KEY_Scan(0,KEY1)){pid.set++;AT24CXX_WriteOneByte_minus(0,pid.set);/*在AT24CXX指定地址寫入一個數據*/}
- if( pid.set>125)pid.set=125;
-
- if( KEY_Scan(0,KEY2)){T_mode=!T_mode;AT24CXX_WriteOneByte(4,T_mode);/*在AT24CXX指定地址寫入一個數據*/}//制冷制熱模式切換
-
- if( KEY_Scan(0,KEY3)){pid.set--;AT24CXX_WriteOneByte_minus(0,pid.set);/*在AT24CXX指定地址寫入一個數據*/}
- if( pid.set<-55)pid.set=-55;
- /********************pwm輸出**********************************************/
-
- pid_calc() ;//增量式PID調節函數
-
- /*********************制冷制熱模式顯示****************************/
- LCD_set_xy(16,1);//寫位置
- if(T_mode==1)//制冷
- {
- LCD_write_data('L'); //寫數據
- cle_pwm1=1;
-
- }
- else//制熱
- {
- LCD_write_data('H'); //寫數據
- cle_pwm2=1;
- }
-
- if(cle_pwm1&&cle_pwm2)
- {
- LCD_set_xy(5,1);//寫位置
- LCD_write_data(' '); //寫數據
- LCD_write_data('0'); //寫數據
- LCD_write_data('0'); //寫數據
- LCD_write_data('0'); //寫數據
- LCD_write_data('0'); //寫數據
- cle_pwm1=0;
- cle_pwm2=0;
- }
- /*********************pwm輸出顯示在lcd1602上****************************/
-
- //if(pid.currpwm<0)//制冷
- if(T_mode==1)//制冷
- {
- pwmval23=-pid.currpwm;
- memset(Data_Partition,0x30,sizeof(Data_Partition));//初始化數組
- conversion(pwmval23);//將數據拆分方便寫入lcd1602
- LCD_set_xy(5,1);//寫位置
- LCD_write_data('-'); //寫數據
- LCD_write_data(Data_Partition[3]); //寫數據
- LCD_write_data(Data_Partition[2]); //寫數據
- LCD_write_data(Data_Partition[1]); //寫數據
- LCD_write_data(Data_Partition[0]); //寫數據
-
- }
-
- //else if(pid.currpwm>0)//制熱
- else if(T_mode==0)//制冷
- {
- pwmval24=pid.currpwm;
- memset(Data_Partition,0x30,sizeof(Data_Partition));//初始化數組0x30 LCD的字符0
- conversion(pwmval24);//將數據拆分方便寫入lcd1602
- LCD_set_xy(5,1);//寫位置
- LCD_write_data('+'); //寫數據
- LCD_write_data(Data_Partition[3]); //寫數據
- LCD_write_data(Data_Partition[2]); //寫數據
- LCD_write_data(Data_Partition[1]); //寫數據
- LCD_write_data(Data_Partition[0]); //寫數據
-
- }
-
- /*****************設定溫度顯示在lcd1602上********************************/
-
- if(pid.set>=0) //lcd1602顯示設定溫度
- {
- b=Data_Line(pid.set);//獲取顯示數據位數
- conversion(pid.set);//將數據拆分方便寫入lcd1602
-
- LCD_set_xy(13,2);//寫位置
- LCD_write_data(' '); //清除“-” 號
-
- LCD_set_xy(14,2);//寫位置
- for(a=0;a<b+1;a++) //清空顯示數據
- {
- LCD_write_data(' '); //寫數據
- }
-
- LCD_set_xy(14,2);//寫位置
- for(a=0;a<b;a++) //整數部分顯示,不限長度
- {
- LCD_write_data(Data_Partition[b-a-1]); //寫數據
- }
- }
-
- /****************************************************************/
- else if(pid.set<0) //lcd1602顯示設定溫度
- {
- b=Data_Line(-pid.set);//獲取顯示數據位數
- conversion(-pid.set);//將數據拆分方便寫入lcd1602
-
- LCD_set_xy(13,2);//寫位置
- LCD_write_data('-'); //顯示“-” 號
-
- LCD_set_xy(14,2);//寫位置
- for(a=0;a<b+1;a++) //清空顯示數據
- {
- LCD_write_data(' '); //寫數據
- }
-
- LCD_set_xy(14,2);//寫位置
- for(a=0;a<b;a++) //整數部分顯示,不限長度
- {
- LCD_write_data(Data_Partition[b-a-1]); //寫數據
- }
-
- }
-
- /**************************溫度顯示在lcd1602*****************************************/
-
- pid.curr=DS18B20_GetTemp_MatchRom ( ucDs18b20Id ); //讀取18b20溫度數據
- if(pid.curr>=0) //lcd1602顯示溫度
- {
-
- b=Data_Line(pid.curr*100);//獲取顯示數據位數
- conversion(pid.curr*100);//將數據拆分方便寫入lcd1602
- // LCD_set_xy(6,2);//寫位置
- // for(a=0;a<b+2;a++) //清空顯示數據
- // {
- // LCD_write_data(' '); //寫數據
- // }
-
- LCD_set_xy(6,2);//寫位置
- for(a=0;a<b-2;a++) //整數部分顯示,不限長度
- {
- LCD_write_data(Data_Partition[b-a-1]); //寫數據
- }
- if(pid.curr<1)
- {
- LCD_write_data('0'); //寫數據
- }
- LCD_write_data('.'); //寫數據
-
- for(a=2;a>0;a--) //小數部分顯示
- {
- LCD_write_data(Data_Partition[a-1]); //寫數據
- }
- }
- /******************************************************************************/
- else if(pid.curr<0) //lcd1602顯示溫度
- {
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
代碼工程51hei附件下載:
PID控制-STM32F103C8T6 控溫.7z
(210.66 KB, 下載次數: 217)
2021-8-28 15:40 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|