使用 Arduino ESP32 收集温湿度数据

힘센캥거루
2025년 7월 7일(수정됨)
1
85
arduino

今天,我们将使用 Arduino ESP32 制作一个用于测量并传输温湿度数据的 Wi-Fi 百叶箱。

这篇文章是基于在学校进行的 16+1 课程的稿件编写的。

1. 准备材料

准备工作很简单。

ESP32, DHT-22, 三根电线
使用 Arduino ESP32 收集温湿度数据-1

首先简单介绍一下 ESP32,它是一个嵌入了 Wi-Fi 模块的 Arduino。

但其尺寸比普通 Arduino 小得多。

2. ESP32 引脚图

使用 Arduino ESP32 收集温湿度数据-2

啊哈?引脚编号似乎有点奇怪?

虽然在前一篇文章中已经解释过,这是因为 Wi-Fi 模块的引入改变了引脚映射。

以下是 ESP32 Arduino 的引脚映射。

不过,似乎这个型号的 GPIO 引脚号和引脚名称基本一致。

我们打算使用下面引脚中的 安全的 D4 引脚 来运行 dht-22。

使用 Arduino ESP32 收集温湿度数据-4

Arduino D 引脚

GPIO 号码

注意事项

功能及说明

D0

GPIO0

strapping: 启动时需要 LOW 或 浮动

影响进入 flash 模式 ([randomnerdtutorials.com][1])

D1

GPIO1 (TX0)

注意 USB 串口冲突

上传·调试用 UART0 TX

D2

GPIO2

strapping: 启动时需要 LOW/浮动

板载 LED → 启动有影响

D3

GPIO3 (RX0)

注意 USB 串口冲突

UART0 RX,启动时 HIGH

D4

GPIO4

★ 安全

数字 I/O, ADC2_CH0, 可触摸

D5

GPIO5

strapping: 启动时需要 HIGH

启动中可输出 PWM

D6D11

GPIO6–11

绝对禁止使用

内部 SPI 闪存引脚

D12

GPIO12

strapping: 启动时需要 LOW

ADC2_CH5, 可触摸,启动有影响

D13

GPIO13

安全

ADC2_CH4, 可触摸

D14

GPIO14

启动时 PWM 输出,支持引导配置

ADC2_CH6, 可触摸

D15

GPIO15

strapping: 启动时需要 HIGH,PWM 输出

ADC2_CH3, 可触摸

D16

GPIO16

使用 Wrover 模块时注意 PSRAM

UART2 默认 TX/RX (17/16)

D17

GPIO17

Wrover 模块注意

UART2 默认 TX/RX (17/16)

D18, D19, D21–D23, D25–D27, D32–D33

安全

数字, PWM, I2C, SPI, ADC/DAC 可用

D34, D35, D36(VP), D39(VN)

34,35,36,39

输入专用,无上拉/下拉

ADC1 频道 (无其他功能)

3. DHT-11 vs DHT-22

购买 Arduino 时,通常包含的基本温湿度计是 DHT-11。

它是蓝色的,但使用时误差范围较大,约为 2 度。

下表总结了 DHT 和 DHT-22 的性能。

项目

DHT-11

DHT-22 (AM2302)

外形

使用 Arduino ESP32 收集温湿度数据-5使用 Arduino ESP32 收集温湿度数据-6

温度测量范围

0 ~ 50°C

-40 ~ +80°C

温度精度

±2°C

±0.5°C

湿度测量范围

20 ~ 80% RH

0 ~ 100% RH

湿度精度

±5% RH

±2~3% RH

测量分辨率

温度: 1°C, 湿度: 1% RH

温度: 0.1°C, 湿度: 0.1% RH

测量周期(采样间隔)

1秒以上

2秒以上

数据传输速度

低速

低速

尺寸

小型

稍大

价格

便宜

比 DHT-11 贵

使用电压

3 ~ 5V

3 ~ 5V

由于误差范围太大,无法信任数据,因此决定使用误差较小的 DHT-22。

如果想要更准确的温度,可以使用 PT-100 温度计,但似乎不需要做到这个程度。

4. 安装 CH340 驱动程序

使用 Arduino ESP32 收集温湿度数据-7

在上面的照片中可以看到红圈内有一个芯片。

这是中国制造的称为 CH340 的芯片,类似于计算机中的 CPU。

提供 CH340 芯片驱动程序的官方网站链接如下。

下载安装后无思考地点击“下一步”即可。

该文件包含以下所有芯片的驱动程序。

顺便提一下,MacBook 默认提供了该芯片组的驱动程序,因此不需要安装。

CH340G,CH340T,CH340C,CH340N, CH340K, CH340E,CH340B,CH341A,CH341F, CH341T,CH341B,CH341C,CH341U

5. Arduino IDE 电路板管理器设置

现在来设置 Arduino IDE 中的电路板管理器。

在 Arduino IDE 中进入 File > Preferences (基本设置)。

使用 Arduino ESP32 收集温湿度数据-8

在附加电路板管理 URL 中复制输入以下地址。

