用ESP32和OLED做个桌面小摆件:实时显示Wi-Fi信号强度与IP地址
用ESP32和OLED打造智能桌面信息站实时监控Wi-Fi与设备状态在创客和物联网爱好者的世界里ESP32和OLED显示屏的组合堪称黄金搭档。这个迷你项目将带你一步步构建一个功能实用、外观精致的桌面信息显示器不仅能实时显示Wi-Fi信号强度、设备IP地址还能扩展显示更多实用信息。相比简单的Hello World式显示我们将深入探讨如何优化显示布局、处理网络连接异常以及如何通过模块化代码设计让项目易于扩展。1. 硬件选型与连接1.1 核心组件介绍ESP32开发板的选择对整个项目的稳定性和扩展性至关重要。推荐使用ESP32-WROOM-32系列它集成了以下优势特性双核240MHz处理器轻松处理网络通信和显示刷新内置Wi-Fi和蓝牙双模无线连接丰富的GPIO接口支持多种通信协议低功耗设计适合长时间运行OLED显示屏方面0.96寸SSD1306驱动的I2C接口屏幕是最佳选择分辨率128×64足够显示多行信息自发光特性无需背光超薄设计厚度仅1mm左右功耗极低全屏点亮仅约20mA1.2 硬件连接指南正确的接线是项目成功的第一步。ESP32与OLED的I2C连接方式如下OLED引脚ESP32 GPIO功能说明GNDGND地线VCC3.3V电源SCLGPIO22时钟线SDAGPIO21数据线注意不同型号的ESP32开发板I2C引脚可能不同使用前请查阅具体开发板的引脚定义。部分开发板标注的SCL/SDA可能并非默认I2C引脚。硬件组装完成后建议先用热熔胶固定连接处防止接触不良。如果计划长期使用可以考虑设计3D打印外壳或购买现成的防护套件。2. 开发环境搭建与基础显示2.1 开发环境配置我们选择PlatformIO作为开发环境它比Arduino IDE更适合ESP32的深度开发。安装步骤如下安装VS Code在扩展商店搜索安装PlatformIO IDE创建新项目选择ESP32 Dev Module作为开发板添加所需库依赖lib_deps adafruit/Adafruit SSD1306^2.5.7 adafruit/Adafruit GFX Library^1.11.32.2 OLED基础显示实现先实现最基本的OLED显示功能创建oled_display.h头文件#include Wire.h #include Adafruit_GFX.h #include Adafruit_SSD1306.h #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, Wire, OLED_RESET); void setupOLED() { if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println(F(SSD1306 allocation failed)); for(;;); } display.clearDisplay(); display.setTextColor(SSD1306_WHITE); }在主程序中调用显示测试void displayTest() { display.clearDisplay(); display.setTextSize(1); display.setCursor(0,0); display.println(Hello World!); display.setTextSize(2); display.setCursor(0,16); display.println(ESP32); display.display(); }这段代码展示了OLED显示的基本操作流程清屏→设置文本属性→定位光标→输出内容→刷新显示。注意每次修改显示内容后都必须调用display()才能真正更新屏幕。3. Wi-Fi连接与网络信息获取3.1 Wi-Fi连接实现稳定的网络连接是获取IP和信号强度的前提。我们采用以下策略增强连接可靠性多SSID支持可配置多个备用网络自动重连连接断开时自动尝试恢复超时处理避免长时间阻塞主程序创建wifi_manager.h实现智能连接#include WiFi.h #include vector struct WiFiNetwork { String ssid; String password; }; class WiFiManager { private: std::vectorWiFiNetwork networks; unsigned long lastConnectTime 0; const unsigned long connectTimeout 10000; // 10秒超时 public: void addNetwork(const String ssid, const String password) { networks.push_back({ssid, password}); } bool connect() { if(WiFi.status() WL_CONNECTED) return true; for(auto net : networks) { WiFi.begin(net.ssid.c_str(), net.password.c_str()); lastConnectTime millis(); while(WiFi.status() ! WL_CONNECTED millis() - lastConnectTime connectTimeout) { delay(500); Serial.print(.); } if(WiFi.status() WL_CONNECTED) { Serial.println(\nConnected to: net.ssid); return true; } } return false; } int8_t getSignalStrength() { if(WiFi.status() ! WL_CONNECTED) return -100; return WiFi.RSSI(); } String getLocalIP() { return WiFi.localIP().toString(); } };3.2 信号强度可视化将抽象的信号强度值转换为直观的图形显示能极大提升用户体验。我们设计一个信号强度指示器void drawWiFiSignal(int8_t rssi) { // 将RSSI转换为0-4的等级 int bars 0; if(rssi -55) bars 4; else if(rssi -65) bars 3; else if(rssi -75) bars 2; else if(rssi -85) bars 1; // 绘制信号图标框架 display.drawRect(105, 0, 18, 10, SSD1306_WHITE); // 根据信号强度绘制条形 for(int i0; ibars; i) { display.fillRect(108 i*4, 8 - i*2, 2, i*2 2, SSD1306_WHITE); } // 显示具体dBm值可选 display.setCursor(90, 12); display.print(rssi); display.print(dBm); }4. 信息显示优化与界面设计4.1 多信息页面布局有限的可视区域需要精心设计信息排布。我们采用分页显示策略enum DisplayPage { PAGE_MAIN, PAGE_NETWORK, PAGE_SYSTEM, PAGE_MAX }; DisplayPage currentPage PAGE_MAIN; void updateDisplay() { display.clearDisplay(); switch(currentPage) { case PAGE_MAIN: drawMainPage(); break; case PAGE_NETWORK: drawNetworkPage(); break; case PAGE_SYSTEM: drawSystemPage(); break; } // 公共元素页眉页脚 drawHeader(); drawFooter(); display.display(); } void drawMainPage() { display.setTextSize(2); display.setCursor(0, 15); display.print(IP:); display.setTextSize(1); display.setCursor(0, 35); display.print(WiFiManager.getLocalIP()); drawWiFiSignal(WiFiManager.getSignalStrength()); }4.2 显示刷新优化频繁的全屏刷新会导致闪烁我们采用差异刷新策略静态内容只在初始化时绘制一次动态内容仅更新变化的部分定时刷新非实时数据可降低刷新频率实现部分刷新功能void refreshDynamicContent() { static String lastIP ; static int8_t lastRSSI 0; String currentIP WiFiManager.getLocalIP(); int8_t currentRSSI WiFiManager.getSignalStrength(); if(currentIP ! lastIP) { display.fillRect(0, 35, 128, 8, SSD1306_BLACK); display.setCursor(0, 35); display.print(currentIP); lastIP currentIP; } if(abs(currentRSSI - lastRSSI) 2) { // 避免微小波动导致的频繁刷新 display.fillRect(90, 0, 38, 22, SSD1306_BLACK); drawWiFiSignal(currentRSSI); lastRSSI currentRSSI; } }5. 项目扩展与进阶功能5.1 添加物理交互按钮通过按钮实现页面切换和功能触发#define BUTTON_PIN 0 // 通常使用GPIO0开发板上的BOOT按钮 void setupButtons() { pinMode(BUTTON_PIN, INPUT_PULLUP); } void checkButtons() { static unsigned long lastPress 0; if(digitalRead(BUTTON_PIN) LOW millis() - lastPress 200) { // 防抖处理 lastPress millis(); currentPage (DisplayPage)((currentPage 1) % PAGE_MAX); updateDisplay(); } }5.2 扩展显示内容利用ESP32的强大性能可以添加更多实用信息系统信息页运行时间内存使用情况CPU温度部分ESP32型号支持环境信息页通过I2C连接传感器获取温湿度空气质量数据网络工具页Ping测试结果网络速度监测实现示例void drawSystemPage() { // 显示运行时间 display.setCursor(0, 10); display.print(Uptime:); display.setCursor(0, 20); display.print(millis() / 1000); display.print(s); // 显示内存信息 display.setCursor(0, 35); display.print(Free RAM:); display.setCursor(0, 45); display.print(esp_get_free_heap_size() / 1024); display.print(KB); }5.3 低功耗优化对于电池供电的应用功耗优化至关重要动态刷新率调整void adjustRefreshRate() { static unsigned long lastActivity millis(); unsigned long idleTime millis() - lastActivity; if(idleTime 300000) { // 5分钟无操作 setRefreshInterval(5000); // 降低到5秒刷新一次 } else { setRefreshInterval(500); // 正常0.5秒刷新 } }深度睡眠模式void enterDeepSleep() { display.clearDisplay(); display.display(); display.ssd1306_command(SSD1306_DISPLAYOFF); esp_sleep_enable_timer_wakeup(30 * 1000000); // 30秒后唤醒 esp_deep_sleep_start(); }6. 项目部署与实用技巧6.1 固件远程更新(OTA)通过Wi-Fi实现无线固件更新#include ESPmDNS.h #include WiFiUdp.h #include ArduinoOTA.h void setupOTA() { ArduinoOTA .onStart([]() { display.clearDisplay(); display.setCursor(0, 20); display.print(OTA Updating); display.display(); }) .onEnd([]() { display.clearDisplay(); display.setCursor(0, 20); display.print(OTA Complete); display.display(); delay(2000); }); ArduinoOTA.begin(); } void loop() { ArduinoOTA.handle(); // ...其他循环代码 }6.2 3D打印外壳设计为项目设计专属外壳的建议使用Fusion 360或Tinkercad进行建模预留OLED视窗和按钮开口考虑散热孔设计提供多种安装方式桌面摆放/壁挂6.3 实际应用场景扩展这个基础项目可以衍生出多种实用变体智能家居信息中心显示智能设备状态网络监控工具实时显示网络质量开发调试助手显示传感器数据个性化电子相框循环显示自定义信息在完成基础功能后我建议尝试添加温湿度传感器如DHT22或BME280来扩展功能。实际测试中发现将Wi-Fi信号强度检测与定时网络诊断结合能帮助快速定位家庭网络死角。另外使用PlatformIO的多环境配置可以轻松管理开发版和生产版的固件差异这在需要部署多个设备时特别有用。