DHT22 Web服務器

ESP32 DHT11 / DHT22 Web服務器–使用Arduino IDE的溫度和溼度

在本項目中,您將學習如何使用DHT11或DHT22來構建異步ESP32 Web服務器,該服務器使用Arduino IDE顯示溫度和溼度。


我們將構建的網絡服務器無需刷新網頁即可自動更新讀數。

通過這個項目,您將學到:

· 如何從DHT傳感器讀取溫度和溼度;

· 使用ESPAsyncWebServer庫構建異步Web服務器;

· 自動更新傳感器讀數,而無需刷新網頁。


異步Web服務器

為了構建Web服務器,我們將使用ESPAsyncWebServer庫,該提供了一種構建異步Web服務器的簡便方法。如庫GitHub頁面中所述,構建異步Web服務器具有多個優點,例如:

· "同時處理多個連接";

· "當您發送響應時,當服務器負責在後臺發送響應時,您將立即準備處理其他連接";

· "用於處理模板的簡單模板處理引擎";

· 以及更多。

所需部件

ESP32 DHT11 / DHT22 Web服務器

要完成本教程,您需要以下部分:

  • ESP32開發板
  • DHT22 或 DHT11 溫溼度傳感器
  • 4.7k歐姆電阻
  • 麵包板
  • 跳線

  • 原理圖

    進入Web服務器之前,您需要按照以下示意圖所示將DHT11或DHT22傳感器連接到ESP32。

    在這種情況下,我們將數據引腳連接到GPIO 27,但是您可以將其連接到任何其他數字引腳。您可以將此示意圖用於DHT11和DHT22傳感器。


    ESP32 DHT11 / DHT22 Web服務器


    (此原理圖使用帶有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服務器頁面。

    ESP32 DHT11 / DHT22 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圖標。

    如何顯示圖標

    要選擇圖標,請訪問。

    ESP32 DHT11 / DHT22 Web服務器

    搜索您要查找的圖標。例如,"溫度計"。

    ESP32 DHT11 / DHT22 Web服務器

    單擊所需的圖標。然後,您只需要複製提供的HTML文本。

    ESP32 DHT11 / DHT22 Web服務器

    要選擇顏色,您只需要通過十六進制傳遞顏色的樣式參數,如下所示:

    繼續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地址應在串口監視器中打印。

    ESP32 DHT11 / DHT22 Web服務器

    Web服務器演示

    打開瀏覽器,輸入ESP32 IP地址。您的Web服務器應顯示最新的傳感器讀數。

    請注意,溫度和溼度讀數會自動更新,而無需刷新網頁。

    ESP32 DHT11 / DHT22 Web服務器

    在本教程中,我們向您展示瞭如何使用ESP32構建異步Web服務器以顯示來自DHT11或DHT22傳感器的傳感器讀數以及如何自動更新讀數。


    分享到:


    相關文章: