1

使用 Arduino ESP32 收集温湿度数据

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

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

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

1. 准备材料

准备工作很简单。

ESP32, DHT-22, 三根电线
准备材料

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

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

2. ESP32 引脚图

准备材料

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

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

以下是 ESP32 Arduino 的引脚映射。

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

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

Arduino 引脚图

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)

外形

dth-11dth-22

温度测量范围

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 驱动程序

准备材料

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

这是中国制造的称为 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 电路板管理器设置

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

https://espressif.github.io/arduino-esp32/package_esp32_index.json
Arduino ESP32 电路板管理器设置Arduino ESP32 电路板管理器设置

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

alt text

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

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

Arduino esp32

6. 连接 Wi-Fi

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

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

示例

只需更改这个示例中的 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");
}

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

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

upload

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

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

https Test

7. 连接 DHT-22 传感器

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

首先,查找并安装库。

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

上传的图片

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

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

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

示例
#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%。

serialMonitor

现在 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 的数据并传输。

reqTest

10. 合并代码

上传的图片

现在合并两个代码。

如果代码合并困难,也可以无脑交给 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,则表示成功。

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

电子表格

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. 总结

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

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

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

过往数据

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

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

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

댓글을 불러오는 중...