今天,我们将使用 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 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 |
D6–D11 | 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) |
|---|---|---|
外形 | ![]() | ![]() |
温度测量范围 | 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,CH341U5. Arduino IDE 电路板管理器设置
现在来设置 Arduino IDE 中的电路板管理器。
在 Arduino IDE 中进入 File > Preferences (基本设置)。

在附加电路板管理 URL 中复制输入以下地址。
https://espressif.github.io/arduino-esp32/package_esp32_index.json

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

将 Arduino 连接到 USB 端口后,端口会自动被识别。
现在选择对应端口的 Arduino 电路板即可。

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");
}如果上传失败,请调节上传速度。
在 工具 -> 上传速度 中更改为稍低一点的数值可以更稳定。

按照示例中的方式连接到网站,串行监视器会输出 HTML。
完成此步骤后就完成了三分之一。

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%。

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

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 温湿度计,剩下的时间是个人项目,担心时间不够用。
希望精心准备的课程顺利结束,并迎接暑假。




댓글을 불러오는 중...