51單片機檢測水箱內溫度,ph值;
使用pid算法控制溫度到設置值;
普通控制ph值到設定值
溫度低,啟動加熱;PH值過高,啟動進水;PH值過低,啟動進料。
水位過高,啟動放水。
電路原理圖如下:
51hei.png (47.99 KB, 下載次數: 43)
下載附件
2022-12-5 03:32 上傳
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.gif (100.79 KB, 下載次數: 41)
下載附件
2022-12-5 03:31 上傳
程序流程圖
流程圖.jpg (52.21 KB, 下載次數: 43)
下載附件
2022-12-5 03:34 上傳
1.png (86.21 KB, 下載次數: 42)
下載附件
2022-12-5 03:34 上傳
2.png (160.03 KB, 下載次數: 41)
下載附件
2022-12-5 03:34 上傳
3.png (158.14 KB, 下載次數: 45)
下載附件
2022-12-5 03:34 上傳
4.png (158.05 KB, 下載次數: 38)
下載附件
2022-12-5 03:34 上傳
5.png (158.04 KB, 下載次數: 38)
下載附件
2022-12-5 03:34 上傳
元件清單:
元件 型號 數量
單片機 AT89C51 1
電容 10uf 1
電容 30pf 2
晶振 12MHZ 1
電阻 10k 1
按鈕 7
溫度傳感器 DS18B20 1
模數芯片 ADC0832 1
電位器 1k 2
電阻 1k 4
三極管 PNP 4
繼電器 5V 4
顯示器 LCD1602 1
排阻 10k 1
單片機源程序如下:
- #include "reg51.h"
- #include "lcd1602.h"
- #include "Ds18b20.h"
- #include "ADC0832.h"
- #include"pid_pwm.h"
- #define uchar unsigned char
- #define uint unsigned int
- sbit k1=P3^2;//按鈕
- sbit k2=P3^3;
- sbit k3=P3^4;
- sbit k4=P3^5;
- sbit k5=P3^6;
- sbit k6=P3^7;
- sbit out1=P2^4;//輸出控制
- sbit out2=P2^5;
- sbit out3=P2^6;
- sbit out4=P2^7;
- uchar time=0,mode=0;//系統變量
- uchar wendu=0,ph=0,water=0;//溫度,pH值,水位
- uchar lim1=25,lim2=7,lim3=100;//閥值
- uchar disp1[]="T:000 P:00 H:000";
- uchar disp2[]=" 000 00 000";
- uchar pwm=0;
- //主函數
- void main()
- {
- uchar i=0;
- init_1602();
- TMOD|=0X01;
- TH0=0X3C;
- TL0=0XB0;
- ET0=1;//打開定時器0中斷允許
- EA=1;//打開總中斷
- TR0=1;//打開定時器
- while(1)
- {
- //PWM輸出
- if(i<99)
- i++;
- else
- i=0;
- if(i<pwm)
- out4=0;
- else
- out4=1;
- //按鍵檢測
- if(!k1)
- {
- if(lim1<120)
- lim1++;
- while(!k1);
- }
- if(!k2)
- {
- if(lim1>0)
- lim1--;
- while(!k2);
- }
- if(!k3)
- {
- if(lim2<14)
- lim2++;
- while(!k3);
- }
- if(!k4)
- {
- if(lim2>0)
- lim2--;
- while(!k4);
- }
- if(!k5)
- {
- if(lim3<127)
- lim3++;
- while(!k5);
- }
- if(!k6)
- {
- if(lim3>0)
- lim3--;
- while(!k6);
- }
- }
- }
- //定時器中斷
- void Timer0() interrupt 1
- {
- uint i=0;
- if(time<10)//0.5s
- time++;
- else
- {
- time=0;
- Ds18b20ReadTemp();//測溫
- wendu=ds18b20_temp;
- ph=ADC(1);//PH
- i=ph;
- ph=i*14/127;
- water=ADC(2);//水位
- //顯示
- disp1[2]=wendu/100+0x30;
- disp1[3]=wendu%100/10+0x30;
- disp1[4]=wendu%10+0x30;
- disp1[8]=ph/10+0x30;
- disp1[9]=ph%10+0x30;
- disp1[13]=water/100+0x30;
- disp1[14]=water%100/10+0x30;
- disp1[15]=water%10+0x30;
- write_string(1,0,disp1);
- disp2[2]=lim1/100+0x30;
- disp2[3]=lim1%100/10+0x30;
- disp2[4]=lim1%10+0x30;
- disp2[8]=lim2/10+0x30;
- disp2[9]=lim2%10+0x30;
- disp2[13]=lim3/100+0x30;
- disp2[14]=lim3%100/10+0x30;
- disp2[15]=lim3%10+0x30;
- write_string(2,0,disp2);
- //PID控制
- pwm=PID(lim1,wendu);
- //PH值控制
- if(ph>lim2)
- out1=0;
- else
- out1=1;
- if(ph<lim2)
- out3=0;
- else
- out3=1;
- //水位控制
- if(water>lim3)
- out2=0;
- else
- out2=1;
- }
- TH0=0X3C;
- TL0=0XB0;
- }
復制代碼- #include"pid_pwm.h"
- uchar P_dat=1,I_dat=1,D_dat=1;//PID參數
- uint pid_dat[]={0,0,0,0,0}; //臨時數據
- //PID計算,返回占空比
- uchar PID(uint mub,uint dat)//調整目標+測量數據
- {
- uchar i=0;
- uint j=0,sum=0,k=0;
- //存儲數據
- for(i=0;i<4;i++)
- pid_dat[i]=pid_dat[i+1];
- pid_dat[4]=dat;
- //P調節
- j=0;
- if(dat<mub)
- {
- j=j+(mub-dat)*P_dat;
- if(j>100)
- j=100;
- }
- else
- {
- k=(dat-mub)*P_dat;
- if(j>k)
- j=j-k;
- }
- //I調節
- sum=0;
- for(i=0;i<5;i++)
- sum+=pid_dat[i];
- sum=sum/5;
- if(sum>mub)//減小
- {
- k=(sum-mub)*I_dat;
- if(j>k)
- j=j-k;
- }
- else //增加
- {
- k=(mub-sum)*I_dat;
- j+=k;
- if(j>100)
- j=100;
- }
- //D調節
- if(dat>pid_dat[3])//減小
- {
- k=(dat-pid_dat[3])*D_dat;
- if(j>k)
- j=j-k;
- }
- else //增加
- {
- k=(pid_dat[3]-dat)*D_dat;
- j+=k;
- if(j>100)
- j=100;
- }
- return j;
- }
復制代碼
51hei.png (9.85 KB, 下載次數: 42)
下載附件
2022-12-5 03:35 上傳
Keil代碼與Proteus仿真下載:
51水箱水質溫度檢測系統.7z
(911.22 KB, 下載次數: 102)
2022-12-5 03:36 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|