基于 ESP01 主板的温湿度监控开发

引言

在物联网应用中,温湿度监控是一个常见且重要的需求。ESP01 作为一款低成本、低功耗的 Wi-Fi 模块,为实现温湿度监控提供了一个便捷的解决方案。本文将详细介绍如何使用 ESP01 主板进行温湿度监控开发,包括硬件连接、代码实现和功能解析。

硬件准备

  • ESP01 主板:核心控制模块,负责数据采集和网络通信。
  • DHT 温湿度传感器:用于测量环境的温度和湿度。
  • 杜邦线:用于连接 ESP01 和 DHT 传感器。

将 DHT 传感器的 VCC 引脚连接到 ESP01 的 3.3V 引脚,GND 引脚连接到 GND,数据引脚连接到 ESP01 的指定引脚(代码中为 DHTPIN)。

代码实现

引入必要的库

1
2
3
4
5
6
7
8
9
#include <ESP8266WiFi.h> 
#include <WiFiUdp.h> 
#include <NTPClient.h> 
#include <PubSubClient.h> 
#include <ESP8266WebServer.h> 
#include <ArduinoJson.h> 
#include <DHT.h> 
#include "app_config.h" 
#include "wifi_config.h" 

这些库分别用于处理 Wi-Fi 连接、NTP 时间同步、MQTT 通信、Web 服务器、JSON 数据处理和 DHT 传感器读取。

初始化相关对象

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// 创建一个UDP对象用于NTP客户端 
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, ntpserver, 8 * 3600, 60000); 

// 创建WiFi和MQTT客户端对象 
WiFiClient espClient; 
PubSubClient client(espClient); 
uint32_t delayMS; 
unsigned long globalPreviousMillis = millis(); 
unsigned long globalCurrentMillis = millis(); 

String readings; 

DHT dht(DHTPIN, DHTTYPE); 
ESP8266WebServer server(80); 

这里初始化了 NTP 客户端、WiFi 客户端、MQTT 客户端、DHT 传感器对象和 Web 服务器对象。

重连 MQTT 服务器

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void reconnect() {
  unsigned long previousMillis  = millis();
  unsigned long rebootMillis  = millis();
  while (!client.connected()) {
    unsigned long currentMillis  = millis();
    if (currentMillis - previousMillis >= 1500) {
      if (currentMillis - rebootMillis >= 5000) {
        Serial.println("exit to try.");
        break;
      }
      previousMillis = currentMillis;
    }
    Serial.print("Attempting MQTT connection...");
    // Generate a random client ID
    String clientId = "ESP32Client-";
    clientId += String(WiFi.macAddress());
    Serial.print(clientId.c_str());
    if (client.connect(clientId.c_str())) {
      Serial.println(" ... connected");
    } else {
      Serial.print(" ... failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 1 seconds");
      delay(1000);
    }
  }
}

该函数用于在 MQTT 连接断开时尝试重新连接,设置了重试时间和退出条件。

获取传感器数据并发布到 MQTT

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
String getReadingsSensor () {
  // 创建一个动态分配的JSON文档
  DynamicJsonDocument sensordoc(1024);
  JsonObject info = sensordoc.createNestedObject("info");
  timeClient.update();
  int epochTimel =timeClient.getEpochTime();

  info["board_type"] = boardType;
  info["ip"] = WiFi.localIP().toString();
  info["mac"] = WiFi.macAddress();
  info["utc"] = epochTimel;
  info["name"] = nodeName;

  JsonObject sensor = sensordoc.createNestedObject("sensor");
  JsonObject sensorTemp = sensor.createNestedObject("ths");

  sensorTemp["name"] = dhtName;
  float humidity = dht.readHumidity();
  float temperature = dht.readTemperature();
  float fahrenheit = dht.readTemperature(true);
  if (isnan(humidity) || isnan(temperature) || isnan(fahrenheit)) {
    Serial.println(F("Failed to read from DHT sensor!"));
  } else {
    float hif = dht.computeHeatIndex(fahrenheit, humidity);
    float hic = dht.computeHeatIndex(temperature, humidity, false);

    Serial.print(F("Humidity: "));
    Serial.print(humidity);
    Serial.print(F("%  Temperature: "));
    Serial.print(temperature);
    Serial.print(F("°C "));
    Serial.print(fahrenheit);
    Serial.print(F("°F  Heat index: "));
    Serial.print(hic);
    Serial.print(F("°C "));
    Serial.print(hif);
    Serial.println(F("°F"));
    sensorTemp["temperature"] = temperature;
    sensorTemp["humidity"] = humidity;
    sensorTemp["fahrenheit"] = fahrenheit;
  }
  serializeJson(sensordoc, readings);
  // 发布数据到MQTT主题
  client.publish("sensor/data", readings.c_str());
  return readings;
}