https://espressif.github.io/arduino-esp32/package_esp32_index.json
使用 Arduino ESP32 收集温湿度数据-9使用 Arduino ESP32 收集温湿度数据-10

然后在电路板管理器中搜索 ESP32,并找到由 Espressif Systems 提供的进行安装。

使用 Arduino ESP32 收集温湿度数据-11

将 Arduino 连接到 USB 端口后,端口会自动被识别。

现在选择对应端口的 Arduino 电路板即可。

使用 Arduino ESP32 收集温湿度数据-12

6. 连接 Wi-Fi

接下来上传一个简单的例子。

点击 文件 -> 示例 -> HttpClient -> BasicHttpsClient,会出现 Http 请求示例。

使用 Arduino ESP32 收集温湿度数据-13

只需更改这个示例中的 SSID 和 PASSWORD 部分即可。

void setup() {

 USE_SERIAL.begin(115200);

 USE_SERIAL.println();
 USE_SERIAL.println();
 USE_SERIAL.println();

 for (uint8_t t = 4; t > 0; t--) {
 USE_SERIAL.printf("[SETUP] WAIT %d...\n", t);
 USE_SERIAL.flush();
 delay(1000);
 }
// 在下方的 SSID 中输入 Wi-Fi 名称,PASSWORD 中输入密码
 wifiMulti.addAP("SSID", "PASSWORD");
}

如果上传失败,请调节上传速度。

在 工具 -> 上传速度 中更改为稍低一点的数值可以更稳定。

使用 Arduino ESP32 收集温湿度数据-14

按照示例中的方式连接到网站,串行监视器会输出 HTML。

完成此步骤后就完成了三分之一。

使用 Arduino ESP32 收集温湿度数据-15

7. 连接 DHT-22 传感器

现在连接 Arduino 的 DHT-22 传感器来获取温湿度值。

首先,查找并安装库。

搜索 dht 传感器库并安装 Adafruit 制作的库。

使用 Arduino ESP32 收集温湿度数据-16

进入 文件->示例 中,可以找到温湿度计示例。

从这些示例中进行传感器测试。

删除注释后,核心如下所示。

使用 Arduino ESP32 收集温湿度数据-17
#include "DHT.h"

#define DHTPIN 4 // 引脚编号指定
#define DHTTYPE DHT22 // DHT 22 
DHT dht(DHTPIN, DHTTYPE);

void setup() {
 Serial.begin(115200); // 串口通信速度. 设置为 115200
 Serial.println(F("DHTxx test!"));
 dht.begin();
}

void loop() {
 delay(2000);
 float h = dht.readHumidity();
 float t = dht.readTemperature();
 float f = dht.readTemperature(true); // 输入 true 则为华氏温度

 if (isnan(h) || isnan(t) || isnan(f)) {
 Serial.println(F("Failed to read from DHT sensor!"));
 return;
 }

 float hif = dht.computeHeatIndex(f, h); // 这是体感温度
 float hic = dht.computeHeatIndex(t, h, false);

 Serial.print(F("Humidity: "));
 Serial.print(h);
 Serial.print(F("% Temperature: "));
 Serial.print(t);
 Serial.print(F("°C "));
 Serial.print(f);
 Serial.print(F("°F Heat index: "));
 Serial.print(hic);
 Serial.print(F("°C "));
 Serial.print(hif);
 Serial.println(F("°F"));
}

通过 Arduino 上传后,可以在串行监视器中确认温度输出。

吹一口气后,湿度迅速飙升到 100%。

使用 Arduino ESP32 收集温湿度数据-18

现在 Arduino 的 Wi-Fi 连接和传感器连接都已解决,可以开始进行 Google 表格设置。

8. Google 表格设置

尽量由我来写,但仅设置 Google 表格的步骤就太长了,所以附上之前写的文章。

请查看以下链接。

9. 从 Arduino 发起 Get 请求

Google 表格设置完成后,可以从 Arduino 发起 GET 请求。

请参考上面的 Wi-Fi 连接示例。

这里只需将请求地址更换为 Google 脚本即可。

中间部分略过。

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>
#include <NetworkClientSecure.h>

...

String host = "https://script.google.com/";
String googleScriptID = "我的 Google 脚本 ID";
String scriptUrl = "macros/s/"+googleScriptID+"/exec";
String queryString = "?value1='你好'&value2='正在测试!'";
String getReqUrl = host + scriptUrl + queryString;

void setup() {
 
 ...

 WiFiMulti.addAP("Wi-Fi 名称", "Wi-Fi 密码");

 ...
}

void loop() {
 NetworkClientSecure *client = new NetworkClientSecure;
 if (client) {
 client->setCACert(rootCACertificate);
 {
 HTTPClient https;
 Serial.print("[HTTPS] begin...\n");
 if (https.begin(*client, getReqUrl)) { // <--- 只需修改这部分
 
 ...

 }
 }}
}

执行后会看到数据出现在电子表格中。

最后一个步骤是接收 DHT-22 的数据并传输。

