ESP32教程43/55 - 物联网互联网气象站 | SunFounder的ESP32物联网学习套件
在本教程中,我们将使用ESP32及其来自SunFounder的摄像头扩展板构建一个连接互联网的气象站。该项目使ESP32能够获取实时天气数据,包括温度和湿度,并将其显示在LCD屏幕上。此应用不仅展示了ESP32的功能,还演示了如何从外部API获取和解析数据。

随着教程的推进,我们将连接组件、配置代码,并确保一切无缝协同工作。最终结果将是一个功能齐全的气象站,每10秒更新一次读数,清晰简洁地显示当前天气状况(视频中00:30处)。
硬件说明
本项目中使用的主要组件包括ESP32微控制器、LCD显示屏以及必要的接线。ESP32内置Wi-Fi和蓝牙,使其能够连接互联网并获取数据。LCD显示屏将显示当前天气信息,包括温度和湿度。
我们使用的LCD是16x2字符显示屏,这意味着它可以显示两行,每行16个字符。这对于我们的天气信息输出来说已经足够。ESP32将通过I2C与LCD通信,这仅使用两条数据线,简化了接线。
数据手册详情
| 制造商 | 乐鑫 |
|---|---|
| 零件编号 | ESP32-WROOM-32 |
| 逻辑/IO电压 | 3.3 V |
| 电源电压 | 3.0–3.6 V |
| 输出电流(每通道) | 最大12 mA |
| 峰值电流(每通道) | 40 mA |
| PWM频率建议 | 1 kHz |
| 输入逻辑阈值 | 0.3 V(低),0.7 V(高) |
| 压降 / RDS(on) / 饱和 | 0.5 V |
| 热限制 | -40至85 °C |
| 封装 | QFN48 |
| 备注 / 变体 | 包含适用于不同应用的多种变体 |
- 确保ESP32使用稳定的3.3 V电源供电。
- 为所有组件使用公共接地,以避免通信问题。
- 使用I2C扫描器检查LCD的I2C地址。
- 监控Wi-Fi连接状态,以避免在数据获取期间断开连接。
- 处理JSON解析错误,以增强数据检索的稳健性。
接线说明