此函数读取 DHT 传感器的温湿度数据,将其封装成 JSON 格式,并通过 MQTT 发布到指定主题。

处理 API 请求

1
2
3
4
5
6
7
8
void handleAPI() {
  String result;
  result += "#Esp-01 API \n";
  String msg = getReadingsSensor();
  result += msg + "\n";
  server.sendHeader("Cache-Control", "no-cache");
  server.send(200, "application/json; charset=utf-8", result);
}

该函数处理 /api/sensor 的 HTTP GET 请求,返回传感器数据的 JSON 格式。

初始化设置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
void setup() {
  Serial.begin(115200);
  dht.begin();
  lastConnectTime = millis();
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  unsigned long previousMillis  = millis();
  unsigned long rebootMillis  = millis();
  while (WiFi.status() != WL_CONNECTED) {
    unsigned long currentMillis  = millis();
    if (currentMillis - previousMillis >= 15000) {
      if (currentMillis - rebootMillis >= 50000) {
        Serial.println("reboot now.");
        ESP.restart();
      }
      Serial.println("retry now.");
      WiFi.disconnect();
      WiFi.reconnect();
      previousMillis = currentMillis;
    }
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  server.on(F("/"), []() {
    server.send(200, "text/plain", "hello from esp32!");
  });

  delayMS = 15000;
  client.setServer(mqttServer, mqttPort);
  client.setKeepAlive(60); // 设置心跳间隔为60秒
  client.setBufferSize(2048);
  server.on("/api/sensor", HTTP_GET, handleAPI);
  server.begin();
  Serial.println("HTTP server started");
  globalPreviousMillis  = millis();
  globalCurrentMillis  = millis();
  getReadingsSensor();
}

setup 函数完成串口初始化、DHT 传感器初始化、Wi-Fi 连接、MQTT 服务器设置和 Web 服务器启动等操作。

主循环

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
void loop() {
  server.handleClient();
  WiFiStatusHandle();
  globalCurrentMillis  = millis();
  if (globalCurrentMillis - globalPreviousMillis >= delayMS) {
    if (!client.connected()) {
      reconnect();
    }
    client.loop();
    // 假设这是从传感器读取的数据  
    getReadingsSensor();
    // 发布数据到MQTT主题
    //client.publish("sensor/data", readings.c_str());
    Serial.println(client.state());
    Serial.println(client.getBufferSize());
    Serial.println(client.getWriteError());
    globalPreviousMillis = globalCurrentMillis;
  }
  delay(200);  //allow the cpu to switch to other tasks
}

loop 函数不断处理 Web 服务器请求,检查 Wi-Fi 状态,每隔一定时间读取传感器数据并发布到 MQTT 服务器。

功能解析

温湿度数据采集

通过 DHT 传感器读取环境的温度和湿度数据,并计算出华氏温度和热指数。

网络通信

  • Wi-Fi 连接:ESP01 连接到指定的 Wi-Fi 网络,获取 IP 地址。

  • MQTT 通信:将采集到的温湿度数据封装成 JSON 格式,通过 MQTT 协议发布到指定主题。

  • Web 服务器:提供一个简单的 Web 服务器,处理 /api/sensor 的 HTTP GET 请求,返回传感器数据。

错误处理和重连机制

在 Wi-Fi 连接失败或 MQTT 连接断开时,会尝试重新连接,并且设置了超时重启机制,确保系统的稳定性。

总结

通过以上步骤,我们成功使用 ESP01 主板实现了温湿度监控功能。该系统可以实时采集环境的温湿度数据,并通过 MQTT 协议将数据传输到服务器,同时提供了一个简单的 Web API 供外部访问。这个方案成本低、易于实现,适用于各种温湿度监控场景。