收藏和點贊,您的關(guān)注是我創(chuàng)作的動力
概要
??水資源一直以來都是人類最重要的財富之一,由于工農(nóng)業(yè)的發(fā)展人
們對水資源的污染變得越來越嚴重,保護水資源應勢在必行。在這個科學技術(shù)日新月異的時代,嵌入式技術(shù)和物聯(lián)網(wǎng)技術(shù)一直在發(fā)展未曾被淘汰便足以證明這些技術(shù)的優(yōu)秀,結(jié)合現(xiàn)在的時代背景對水質(zhì)檢測的需求,水質(zhì)檢測對世界各國家的發(fā)展以及人們的生活至關(guān)重要。本文在以上基礎(chǔ)上本文利用嵌入式技術(shù)和物聯(lián)網(wǎng)技術(shù)設(shè)計一款基于 STM32F103C8T6單片機實現(xiàn)水質(zhì)檢測的功能,單片機外接 E-201 系列的 PH 傳感器和TSW-30 渾濁度傳感器采集數(shù)據(jù)然后通過單片機計算具體水質(zhì)數(shù)據(jù),再將水質(zhì)數(shù)據(jù)顯示到 LCD1602 液晶顯示器上,并外接 ESP8266WIFI 模塊通過單片機將水質(zhì)數(shù)據(jù)實時傳輸?shù)绞謾C應用上顯示,該設(shè)計與傳統(tǒng)的水質(zhì)檢測相比有著采集效率高,實時性好,成本低等優(yōu)點。同時,水資檢測是保護水資源的重要手段之一,對人們的身體健康有著良好的保障,對國家的發(fā)展有著重要意義。
一、系統(tǒng)總體設(shè)計
1功能需求分析
本設(shè)計以單片機為基礎(chǔ)對水質(zhì)進行檢測,需要實現(xiàn)顯示功能、水質(zhì)數(shù)據(jù)采集功能、無線通信功能,實現(xiàn)一個自動采集水質(zhì)數(shù)據(jù)并顯示出來的系統(tǒng)。
顯示需求分析:
單片機較為常用的液晶顯示屏主流有 LCD1602 和 LCD12864,這兩款液晶顯示器區(qū)別不大,顯示內(nèi)容上 LCD12864 比 LCD1602 能夠呈現(xiàn)的信息更多,LCD12864能夠顯示中文,LCD1602 顯示數(shù)字和英文更為方便,后者比前者相對便宜,且本設(shè)計用于顯示大小對 LCD1602 已經(jīng)足夠,所以顯示方面選擇性價比更高的 LCD1602。
水質(zhì)傳感器需求分析:
水質(zhì)可以檢測的常見參數(shù)有 COD、氨氮、色度、渾濁度、PH 值等,但由于成本和技術(shù)上的問題,只能選取少量參數(shù)進行檢測。
(1)COD 是水中的還原物被氧化需要的量,是一種化學檢測方法,但一般用在工業(yè)級別的檢測上,且會因使用的氧化劑會導致結(jié)果有所區(qū)別,故不選取。
(2)氨氮是檢測由 NH3 和 NH4+ 在水中結(jié)合而成的化合物含量,這中化合物會導致水富營養(yǎng)化,這種檢測儀器較為昂貴,設(shè)計成本太高所以不適用于本設(shè)計。
(3)色度是天然水或者對水中的懸浮物進行處理,然后進行檢測其顏色的一種檢測方式,但由于檢測原理較為復雜,應用于單片機檢測上難度較大,故也不選用
(4)PH 是指水中氫離子濃度,這種檢測方式雖然也在工業(yè)上使用,且市面上的 PH 檢測儀器無法進行二次開發(fā),但卻有成熟的 PH 檢測模塊可以配合 ph 測量電極使用,價格便宜,使用起來簡單方便,可采用。
(5)渾濁度指水中懸浮物質(zhì)的含量,檢測原理是根據(jù)水對光線的穿透量的大小,雖然工業(yè)級的檢測儀器價格高昂,但可采用洗衣機、洗碗機所使用的渾濁度傳感器,這種傳感器價格低廉,適合用于開發(fā),可采用。
無線通信需求分析:
目前嵌入式使用比較多的無線通信技術(shù)有紅外遙控、藍牙、WIFI。紅外遙控技術(shù)需要端口對接,受障礙物影響較大,而且傳輸距離較短;而藍牙技術(shù)雖然沒有了障礙物的影響,能夠全方位地傳輸信息,但缺點是傳輸距離仍然較短,傳輸速率較慢;WIFI 相對以上兩者,沒有了那些缺點,傳輸距離和傳輸速率都有了明顯的提升,以上三種技術(shù)中顯然 WIFI是最適用的。
2原理圖設(shè)計
STM32 最小系統(tǒng)由 STM32 芯片、晶振電路和復位電路組成,如圖 3.5 所示。晶振電路的作用是為單片機提供合適的時鐘信號流,就像人的心臟提供心跳,單片機才能運行,電路中兩個電容是為了滿足諧振要求,要想晶振電路能夠工作正常,需要接上適當大小的電容。復位電路是上電復位電路,為低電平復位,電壓升高,讓系統(tǒng)恢復到初始狀態(tài)。具體原理圖如圖 3.9 所示。
圖3-4 STM32 最小系統(tǒng)
圖 3.7 為穩(wěn)壓電路,AMS1117 是一款穩(wěn)壓芯片,用于轉(zhuǎn)換電壓。由于 USB 供電通常為 5V,而 STM32 需要 3.3V 供電,所以需要通過穩(wěn)壓電路將 5V 轉(zhuǎn)換為 3.3V 給單片機提供電源,D3 二極管是肖特基二極管,它的主要作用是讓電流只能從一個方向通過,保障電路正常工作。
二、程序流程圖
本設(shè)計以 STM32 為核心,外接液晶顯示模塊、PH 傳感器、渾濁度傳感器、WIFI模塊實現(xiàn)檢測水質(zhì) PH 值和渾濁度,STM32 單片機通過 PH 傳感器以及渾濁度傳感器獲取電壓信號,然后單片機獲取信號再將具體數(shù)據(jù)計算結(jié)果,將結(jié)果通過程序顯示在 LCD1602,同時單片機利用 WIFI 模塊發(fā)送水質(zhì)的 PH 值和渾濁度數(shù)據(jù),手機應用獲取到具體數(shù)據(jù)并顯示出來,具體程序流程圖如圖 4.1。開始時需要時鐘初始化、IO 口初始化、串口初始化、液晶初始化等。其中獲取 PH 值和渾濁度參數(shù)是通過單片機的采集電壓而來的,然后算出實際數(shù)據(jù)
圖4-1 程序流程圖
圖4.1為液晶顯示的部分程序內(nèi)容,其中調(diào)用函數(shù) LCD_DisStr(0,0,“”)表示從第一行第一列開始顯示數(shù)據(jù),LCDW_Dat()顯示水質(zhì)數(shù)據(jù)的各位(個位、十位等)數(shù)據(jù)。
圖4-2 液晶顯示
STM32 單片機通過 WIFI 模塊發(fā)送數(shù)據(jù)方式如圖 4.3 所示,sendchar()為發(fā)送一段字符串,字符串中 S 表示發(fā)送起點,009 表示九個字節(jié)的數(shù)據(jù),后面跟著的即為發(fā)送的數(shù)據(jù),E 表示發(fā)送結(jié)束。
圖4-3WIFI 發(fā)送
仿真電路圖
如圖5.1所示。
圖5-1仿真電路圖
三、 主要代碼
主程序:
源代碼:
#include "sys.h"
#include "delay.h"
#include "gpio.h"
#include "OLED_I2C.h"
#include "ds18b20.h"
#include "usart1.h"
#include "esp8266.h"
#include "adc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STM32_RX1_BUF Usart1RecBuf
#define STM32_Rx1Counter RxCounter
#define STM32_RX1BUFF_SIZE USART1_RXBUFF_SIZE
#define Offset 0.00 //deviation compensate
#define RATIO 4.51/4.08
short temperature=0; //溫度
u8 tempSetVal=40; //溫度上限
u8 shuaxin = 0; //刷新標志
u8 setFlag = 0; //設(shè)置標志
float PH = 0.0;
u16 Ph_min = 300,Ph_max = 900; //PH下限上限
u16 Turbidity=0;
u16 TurSetMax=1000; //濁度上限
unsigned long int avgValue; //Store the average value of the sensor feedback
char display[16];
void Usart1RxBufClear(void) //清除串口接收緩存
{
memset(STM32_RX1_BUF, 0, STM32_RX1BUFF_SIZE);//清除緩存
STM32_Rx1Counter = 0;
}
void InitDisplay(void) //初始化顯示
{
unsigned char i=0;
OLED_ShowStr(0, 2, "PH:", 2,0);
for(i=0;i<2;i++)OLED_ShowCN(i*16,4,i+0,0);//顯示中文:溫度
for(i=0;i<2;i++)OLED_ShowCN(i*16,6,i+2,0);//顯示中文:濁度
OLED_ShowChar(32,4,':',2,0);
OLED_ShowChar(32,6,':',2,0);
}
void displaySetValue(void) //顯示設(shè)置的值
{
if(setFlag == 1 ||setFlag == 2)
{
sprintf(display,"%5.2f",(float)Ph_min/100);
OLED_ShowStr(40, 4,(u8 *)display, 2,setFlag+1-1);
sprintf(display,"%5.2f",(float)Ph_max/100);
OLED_ShowStr(40, 6,(u8 *)display, 2,setFlag+1-2);
}
if(setFlag == 3)
{
sprintf(display,"%02d",tempSetVal);
OLED_ShowStr(40, 4,(u8 *)display, 2,setFlag+1-3);
}
if(setFlag == 4)
{
sprintf(display,"%04d",TurSetMax);
OLED_ShowStr(40, 4,(u8 *)display, 2,setFlag+1-4);
}
}
void keyscan(void) //按鍵掃描
{
unsigned char i=0;
if(KEY1 == 0) //設(shè)置鍵
{
delay_ms(20);
if(KEY1 == 0)
{
while(KEY1 == 0);
BEEP=0;
setFlag ++;
if(setFlag == 1)
{
OLED_CLS(); //清屏
for(i=0;i<2;i++)OLED_ShowCN(i*16+32,0,i+8,0);//顯示中文:設(shè)置
OLED_ShowStr(62, 0, " PH", 2,0);
for(i=0;i<2;i++)OLED_ShowCN(i*16,4,i+4,0);//顯示中文:下限
for(i=0;i<2;i++)OLED_ShowCN(i*16,6,i+6,0);//顯示中文:上限
OLED_ShowChar(32,4,':',2,0);
OLED_ShowChar(32,6,':',2,0);
}
if(setFlag == 3)
{
for(i=0;i<2;i++)OLED_ShowCN(i*16+64,0,i+0,0);//顯示中文:溫度
OLED_ShowStr(56, 4, " ", 2,0);
OLED_ShowCentigrade(56, 4); //℃
OLED_ShowStr(0, 6, " ", 2,0);
}
if(setFlag == 4)
{
for(i=0;i<2;i++)OLED_ShowCN(i*16+64,0,i+2,0);//顯示中文:濁度
OLED_ShowStr(72, 4, "NTU", 2,0);
}
if(setFlag >= 5)
{
setFlag = 0;
OLED_CLS(); //清屏
InitDisplay();
}
displaySetValue();
}
}
if(KEY2 == 0) //加鍵
{
delay_ms(100);
if(KEY2 == 0)
{
if(setFlag == 1)
{
if(Ph_max-Ph_min > 10)Ph_min+=10;
}
if(setFlag == 2)
{
if(Ph_max < 1400)Ph_max+=10;
}
if(setFlag == 3)
{
if(tempSetVal<99)tempSetVal++;
}
if(setFlag == 4)
{
if(TurSetMax<3000)TurSetMax+=10;
}
displaySetValue(); //顯示沒有設(shè)置值
}
}
if(KEY3 == 0) //減鍵
{
delay_ms(100);
if(KEY3 == 0)
{
if(setFlag == 1)
{
if(Ph_min >= 10)Ph_min-=10;
}
if(setFlag == 2)
{
if(Ph_max-Ph_min > 10)Ph_max-=10;
}
if(setFlag == 3)
{
if(tempSetVal>0)tempSetVal--;
}
if(setFlag == 4)
{
if(TurSetMax>=10)TurSetMax-=10;
}
displaySetValue(); //顯示沒有設(shè)置值
}
}
}
void Get_PH(void) //獲取PH
{
u16 buf[10];//buffer for read analog
u8 i,j;
float phValue=0.0;
for(i=0;i<10;i++) //Get 10 sample value from the sensor for smooth the value
{
buf[i]=Get_Adc_Average(ADC_Channel_8,10);
}
for(i=0;i<9;i++) //sort the analog from small to large
{
for(j=i+1;j<10;j++)
{
if(buf[i]>buf[j])
{
int temp=buf[i];
buf[i]=buf[j];
buf[j]=temp;
}
}
}
avgValue=0;
for(i=2;i<8;i++) //take the average value of 6 center sample
avgValue+=buf[i];
phValue=((float)avgValue*5.0/4095/6)*RATIO; //convert the analog into millivolt
PH=(phValue*(-5.290))+23.053; //convert the millivolt into pH value
if(PH<0)PH=0;
if(PH>14.0)PH=14.0;
}
void Get_Turbidity(void) //獲取渾濁度
{
float T;
u16 adcx = 0;
adcx = Get_Adc_Average(ADC_Channel_9,20);//讀取AD值
T = adcx;
T = T*(3.3/4096)+1.72;
if(T < 2.5)
{
T = 3000;
}
else
{
T = (-1120.4*T*T+5742.3*T-4352.9); //Tul是AD值
}
if(T < 0)
{
T = 0;
}
Turbidity = (u16)T;
if(Turbidity > 3000)Turbidity = 3000;
}
void UsartSendData(void) //串口發(fā)送數(shù)據(jù)
{
char SEND_BUF[100];
char BUF[50];
memset(SEND_BUF,0,sizeof(SEND_BUF)); //清空緩沖區(qū)
sprintf(SEND_BUF,"PH:%5.2f\r\n",PH);
memset(BUF,0,sizeof(BUF)); //清空緩沖區(qū)
sprintf(BUF,"溫度:%d℃\r\n",temperature);
strcat(SEND_BUF,BUF);
memset(BUF,0,sizeof(BUF)); //清空緩沖區(qū)
sprintf(BUF,"濁度:%dNTU\r\n",Turbidity);
strcat(SEND_BUF,BUF);
strcat(SEND_BUF,"\r\n");
ESP8266_SendData((u8 *)SEND_BUF, strlen(SEND_BUF)); //ESP8266發(fā)送數(shù)據(jù)
}
int main(void)
{
u16 timeCount1 = 300;
u16 timeCount2 = 10;
u8 shanshuo=0;
delay_init(); //延時函數(shù)初始化
NVIC_Configuration(); //中斷優(yōu)先級配置
I2C_Configuration(); //IIC初始化
delay_ms(200);
Adc_Init(); //ADC初始化
OLED_Init(); //OLED液晶初始化
OLED_CLS(); //清屏
OLED_ShowStr(0, 2," Loading... ", 2,0);
ESP8266_Init();
OLED_CLS(); //清屏
InitDisplay();
KEY_GPIO_Init(); //按鍵引腳初始化
DS18B20_GPIO_Init();
DS18B20_Init(); //初始化顯示
uart1_Init(9600);
while(1)
{
keyscan(); //按鍵掃描
timeCount1 ++;
if(timeCount1 >= 300 && !setFlag) //延時一段時間讀取
{
timeCount1 = 0;
shanshuo=!shanshuo;
Get_PH() ; //獲取PH
/*超限的時候閃爍顯示*/
if(((PH*100)<=Ph_min || (PH*100)>=Ph_max) && shanshuo)
{
OLED_ShowStr(32, 2," ", 2,0);
}
else
{
sprintf(display,"%5.2f ",(float)PH);
OLED_ShowStr(32, 2,(u8 *)display, 2,0);
}
temperature = ReadTemperature();//讀取溫度
/*超限的時候閃爍顯示*/
if((temperature>=tempSetVal) && shanshuo)
{
OLED_ShowStr(40, 4," ", 2,0);
}
else
{
sprintf(display,"%02d",temperature);
OLED_ShowStr(40, 4,(u8 *)display, 2,0);
OLED_ShowCentigrade(56, 4); //℃
}
Get_Turbidity() ;
/*超限的時候閃爍顯示*/
if((Turbidity>=TurSetMax) && shanshuo)
{
OLED_ShowStr(40, 6," ", 2,0);
}
else
{
sprintf(display,"%dNTU ",Turbidity);
OLED_ShowStr(40, 6,(u8 *)display, 2,0);
}
if(((PH*100)<=Ph_min || (PH*100)>=Ph_max)||(temperature>=tempSetVal)||(Turbidity>=TurSetMax))BEEP= 1;else BEEP=0; //超限蜂鳴器報警
timeCount2 ++;
if(timeCount2 >= 3)
{
timeCount2 = 0;
UsartSendData(); //串口發(fā)送數(shù)據(jù)
}
}
delay_ms(1);
}
}
四、 內(nèi)容截圖
五、 文章目錄
目 錄文章來源:http://www.zghlxwxcb.cn/news/detail-760774.html
1 緒論………………………………………………………………………………1
1.1 研究背景…………………………………………………………………Y
1.2 國內(nèi)外研究現(xiàn)狀………………………………………………………………Y
1.3選題背景和研究內(nèi)容……………………………………………………………Y
1.4本章小結(jié)………………………………………………………………Y
2 方案論證……………………………………………………………………Y
2.1 功能需求分析…………………………………………………………………Y
2.2技術(shù)應用概況…………………………………………………………………Y
2.3本章小結(jié)…………………………………………………………………Y
3 硬件設(shè)計………………………………………………………………………Y
3.1 芯片選型及系統(tǒng)框架……………………………………………………………Y
3.2原理圖設(shè)計…………………………………………………………………Y
4 軟件開發(fā)………………………………………………………………………Y
4.1 開發(fā)軟件應用……………………………………………………………Y
4.2程序流程圖…………………………………………………………………Y
5 綜合測試………………………………………………………………………Y
5.1硬件測試……………………………………………………………Y
5.2功能測試…………………………………………………………………Y
6總結(jié)與展望………………………………………………………………………Y
致謝 …………………………………………………………………………………Y
參考文獻……………………………………………………………………………Y
附錄…………………………………………………………………………………Y文章來源地址http://www.zghlxwxcb.cn/news/detail-760774.html
到了這里,關(guān)于基于單片機的智能水質(zhì)監(jiān)測系統(tǒng)設(shè)計的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!