要连接组件,首先将LCD连接到ESP32。LCD将使用I2C接口,因此将LCD的SDA引脚连接到ESP32上的GPIO21,将SCL引脚连接到GPIO22。确保将LCD的电源和接地引脚分别连接到ESP32上的5V和GND引脚。
接下来,确保使用随附的锂电池或USB连接正确为ESP32供电。电池提供便携性,而USB连接则适用于编程和调试。最后,检查所有连接是否牢固,以避免可能干扰功能的松动接线问题。
代码示例与讲解
在程序的设置阶段,我们初始化串行通信并使用提供的SSID和密码连接到Wi-Fi网络。以下代码片段处理Wi-Fi连接:
WiFi.begin(ssid, password);
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("已连接到Wi-Fi网络,IP地址:");
Serial.println(WiFi.localIP());
此代码确保ESP32在进行任何数据获取之前连接到指定的Wi-Fi网络。如果连接失败,它将持续尝试重新连接。
接下来,我们需要发送HTTP GET请求以获取天气数据。这通过以下代码片段实现:
String serverPath = "http://api.openweathermap.org/data/2.5/weather?q=" + city + "," + countryCode + "&units=metric" + "&APPID=" + openWeatherMapApiKey;
jsonBuffer = httpGETRequest(serverPath.c_str());
在这里,我们构建API请求的URL,其中包含城市、国家代码和我们的API密钥。然后调用httpGETRequest函数来获取天气数据。
最后,我们解析JSON响应并将相关数据显示在LCD上:
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(time);
lcd.print(" ");
lcd.print(myObject["weather"][0]["main"]);
lcd.setCursor(0, 1);
lcd.print("T:");
lcd.print(myObject["main"]["temp"]);
lcd.print("\xDF"); // "°"字符
lcd.print("C ");
lcd.print("H:");
lcd.print(myObject["main"]["humidity"]);
lcd.print("%");
此代码片段使用当前时间、天气状况、温度和湿度更新LCD显示。它清除之前的显示并将光标设置到每行的适当位置。
演示 / 预期效果
成功接线和编程后,您的气象站将连接到Wi-Fi并开始每10秒获取一次天气数据。您将看到当前温度、湿度和天气状况显示在LCD屏幕上。如果ESP32无法连接到Wi-Fi,它将在串行监视器上打印错误消息。
请注意API调用限制,以免被OpenWeatherMap服务屏蔽。如果在数据获取过程中遇到任何问题,请检查您的API密钥,并确保城市和国家代码填写正确(视频15:45处有说明)。
视频时间戳
- 00:00 开始
- 2:00 项目介绍
- 5:04 OpenWeather账户
- 6:11 接线
- 8:05 Arduino代码详解
- 14:13 代码中的JSON元素
- 20:23 在Arduino IDE中选择ESP32开发板和COM端口
- 22:05 LCD1602气象站演示
- 23:45 LCD2004气象站演示
/*
* 鲁伊·桑托斯
* 完整项目详情请访问 https://RandomNerdTutorials.com/esp32-http-get-open-weather-map-thingspeak-arduino/
*
* 在此免费授权任何获取本软件及相关文档文件副本的人。
*
* 上述版权声明和本许可声明应包含在所有副本或软件的重要部分中。
*/
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <Arduino_JSON.h>
// 将下列变量替换为您的SSID/密码组合。
const char* ssid = "SSID";
const char* password = "PASSWORD";
// 您的域名及其 URL 路径或带路径的 IP 地址
String openWeatherMapApiKey = "openWeatherMapApiKey";
// 用您的国家代码和城市替换
// 通过 https://openweathermap.org/find 查找国家代码
String city = "CITY";
String countryCode = "COUNTRY CODE";
// 默认定时器设置为 10 秒,供测试之用。
// 对于最终应用程序,请检查每小时/每分钟的API调用限制,以避免被封锁/禁用。
unsigned long lastTime = 0;
// 定时器设置为10分钟(600000)
// 无符号长整型定时器延迟 = 600000;
// 设置计时器为10秒(10000)
unsigned long timerDelay = 10000;
String jsonBuffer;
// 设置液晶显示器的列数和行数
int lcdColumns = 16;
int lcdRows = 2;
// 设置LCD地址、列数和行数
// SDA -> GPIO21,SCL -> GPIO22
// LCD地址是0x27,运行一个I2C扫描器代码。
LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows);
// NTP服务器时间
const char* ntpServer = "pool.ntp.org";
long gmtOffset_sec = 0;
int daylightOffset_sec = 0; // 3600;
void setup() {
Serial.begin(115200);
// WiFi
WiFi.begin(ssid, password);
Serial.println("Connecting");
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());
Serial.println("Timer set to 10 seconds (timerDelay variable), it will take 10 seconds before publishing the first reading.");
// 初始化LCD
lcd.init();
// 打开LCD背光
lcd.backlight();
}
void loop() {
// 发送一个HTTP GET请求
if ((millis() - lastTime) > timerDelay) {
// 检查WiFi连接状态
if(WiFi.status()== WL_CONNECTED){
String serverPath = "http: // api.openweathermap.org/data/2.5/weather?q=" + city + "," + countryCode + "&units=metric" + "&APPID=" + openWeatherMapApiKey;
jsonBuffer = httpGETRequest(serverPath.c_str());
Serial.println(jsonBuffer);
JSONVar myObject = JSON.parse(jsonBuffer);
// JSON.typeof(jsonVar) 可以用来获取变量的类型。
if (JSON.typeof(myObject) == "undefined") {
Serial.println("Parsing input failed!");
return;
}
// JSON对象 =
// Serial.println(myObject);
// 温度:
// Serial.println(myObject["main"]["temp"]);
// 压力:
// Serial.println(myObject["main"]["pressure"]);
// 湿度:
// Serial.println(myObject["main"]["湿度"]);
// 风速:
// Serial.println(myObject["风"]["速度"]);
// 获取时间
gmtOffset_sec = myObject["timezone"];
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
// 时间 =
String time = printLocalTime();
// 液晶打印
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(time);
lcd.print(" ");
lcd.print(myObject["weather"][0]["main"]);
lcd.setCursor(0, 1);
lcd.print("T:");
lcd.print(myObject["main"]["temp"]);
lcd.print("\xDF"); // "°" 字符
lcd.print("C ");
lcd.print("H:");
lcd.print(myObject["main"]["humidity"]);
lcd.print("%");
}
else {
Serial.println("WiFi Disconnected");
}
lastTime = millis();
}
}
String printLocalTime(){
struct tm timeinfo;
if(!getLocalTime(&timeinfo)){
Serial.println("Failed to obtain time");
return "null";
}
// Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
// 获取时间格式 HH:MM
char timeHour[3];
strftime(timeHour,3, "%H", &timeinfo);
char timeMinute[3];
strftime(timeMinute,3, "%M", &timeinfo);
String time = String(timeHour) + ":" + String(timeMinute);
Serial.println(time)
; return time;
}
String httpGETRequest(const char* serverName) {
WiFiClient client;
HTTPClient http;
// 您的域名及其 URL 路径或带路径的 IP 地址
http.begin(client, serverName);
// 发送HTTP POST请求
int httpResponseCode = http.GET();
String payload = "{}";
if (httpResponseCode>0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
payload = http.getString();
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
// 免费资源
http.end();
return payload;
}
Common Course Links
Common Course Files
资源与参考
-
文档ESP32 教程 43/55 - SunFounder 物联网天气站文档页面docs.sunfounder.com
文件📁
没有可用的文件。