使用 Arduino ESP32 收集温湿度数据-20

10. 合并代码

使用 Arduino ESP32 收集温湿度数据-21

现在合并两个代码。

如果代码合并困难,也可以无脑交给 AI。

首先,我将 DHT-22 的循环代码修改为返回天气数据结构体的函数。

#include "DHT.h"

#define DHTPIN 4   
#define DHTTYPE DHT22   

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(115200);
  dht.begin();
}

struct WeatherData {
  float humi;
  float temp;
  float heat;
  bool valid;
};

WeatherData getWeather() {
  WeatherData data;
  data.humi = dht.readHumidity();
  data.temp = dht.readTemperature();

  if (isnan(data.humi) || isnan(data.temp)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    data.valid = false;
    return data;
  }
  data.valid = true;
  data.heat = dht.computeHeatIndex(data.temp, data.humi, false);

  Serial.print(F("Humidity: "));
  Serial.print(data.humi);
  Serial.print(F("%  Temperature: "));
  Serial.print(data.temp);
  Serial.print(F("°C "));
  Serial.print(F("°Heat index: "));
  Serial.print(data.heat);
  Serial.print(F("°C "));
  return data;
}

将需要的部分适当合并进 httpsClient 代码中。

现在进行合并。

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>
#include <NetworkClientSecure.h>
#include "DHT.h"

...
证书略过
...

void setClock() {
  ...
}

#define DHTPIN 4   
#define DHTTYPE DHT22   

WiFiMulti WiFiMulti;
DHT dht(DHTPIN, DHTTYPE);
char* SSID = "Wi-Fi 名称";
char* PASSWORD = "Wi-Fi 密码";
String host = "https://script.google.com/";
String googleScriptID = "我的 Google 脚本 ID";
String scriptUrl = "macros/s/"+googleScriptID+"/exec";

struct WeatherData {
  ...
};

WeatherData getWeather(); // 因错误声明提前


void setup() {
  dht.begin();
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP(SSID, PASSWORD);
  Serial.print(F("Waiting for WiFi to connect..."));
  while ((WiFiMulti.run() != WL_CONNECTED)) {
    Serial.print(F("."));
  }
  Serial.println(F(" connected"));
  setClock();
}

WeatherData getWeather() {
    ...
}


void loop() {
  NetworkClientSecure *client = new NetworkClientSecure;
  if (client) {
    client->setCACert(rootCACertificate);
    {
      HTTPClient https;
      WeatherData data = getWeather();
      if (!data.valid){
        Serial.println(F("无天气信息可获取。"));
        Serial.println("等待 10 秒后再试...");
        delay(10000);
        return;
      };
      Serial.print("[HTTPS] begin...\n");
      String queryString = "?value1=" + String(data.humi) + "&value2=" + String(data.temp) ;
      String getReqUrl = host + scriptUrl + queryString;
      if (https.begin(*client, getReqUrl)) {  // HTTPS
        Serial.print("[HTTPS] GET...\n");

        int httpCode = https.GET();

        if (httpCode > 0) {
          Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
        } else {
          Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
        }
        https.end();
      } else {
        Serial.printf("[HTTPS] Unable to connect\n");
      }
    }
    delete client;
  } else {
    Serial.println("Unable to create client");
  }
  Serial.println();
  Serial.println("等待 10 秒后再试...");
  delay(10000);
}

执行后如果串行监视器上显示湿度、温度,还能看到 GET 请求代码 200,则表示成功。

进入电子表格确认数据即可。

使用 Arduino ESP32 收集温湿度数据-22

11. 追加工作

如果想记录体感温度,可以修改 Google 脚本。

在解析参数的部分添加变量或更改变量名称即可。

...
for (var param in e.parameter) {
  Logger.log('In for loop, param=' + param);
  var value = stripQuotes(e.parameter[param]);
  Logger.log(param + ':' + e.parameter[param]);
  switch (param) {
    case 'humi':
    rowData[2] = value; // value1 in column C
    result = '湿度已记录'; 
    break;
    case 'temp':
    rowData[3] = value; // Humidity in column D
    result += ', 温度已记录'; 
    break;
    case 'heat':
    rowData[4] = value;
    result += ", 体感温度已记录";
    break

    default:
    result = "不支持的参数。";
  }
...

当然,这样做后也需要在 Arduino 代码中更改查询字符串。

无论如何,这是个性化项目,因此这样做是为了未来的维护或个人偏好。

12. 总结

过去和学生们进行实验时,有如下数据。

中间的数据缺失是由于夜间断电造成的...

不过,如此简单的装置也能自动收集数据,我们只需分析这些数据,真是个不错的项目。

使用 Arduino ESP32 收集温湿度数据-23

从制作的结果来看,内容似乎不多,但详细描述下来文章变得非常长。

在 16+1 课程上,前 3 小时是 C 语言,后 2 小时是 Arduino 温湿度计,剩下的时间是个人项目,担心时间不够用。

希望精心准备的课程顺利结束,并迎接暑假。

댓글을 불러오는 중...