ESP32 DHT11 / DHT22 Web服務器–使用Arduino IDE的溫度和溼度
在本項目中,您將學習如何使用DHT11或DHT22來構建異步ESP32 Web服務器,該服務器使用Arduino IDE顯示溫度和溼度。
我們將構建的網絡服務器無需刷新網頁即可自動更新讀數。
通過這個項目,您將學到:
· 如何從DHT傳感器讀取溫度和溼度;
· 使用ESPAsyncWebServer庫構建異步Web服務器;
· 自動更新傳感器讀數,而無需刷新網頁。
異步Web服務器
為了構建Web服務器,我們將使用ESPAsyncWebServer庫,該提供了一種構建異步Web服務器的簡便方法。如庫GitHub頁面中所述,構建異步Web服務器具有多個優點,例如:
· "同時處理多個連接";
· "當您發送響應時,當服務器負責在後臺發送響應時,您將立即準備處理其他連接";
· "用於處理模板的簡單模板處理引擎";
· 以及更多。
所需部件
要完成本教程,您需要以下部分:
原理圖
進入Web服務器之前,您需要按照以下示意圖所示將DHT11或DHT22傳感器連接到ESP32。
在這種情況下,我們將數據引腳連接到GPIO 27,但是您可以將其連接到任何其他數字引腳。您可以將此示意圖用於DHT11和DHT22傳感器。
(此原理圖使用帶有36個GPIO的ESP32 DEVKIT V1模塊版本–如果您使用的是其他型號,請檢查所用電路板的引腳排列。)
注意:如果您使用的模塊帶有DHT傳感器,則通常只有三個引腳。引腳上應標有標籤,以便您知道如何進行接線。此外,這些模塊中的許多模塊已經帶有內部上拉電阻,因此您無需在電路中增加一個。
安裝庫
您需要為此項目安裝幾個庫:
· DHT和Adafruit的統一傳感器驅動器庫讀取DHT傳感器數據。
· ESPAsyncWebServer和Async TCP庫可構建異步Web服務器。
按照以下說明安裝這些庫:
安裝DHT傳感器庫
要使用Arduino IDE讀取DHT傳感器,您需要安裝DHT傳感器庫 。請按照以下步驟安裝庫。
1. 下載DHT-sensor-library-master .zip文件
2. 解壓縮.zip文件夾,您應該獲得 DHT-sensor-library-master 文件夾
3. 重命名您的文件夾 到DHT_sensor
4. 將DHT_sensor 文件夾移至Arduino IDE安裝庫文件夾
5. 最後,重新打開您的Arduino IDE
安裝Adafruit統一傳感器驅動程序
您還需要安裝Adafruit統一傳感器驅動程序庫才能使用DHT傳感器。請按照以下步驟安裝庫。
1. 下載 Adafruit_sensor-master.zip文件
2. 解壓縮.zip文件夾,您應該獲得 Adafruit_sensor-master 文件夾
3. 重命名您的文件夾 到 Adafruit_sensor
4. 將Adafruit_sensor文件夾移至Arduino IDE安裝庫文件夾
5. 最後,重新打開您的Arduino IDE
安裝ESPAsyncWebServer庫
請按照以下步驟安裝 ESPAsyncWebServer庫:
1. 下載ESPAsyncWebServer-master.zip文件
2. 解壓縮.zip文件夾,您應該得到ESPAsyncWebServer-master文件夾
3. 重命名您的文件夾 到ESPAsyncWebServer
4. 將ESPAsyncWebServer 文件夾移至Arduino IDE安裝庫文件夾
為ESP32安裝異步TCP庫
該 ESPAsyncWebServer庫需要 AsyncTCP庫才能工作。請按照以下步驟安裝該庫:
1. 下載AsyncTCP-master.zip文件
2. 解壓縮.zip文件夾,您應該獲得AsyncTCP-master文件夾
3. 重命名您的文件夾 到AsyncTCP
4. 將AsyncTCP文件夾移至Arduino IDE安裝庫文件夾
5. 最後,重新打開您的Arduino IDE
程序代碼
我們將使用Arduino IDE對ESP32進行編程,因此在繼續之前,請確保已安裝ESP32附加組件:
打開您的Arduino IDE並複製以下代碼。
/*********
Rui Santos
Complete project details at https://randomnerdtutorials.com
*********/
// Import required libraries
#include "WiFi.h"
#include "ESPAsyncWebServer.h"
#include <adafruit>
#include <dht.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
#define DHTPIN 27 // Digital pin connected to the DHT sensor
// Uncomment the type of sensor in use:
//#define DHTTYPE DHT11 // DHT 11
#define DHTTYPE DHT22 // DHT 22 (AM2302)
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
DHT dht(DHTPIN, DHTTYPE);
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
String readDHTTemperature() {
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
//float t = dht.readTemperature(true);
// Check if any reads failed and exit early (to try again).
if (isnan(t)) {
Serial.println("Failed to read from DHT sensor!");
return "--";
}
else {
Serial.println(t);
return String(t);
}
}
String readDHTHumidity() {
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h = dht.readHumidity();
if (isnan(h)) {
Serial.println("Failed to read from DHT sensor!");
return "--";
}
else {
Serial.println(h);
return String(h);
}
}
const char index_html[] PROGMEM = R"rawliteral(
<link>
<style>
html {
font-family: Arial;
display: inline-block;
margin: 0px auto;
text-align: center;
}
h2 { font-size: 3.0rem; }
p { font-size: 3.0rem; }
.units { font-size: 1.2rem; }
.dht-labels{
font-size: 1.5rem;
vertical-align:middle;
padding-bottom: 15px;
}
ESP32 DHT Server
Temperature
%TEMPERATURE%
°C
Humidity
%HUMIDITY%
%
<script>
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("temperature").innerHTML = this.responseText;
}
};
xhttp.open("GET", "/temperature", true);
xhttp.send();
}, 10000 ) ;
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("humidity").innerHTML = this.responseText;
}
};
xhttp.open("GET", "/humidity", true);
xhttp.send();
}, 10000 ) ;
)rawliteral";
// Replaces placeholder with DHT values
String processor(const String& var){
//Serial.println(var);
if(var == "TEMPERATURE"){
return readDHTTemperature();
}
else if(var == "HUMIDITY"){
return readDHTHumidity();
}
return String();
}
void setup(){
// Serial port for debugging purposes
Serial.begin(115200);
dht.begin();
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
// Print ESP32 Local IP Address
Serial.println(WiFi.localIP());
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", readDHTTemperature().c_str());
});
server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", readDHTHumidity().c_str());
});
// Start server
server.begin();
}
void loop(){
}
將WIFI用戶名和密碼插入以下變量中,該代碼將立即生效。
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
代碼如何工作
在下面的段落中,我們將解釋代碼的工作方式。
導入庫
首先,導入所需的庫。需要WiFi,ESPAsyncWebServer和ESPAsyncTCP來構建Web服務器。Adafruit_Sensor和DHT是從DHT11或DHT22傳感器來讀取數據。
#include "WiFi.h"
#include "ESPAsyncWebServer.h"
#include <espasynctcp.h>
#include <adafruit>
#include <dht.h>
設置您的WIFI網絡
在以下變量中插入您的用戶名和密碼,以便ESP32可以連接到您的本地WIFI網絡。
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
變量定義
定義DHT數據引腳連接的GPIO。在這種情況下,它已連接到GPIO 27。
#define DHTPIN 27 // Digital pin connected to the DHT sensor
然後,選擇您正在使用的DHT傳感器類型。在我們的示例中,我們使用的是DHT22。如果您使用的是其他類型,則只需要取消註釋傳感器並註釋所有其他傳感器即可。
#define DHTTYPE DHT22 // DHT 22 (AM2302)
使用我們之前定義的類型和引腳實例化DHT對象。
DHT dht(DHTPIN, DHTTYPE);
在端口80上創建一個AsyncWebServer對象。
AsyncWebServer server(80);
讀取溫度和溼度函數
我們創建了兩個函數:一個讀取溫度(readDHTTemperature()),另一個讀取溼度(readDHTHumidity())。
String readDHTTemperature() {
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
//float t = dht.readTemperature(true);
// Check if any reads failed and exit early (to try again).
if (isnan(t)) {
Serial.println("Failed to read from DHT sensor!");
return "--";
}
else {
Serial.println(t);
return String(t);
}
}
獲取傳感器讀數就像在dht對象上使用readTemperature()和readHumidity()方法一樣簡單。
float t = dht.readTemperature();
float h = dht.readHumidity();
如果傳感器無法獲得讀數,我們還有一個條件返回兩個破折號(–)。
if (isnan(t)) {
Serial.println("Failed to read from DHT sensor!");
return "--";
}
讀數以字符串類型返回。要將float轉換為字符串,請使用String()函數。
return String(t);
默認情況下,我們以攝氏度為單位讀取溫度。要獲取以華氏度為單位的溫度,請以攝氏度為單位註釋溫度,並以華氏度為註釋溫度,以便您具有以下條件:
//float t = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
float t = dht.readTemperature(true);
建立網頁
進入Web服務器頁面。
如上圖所示,該網頁顯示一個標題和兩個段落。有一段顯示溫度,另一段顯示溼度。還有兩個圖標可以美化我們的頁面。
讓我們看看如何創建此網頁。
所有包含樣式的HTML文本都存儲在index_html變量中。現在,我們將遍歷HTML文本,並查看每個部分的作用。
以下標記使您的網頁在任何瀏覽器中都能響應。
所述需要標籤來從網站fontawesome加載的圖標。
<link>
風格樣式
在
基本上,我們將HTML頁面設置為顯示Arial字體的文本,該文本以不帶邊距的塊顯示,並居中對齊。
html {
font-family: Arial;
display: inline-block;
margin: 0px auto;
text-align: center;
}
我們為讀數的標題(h2),段落(p)和單位(.units)設置字體大小。
h2 { font-size: 3.0rem; }
p { font-size: 3.0rem; }
.units { font-size: 1.2rem; }
讀數的標籤樣式如下所示:
dht-labels{
font-size: 1.5rem;
vertical-align:middle;
padding-bottom: 15px;
}
先前的所有標記應位於
和 head>標記之間。這些標記用於包含用戶不直接可見的內容,例如,<link>標記和樣式。HTML主體
在
body>標記內是我們添加網頁內容的位置。該
h2>標籤標題添加到網頁。在這種情況下," ESP32 DHT服務器"文本,但是您可以添加任何其他文本。
ESP32 DHT Server
然後,有兩個段落。一個顯示溫度,另一個顯示溼度。段落由
和 p>標記分隔。溫度的段落如下:
Temperature
%TEMPERATURE%
°C
溼度的段落在以下摘要中:
Humidity
%HUMIDITY%
%
所述的標籤顯示fontawesome圖標。
如何顯示圖標
要選擇圖標,請訪問。
搜索您要查找的圖標。例如,"溫度計"。
單擊所需的圖標。然後,您只需要複製提供的HTML文本。
要選擇顏色,您只需要通過十六進制傳遞顏色的樣式參數,如下所示:
繼續HTML文本…
下一行在網頁中寫入"溫度"一詞。
Temperature
%符號之間的TEMPERATURE文本是溫度值的佔位符。
%TEMPERATURE%
這意味著此%TEMPERATURE%文本就像一個變量,將被DHT傳感器的實際溫度值代替。HTML文本上的佔位符應位於%符號之間。
最後,我們添加度數符號。
°C
該 < / SUP>標籤使文本標。
對於溼度段,我們使用相同的方法,但是使用不同的圖標和%HUMIDITY%佔位符。
Humidity
%HUMIDITY%
%
自動更新
最後,我們的網頁中有一些JavaScript代碼,每10秒自動更新一次溫度和溼度。
HTML文本中的腳本應位於<script> </>
要更新背景溫度,我們有一個setInterval()函數,該函數每10秒運行一次。
基本上,它在/ temperature URL中發出請求以獲取最新的溫度讀數。
xhttp.open("GET", "/temperature", true);
xhttp.send();
}, 10000 ) ;
收到該值時,它將更新id為temperature的HTML元素。
if (this.readyState == 4 && this.status == 200) {
document.getElementById("temperature").innerHTML = this.responseText;
}
總而言之,上一節負責異步更新溫度。對溼度讀數重複相同的過程。
重要提示:由於DHT傳感器獲取讀數的速度非常慢,如果您計劃同時將多個客戶端連接到ESP32,建議您增加請求間隔或刪除自動更新。
處理器
現在,我們需要創建processor()函數,該函數將用實際的溫度和溼度值替換HTML文本中的佔位符。
String processor(const String& var){
//Serial.println(var);
if(var == "TEMPERATURE"){
return readDHTTemperature();
}
else if(var == "HUMIDITY"){
return readDHTHumidity();
}
return String();
}
當請求網頁時,我們檢查HTML是否具有任何佔位符。如果找到%TEMPERATURE%佔位符,則通過調用先前創建的readDHTTemperature()函數來返回溫度。
if(var == "TEMPERATURE"){
return readDHTTemperature();
}
如果佔位符為%HUMIDITY%,則返回溼度值。
else if(var == "HUMIDITY"){
return readDHTHumidity();
}
設定()
在setup()中,初始化串口監視器以進行調試。
Serial.begin(115200);
初始化DHT傳感器。
dht.begin();
連接到您的局域網並打印ESP32 IP地址。
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
最後,添加以下代碼行以處理Web服務器。
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", readDHTTemperature().c_str());
});
server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", readDHTHumidity().c_str());
});
當我們在根URL上發出請求時,我們將發送存儲在index_html變量中的HTML文本。我們還需要傳遞處理器函數,該函數將用正確的值替換所有佔位符。
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
我們需要添加兩個其他處理程序來更新溫度和溼度讀數。當我們在/ temperature URL 上收到請求時,我們只需要發送更新的溫度值。它是純文本,應該以char形式發送,因此我們使用c_str()方法。
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", readDHTTemperature().c_str());
});
對溼度重複相同的過程。
server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", readDHTHumidity().c_str());
});
最後,我們可以啟動服務器。
server.begin();
因為這是一個異步Web服務器,所以我們不需要在loop()中編寫任何內容。
void loop(){
}
以上就是代碼的工作原理。
上載驗證程序
現在,將代碼上傳到ESP32。確保選擇了正確的板和COM端口。
上傳後,以115200的波特率打開串口監視器。按ESP32復位按鈕。ESP32 IP地址應在串口監視器中打印。
Web服務器演示
打開瀏覽器,輸入ESP32 IP地址。您的Web服務器應顯示最新的傳感器讀數。
請注意,溫度和溼度讀數會自動更新,而無需刷新網頁。
在本教程中,我們向您展示瞭如何使用ESP32構建異步Web服務器以顯示來自DHT11或DHT22傳感器的傳感器讀數以及如何自動更新讀數。
閱讀更多 工控電子愛好者 的文章