ESP32玩转1.8寸LCD屏:用TFT_eSPI库做个桌面小天气站(附完整代码)
ESP32玩转1.8寸LCD屏用TFT_eSPI库做个桌面小天气站附完整代码在物联网和智能家居的浪潮中ESP32凭借其强大的性能和丰富的功能成为了创客们的首选。而1.8寸LCD屏则因其小巧的体积和清晰的显示效果成为了嵌入式项目中的热门选择。本文将带你从零开始使用TFT_eSPI库打造一个实用的桌面天气站不仅能显示实时天气信息还能成为你桌面上的一道亮丽风景线。1. 硬件准备与环境搭建1.1 所需硬件清单在开始项目前我们需要准备以下硬件组件ESP32开发板推荐使用ESP32-WROOM-321.8寸TFT LCD屏ST7735驱动芯片面包板和杜邦线用于连接电路Micro USB数据线用于供电和编程可选3D打印外壳提升项目美观度1.2 电路连接指南正确连接ESP32与LCD屏是项目成功的第一步。以下是典型的引脚连接方式LCD引脚ESP32引脚功能说明VCC3.3V电源正极GNDGND电源地SCLGPIO18SPI时钟SDAGPIO23SPI数据RESGPIO4复位信号DCGPIO2数据/命令选择CSGPIO5片选信号提示不同型号的LCD屏可能有不同的引脚定义请务必参考你的屏幕规格书。1.3 软件环境配置安装Arduino IDE建议1.8.x或更高版本添加ESP32开发板支持# 在Arduino首选项中添加开发板管理器网址 https://dl.espressif.com/dl/package_esp32_index.json通过库管理器安装以下库TFT_eSPI用于驱动LCD屏ArduinoJson用于解析天气数据WiFiManager用于WiFi配置2. TFT_eSPI库配置与基础使用2.1 库文件配置TFT_eSPI库需要通过修改配置文件来适配不同的屏幕找到库目录下的User_Setup.h文件取消ST7735驱动的注释并注释掉其他不相关的驱动设置正确的屏幕分辨率和SPI引脚// 示例配置片段 #define ST7735_DRIVER #define TFT_WIDTH 128 #define TFT_HEIGHT 160 #define TFT_MOSI 23 #define TFT_SCLK 18 #define TFT_CS 5 #define TFT_DC 2 #define TFT_RST 42.2 基础显示功能测试在正式开发天气站前我们先测试屏幕的基本功能#include TFT_eSPI.h TFT_eSPI tft TFT_eSPI(); void setup() { tft.init(); tft.setRotation(3); // 根据屏幕方向调整 tft.fillScreen(TFT_BLACK); tft.setTextColor(TFT_WHITE); tft.setTextSize(2); tft.drawString(Hello World!, 10, 10); } void loop() { // 空循环 }2.3 常用绘图函数TFT_eSPI库提供了丰富的绘图功能这些将在天气站的UI设计中大显身手文本显示drawString(),setTextSize(),setTextColor()图形绘制drawLine(),drawCircle(),fillRect()图像显示pushImage()支持BMP格式3. 天气数据获取与处理3.1 选择天气API市面上有多种免费的天气API可供选择API名称免费额度数据更新频率特点OpenWeatherMap60次/分钟每2小时全球覆盖数据全面和风天气1000次/天实时中文支持好WeatherAPI100万次/月实时简单易用注意使用API前需要注册获取API Key请妥善保管不要泄露。3.2 HTTP请求与JSON解析以下是使用OpenWeatherMap API获取天气数据的示例代码#include WiFi.h #include HTTPClient.h #include ArduinoJson.h const char* ssid 你的WiFi名称; const char* password 你的WiFi密码; const String apiKey 你的API密钥; const String city Beijing; void getWeatherData() { if (WiFi.status() WL_CONNECTED) { HTTPClient http; String url http://api.openweathermap.org/data/2.5/weather?q city appid apiKey unitsmetric; http.begin(url); int httpCode http.GET(); if (httpCode HTTP_CODE_OK) { String payload http.getString(); DynamicJsonDocument doc(1024); deserializeJson(doc, payload); float temp doc[main][temp]; int humidity doc[main][humidity]; const char* desc doc[weather][0][description]; // 在这里处理天气数据... } http.end(); } }3.3 数据缓存与更新策略为了减少API调用次数并保持数据新鲜我们可以实现以下策略每次获取数据后保存到全局变量设置定时器每30分钟更新一次数据在屏幕刷新时显示缓存数据网络异常时显示最后有效数据4. 天气站UI设计与实现4.1 界面布局规划一个美观实用的天气站界面通常包含以下元素顶部区域城市名称、当前时间中部区域天气图标、温度显示底部区域湿度、风速等详细信息背景根据天气状况动态变化晴天、雨天等4.2 主要界面组件实现4.2.1 温度显示组件void drawTemperature(float temp) { tft.fillRect(20, 50, 88, 60, TFT_BLACK); tft.setTextColor(TFT_YELLOW); tft.setTextSize(4); tft.drawFloat(temp, 1, 30, 50); // 绘制摄氏度符号 tft.setTextSize(2); tft.drawString(o, 90, 50); tft.drawCircle(100, 52, 2, TFT_YELLOW); }4.2.2 天气图标绘制根据不同的天气状况显示相应的图标void drawWeatherIcon(String condition) { tft.fillRect(0, 0, 128, 40, TFT_BLACK); if (condition.indexOf(rain) 0) { // 绘制雨天图标 tft.fillCircle(30, 20, 15, TFT_LIGHTGREY); tft.fillCircle(50, 20, 15, TFT_LIGHTGREY); tft.fillTriangle(20, 20, 40, 20, 30, 40, TFT_LIGHTGREY); // 绘制雨滴... } else if (condition.indexOf(cloud) 0) { // 绘制多云图标 // ... } else { // 默认晴天图标 tft.fillCircle(40, 20, 15, TFT_YELLOW); } }4.3 完整天气站代码实现以下是整合了所有功能的完整代码框架#include TFT_eSPI.h #include WiFi.h #include HTTPClient.h #include ArduinoJson.h #include TimeLib.h TFT_eSPI tft TFT_eSPI(); // WiFi和API配置 const char* ssid yourSSID; const char* password yourPassword; const String apiKey yourAPIKey; const String city Beijing; // 天气数据结构 struct WeatherData { float temperature; int humidity; String description; time_t lastUpdate; } currentWeather; void setup() { Serial.begin(115200); tft.init(); tft.setRotation(3); connectWiFi(); getWeatherData(); // 初始化时间显示 configTime(8 * 3600, 0, pool.ntp.org); } void loop() { static unsigned long lastUpdate 0; // 每30分钟更新一次天气数据 if (millis() - lastUpdate 30 * 60 * 1000) { getWeatherData(); lastUpdate millis(); } // 刷新界面 drawInterface(); delay(1000); } void connectWiFi() { WiFi.begin(ssid, password); while (WiFi.status() ! WL_CONNECTED) { delay(500); Serial.print(.); } Serial.println(WiFi connected); } void getWeatherData() { if (WiFi.status() WL_CONNECTED) { HTTPClient http; String url http://api.openweathermap.org/data/2.5/weather?q city appid apiKey unitsmetric; http.begin(url); int httpCode http.GET(); if (httpCode HTTP_CODE_OK) { String payload http.getString(); DynamicJsonDocument doc(1024); deserializeJson(doc, payload); currentWeather.temperature doc[main][temp]; currentWeather.humidity doc[main][humidity]; currentWeather.description doc[weather][0][description].asString(); currentWeather.lastUpdate now(); } http.end(); } } void drawInterface() { tft.fillScreen(TFT_BLACK); // 绘制时间 drawTime(); // 绘制天气图标 drawWeatherIcon(currentWeather.description); // 绘制温度 drawTemperature(currentWeather.temperature); // 绘制其他信息 drawAdditionalInfo(); } // 其他绘制函数实现...5. 项目优化与扩展5.1 低功耗优化对于电池供电的场景我们可以采取以下措施降低功耗使用ESP32的深度睡眠模式减少屏幕刷新频率关闭不需要的外设优化WiFi连接策略// 深度睡眠示例 void enterDeepSleep() { esp_sleep_enable_timer_wakeup(30 * 60 * 1000000); // 30分钟 esp_deep_sleep_start(); }5.2 多城市支持通过按钮或Web界面切换显示不同城市的天气添加物理按钮切换城市实现简单的Web配置界面将城市列表保存在EEPROM中5.3 3D打印外壳设计为天气站设计一个精美的外壳可以大大提升产品的完成度考虑屏幕的可视角度预留ESP32的编程接口设计合理的散热结构添加挂墙或桌面摆放的选项6. 常见问题与解决方案6.1 屏幕显示异常现象屏幕出现花屏、颜色异常或无法显示解决方案检查SPI引脚连接是否正确确认User_Setup.h中的配置与硬件匹配尝试降低SPI时钟频率检查电源是否稳定6.2 WiFi连接不稳定现象天气数据无法更新或更新间隔过长解决方案添加WiFi连接状态指示实现自动重连机制考虑使用WiFiManager库实现智能配置void checkWiFi() { if (WiFi.status() ! WL_CONNECTED) { Serial.println(WiFi disconnected, reconnecting...); WiFi.disconnect(); WiFi.begin(ssid, password); } }6.3 内存不足问题现象程序运行不稳定或突然重启解决方案优化JSON解析缓冲区大小减少全局变量的使用使用PROGMEM存储常量数据定期检查内存使用情况void checkMemory() { Serial.printf(Free heap: %d bytes\n, ESP.getFreeHeap()); }通过本文的指导你应该已经掌握了使用ESP32和1.8寸LCD屏制作桌面天气站的全部技能。这个项目不仅实用而且具有很强的可扩展性你可以根据自己的需求添加更多功能如空气质量显示、天气预报、甚至与智能家居系统联动。