1. 项目概述与核心思路最近在捣鼓一些桌面小玩意儿想着能不能做个既实用又不占地方的电子摆件。正好手头有几片闲置的Wemos D1 mini这玩意儿本质上就是一块集成了WiFi的ESP8266开发板性能对于简单物联网应用绰绰有余。我的想法是做一个超迷你的天气预报器专门显示第二天的最低和最高温度放在书桌或床头一眼就能知道明天该穿什么衣服比掏出手机查天气要方便那么一点点。这个项目的核心逻辑非常清晰让一块微控制器定时从互联网上的免费气象API获取数据然后在一块很小的OLED屏幕上显示出来。听起来简单但里面涉及了几个关键环节的打通首先是硬件得让屏幕和主控板正确通信其次是软件需要编写程序处理网络连接、数据请求和解析最后是供电和外观让它能稳定、美观地运行。整个过程就像搭积木把WiFi联网、数据获取、屏幕驱动这几个模块组合起来。我选择Wemos D1 mini和它配套的0.66英寸OLED屏主要是因为它们天生一对引脚兼容省去了飞线焊接的麻烦非常适合快速原型制作。2. 硬件准备与连接要点2.1 核心元件选型解析硬件是整个项目的骨架选对部件事半功倍。我主要用了两样东西主控板Lolin Wemos D1 mini v4。选择它的理由很充分。首先它基于ESP8266芯片自带WiFi功能这是实现联网获取天气数据的基础无需额外模块。其次它体积非常小巧大约只有大拇指指甲盖那么大非常适合做这种微型设备。最后它兼容Arduino IDE开发环境有庞大的社区和库支持对于开发者极其友好。市面上版本较多v4版通常使用USB-C接口比老版的Micro-USB更通用。显示屏0.66英寸 64x48像素 OLED Shield。这里的关键词是“Shield”扩展板。这意味着这块屏幕是专门为Wemos D1 mini设计的板载了必要的电平转换和驱动电路并且引脚排列与主控板完全对应。屏幕尺寸虽小但OLED特性决定了它自发光的像素在显示深色时几乎不耗电且对比度高显示文字非常清晰。64x48的分辨率显示几行温度数字绰绰有余。注意务必确认你购买的OLED屏是“for Wemos D1 mini”的Shield版本。通用的I2C OLED屏虽然也能用但需要自己连接SDA、SCL、VCC、GND四根线并且可能需要额外的电平转换或上拉电阻对新手不友好。Shield版本是即插即用的最佳选择。2.2 硬件连接与焊接实操拿到手的两块板子可能引脚是分开的。你需要进行简单的焊接准备引脚你需要一排单排的排针male headers和一排排母female headers。焊接排母到Wemos D1 mini将排母焊接到Wemos D1 mini的板子正面即有芯片和USB接口的一面。这是为了将来屏幕可以像“帽子”一样插在上面。焊接时注意排母的塑料底座应紧贴电路板确保所有引脚垂直。焊接排针到OLED Shield将排针焊接到OLED Shield的背面即没有屏幕的一面。排针的引脚应朝下即从背面穿出到正面。连接焊接完成后只需将OLED Shield背面的排针直接插入到Wemos D1 mini正面的排母中即可。它们应该严丝合缝地对齐。至此硬件连接就完成了不需要任何杜邦线。实操心得焊接时建议使用助焊剂能让焊点更圆润光亮。对于新手可以先在一两个对角位置的引脚上点焊固定好位置后再焊接其他引脚避免排针歪斜。焊接完成后务必检查有无虚焊焊点不光滑、有裂缝或短路相邻焊点被焊锡连在一起。3. 软件开发环境搭建与核心库配置3.1 Arduino IDE环境部署软件部分我们使用最普及的Arduino IDE。但Wemos D1 miniESP8266并不是Arduino原生的板子所以第一步是把它“添加”到IDE的板卡管理器中。安装Arduino IDE从Arduino官网下载并安装最新版IDE。添加ESP8266开发板支持打开Arduino IDE进入文件-首选项。在“附加开发板管理器网址”一栏中填入以下网址http://arduino.esp8266.com/stable/package_esp8266com_index.json。如果已有其他网址用逗号隔开即可。点击“好”保存。安装ESP8266平台点击工具-开发板-开发板管理器...。在弹出的窗口中搜索“esp8266”。找到由“ESP8266 Community”提供的“esp8266”平台点击安装。这个过程会下载必要的编译工具链和核心库需要一些时间。3.2 关键库文件的安装与选择程序运行依赖几个重要的库它们提供了网络连接、JSON解析和屏幕驱动的能力。大部分可以通过IDE内置的库管理器安装但屏幕驱动库有个关键陷阱。通过库管理器安装推荐点击工具-管理库...。分别搜索并安装以下库ArduinoJson用于解析从天气API返回的JSON格式数据。请安装较新的版本如6.x或7.x代码需要对应调整。ESP8266WiFi通常安装ESP8266平台时已自带无需重复安装。Wire和SPIArduino核心库通常已内置。搜索WiFiClientSecure或相关安全连接库ESP8266核心包通常已包含。如果编译报错再尝试搜索安装。手动安装特殊的OLED驱动库这是本项目最容易踩坑的地方。通用的Adafruit_SSD1306库默认不支持64x48这种特殊分辨率的Wemos OLED Shield强行使用会导致屏幕乱码或全亮。你需要一个修改版的库。访问这个GitHub仓库https://github.com/stblassitude/Adafruit_SSD1306_Wemos_OLED。点击绿色的“Code”按钮选择“Download ZIP”。在Arduino IDE中点击项目-加载库-添加.ZIP库...然后选择你刚下载的ZIP文件。安装成功后在工具-管理库...中可能看不到它这很正常它已被添加到你的本地库中。排查技巧如果编译时提示找不到Adafruit_SSD1306.h首先检查是否安装了错误的通用库。如果是请在库管理器中卸载通用的Adafruit SSD1306库确保IDE使用的是我们手动添加的特殊版本。库的安装路径通常在Arduino IDE安装目录下的libraries文件夹或者系统的文档文件夹里可以检查是否存在重复或冲突的库文件夹。4. 程序代码详解与个性化配置4.1 程序主框架与工作流程解析完整的程序代码.ino文件包含了从启动到稳定显示的所有逻辑。其工作流程可以概括为以下几步我结合代码关键部分进行说明初始化设置setup函数程序上电或复位后执行一次。void setup() { Serial.begin(115200); // 开启串口调试便于查看日志 display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // 初始化OLED屏幕I2C地址通常是0x3C display.clearDisplay(); // 清屏 display.setTextSize(1); // 设置字体大小 display.setTextColor(SSD1306_WHITE); // 设置字体颜色白色 display.setCursor(0,0); // 设置光标起始位置 display.println(Connecting WiFi...); display.display(); // 将缓冲区内容刷到屏幕上显示 WiFi.begin(ssid, password); // 连接WiFi // ... 等待连接成功 }这里的关键是屏幕初始化必须使用正确的I2C地址0x3C是常见值SSD1306_SWITCHCAPVCC参数表示使用芯片内部电荷泵生成驱动电压。主循环loop函数连接成功后循环执行。void loop() { if (WiFi.status() WL_CONNECTED) { // 检查WiFi是否仍连接 fetchWeatherData(); // 获取天气数据 displayWeatherData(); // 显示数据 } else { // 尝试重连WiFi } delay(3600000); // 等待1小时3600000毫秒后再次执行 }核心是fetchWeatherData()函数它负责向天气API发起HTTP请求并获取数据。4.2 关键配置项修改指南要让设备为你工作必须修改源代码中的几个关键配置。这些信息通常集中在代码开头的定义部分。WiFi网络凭证const char* ssid YOUR_WIFI_SSID; // 你的WiFi名称 const char* password YOUR_WIFI_PASSWORD; // 你的WiFi密码将双引号内的内容替换成你家的WiFi名和密码。注意大小写。地理位置与API请求URL这是项目的核心配置。原代码中使用了一个指向open-meteo.comAPI的URL并包含了经纬度和时区参数。String url https://api.open-meteo.com/v1/forecast?latitude52.2658longitude6.7931dailytemperature_2m_max,temperature_2m_mintimezoneEurope/Amsterdamforecast_days2;latitude纬度 longitude经度必须改成你所在城市的坐标。最准确的方法是使用地图应用如谷歌地图、百度地图找到你的城市右键点击选择“这是什么”或类似功能即可看到经纬度。例如北京的坐标大约是latitude39.9042longitude116.4074。timezone时区改为你所在的时区。对于中国大陆使用Asia/Shanghai。时区列表可以参考IANA时区数据库。forecast_days请求预报的天数。这里设为2是为了获取明天索引为1的数据。获取坐标的实用方法除了地图应用你也可以直接搜索“[你的城市名] 经纬度”。或者使用open-meteo.com官网它提供了一个交互式地图点击位置后会自动生成包含正确坐标的API请求URL直接复制过来用更省事。数据解析逻辑适配不同的天气API返回的JSON数据结构可能不同。原代码是针对特定API编写的。你需要根据你实际使用的API响应来调整fetchWeatherData()函数中的解析部分。核心是使用ArduinoJson库来遍历JSON对象。JsonDocument doc; // 创建一个JsonDocument对象来存储解析后的数据 DeserializationError error deserializeJson(doc, payload); // payload是API返回的字符串 if (!error) { // 假设API返回的每日最高温度数组在 daily.temperature_2m_max 路径下 float tempMaxTomorrow doc[daily][temperature_2m_max][1]; // 索引0是今天1是明天 float tempMinTomorrow doc[daily][temperature_2m_min][1]; // 存储到全局变量中供显示函数使用 }务必使用串口监视器波特率115200打印出API返回的原始payload然后对照这个实际数据来调整代码中的JSON键名如dailytemperature_2m_max和访问路径。这是调试成功的关键一步。5. 数据获取、显示逻辑与优化5.1 网络请求与错误处理机制微控制器作为客户端向网络服务器发起请求这个过程需要稳定可靠。我们使用WiFiClientSecure客户端来处理HTTPS连接。void fetchWeatherData() { WiFiClientSecure client; // 创建安全客户端对象 client.setInsecure(); // 忽略SSL证书验证简化代码生产环境建议处理证书 HTTPClient http; // 创建HTTPClient对象 if (http.begin(client, url)) { // 开始连接传入URL int httpCode http.GET(); // 发送GET请求 if (httpCode HTTP_CODE_OK) { // 如果返回200 OK String payload http.getString(); // 获取响应体JSON字符串 Serial.println(payload); // 打印到串口用于调试 parseWeatherData(payload); // 调用函数解析数据 } else { Serial.printf(HTTP GET failed, error: %s\n, http.errorToString(httpCode).c_str()); displayError(HTTP Err); // 在屏幕上显示错误 } http.end(); // 结束连接 } else { Serial.println(Unable to connect to server); displayError(Conn Err); } }注意事项client.setInsecure()跳过了SSL证书验证这使代码更简单但在严格的安全要求下并不推荐。对于个人项目可以接受。网络请求可能因信号、服务器问题而失败因此必须有错误处理如displayError函数在屏幕上给出提示而不是让程序卡死或显示错误数据。5.2 OLED屏幕显示优化技巧0.66英寸屏幕很小如何清晰有效地显示信息需要设计。分屏或滚动显示由于屏幕只能显示几行文字可以考虑将“明日最低温”和“最高温”分两行显示或者加入一个简单的图标如向上箭头表示最高温向下箭头表示最低温。使用display.setCursor(x, y)精确控制文字位置。void displayWeatherData() { display.clearDisplay(); display.setCursor(0, 0); display.print(Min: ); display.print(tempMin); display.print( C); display.setCursor(0, 16); // Y坐标下移16像素开始新的一行 display.print(Max: ); display.print(tempMax); display.print( C); display.setCursor(0, 32); display.print(Updated:); // 显示更新时间 // ... 显示时间戳 display.display(); }避免屏幕烧屏OLED屏长时间显示静态内容可能导致像素老化不均烧屏。可以在每次更新数据时轻微移动一下显示内容的位置例如在几个像素范围内随机偏移或者定期如每10次更新完全清屏一次再显示。增加视觉反馈在连接WiFi或获取数据时可以在屏幕上显示“Connecting...”或“Fetching...”让用户知道设备正在工作。获取成功后可以短暂地让屏幕全亮再恢复显示作为一种完成提示。6. 供电、外壳与进阶玩法6.1 稳定供电方案选择这个小设备功耗很低但需要持续供电。有几种方案USB电源适配器直连最简单可靠。找一个手机充电头和一根USB-C线插上即可。这是桌面摆放时的最佳选择。移动电源供电如果你想把它放在没有插座的地方或者需要便携可以连接一个小容量的移动电源。ESP8266在深度睡眠模式下功耗可低至几十微安配合大容量移动电源续航可达数周甚至数月。电池充电管理模块如果想做成完全无线的可以接一块锂电池如3.7V 18650或LiPo电池并搭配一个TP4056之类的充电管理模块。Wemos D1 mini的输入电压范围是3.3V-5V单节锂电池满电4.2V需要降压到3.3V使用或者使用两节电池串联再降压到5V。这增加了复杂度。实操心得如果使用移动电源有些移动电源在输出电流很小时会自动关机。为了解决这个问题可以在程序中定期比如每半小时让ESP8266的某个GPIO引脚输出一个短暂的高电平连接一个较大的电阻到地制造一个小的电流脉冲“欺骗”移动电源保持输出。或者选择带有“小电流模式”或“持续供电模式”的移动电源。6.2 创意外壳设计与制作一个精致的外壳能让项目从“开发板堆”升级为“产品”。这里提供几个思路3D打印这是最定制化的方案。你可以使用Fusion 360、Tinkercad等软件自己设计或者去Thingiverse等网站搜索“Wemos D1 mini case”、“OLED enclosure”等关键词下载现成的模型修改后打印。设计时注意留出USB接口、复位按钮和屏幕的开口。现成改造利用现有的小盒子如薄荷糖铁盒、小型塑料药盒。用尺子量好内部空间和屏幕位置用手电钻或烙铁开孔。内部可以用热熔胶或蓝丁胶固定电路板。亚克力拼接购买几块薄亚克力板用激光切割或手工雕刻出底板、侧板和面板然后用螺丝或胶水组装。这种方案看起来很有极客风。6.3 功能扩展与进阶想法基础功能实现后你可以考虑以下扩展让这个小设备变得更强大增加更多天气信息除了温度还可以显示天气状况晴、雨、雪图标、湿度、风速、日出日落时间等。这需要修改API请求参数和屏幕显示逻辑。Open-Meteo API提供了丰富的数据。实现深度睡眠以省电如果使用电池供电省电是关键。ESP8266可以进入深度睡眠模式此时仅RTC电路和少量内存工作功耗极低。你可以让设备每小时唤醒一次连接WiFi获取数据显示几分钟后再进入睡眠。代码中需要使用ESP.deepSleep(sleep_time_in_microseconds)函数。添加物理按钮增加一个按钮短按切换显示信息如今天天气/明天天气长按强制刷新数据。接入智能家居平台将获取到的温度数据通过MQTT协议发送到Home Assistant或Node-RED等平台作为环境传感器使用触发其他自动化流程。更换显示方式如果你觉得0.66英寸太小可以换用I2C接口的更大尺寸OLED屏如0.96寸、1.3寸只需修改屏幕初始化参数和显示坐标即可主控板不变。7. 常见问题与故障排除实录在制作和调试过程中你几乎一定会遇到下面这些问题。我把我的踩坑记录和解决方法整理出来希望能帮你快速通关。7.1 编译与上传问题问题编译时提示“fatal error: Adafruit_SSD1306.h: No such file or directory”原因IDE找不到OLED屏幕驱动库。解决确保你已经按照第3.2节所述正确安装了针对Wemos OLED Shield的特殊版本库并且卸载了可能冲突的通用Adafruit SSD1306库。检查项目-加载库中是否已列出该库。问题上传代码时IDE一直显示“正在连接...”或上传失败原因板子型号选择错误、端口选择错误、或板子未进入上传模式。解决在工具-开发板中选择正确的型号如“LOLIN(WEMOS) D1 R2 mini”。在工具-端口中选择正确的串口在Windows设备管理器中查看COM号在Mac/Linux上是/dev/cu.usbserial-xxx或/dev/ttyUSB0等。确保USB线连接良好。在上传代码前先按住板子上的“FLASH”或“BOOT”按钮不放再按一下“RST”复位按钮然后松开“RST”最后松开“FLASH”按钮使板子进入固件上传模式。对于有些版本的D1 mini可能需要先按住FLASH再上电。7.2 网络与数据获取问题问题串口监视器显示一直“Connecting to WiFi...”或连接失败原因WiFi SSID或密码错误路由器设置了MAC地址过滤或仅允许特定设备连接信号太弱。解决仔细检查代码中的ssid和password确保没有多余空格大小写正确。查看路由器后台确认是否有访问限制。将设备靠近路由器试试。在代码中增加重试机制和超时判断连接失败后延迟一段时间再重试。问题能连上WiFi但获取天气数据失败HTTP返回错误码原因API请求URL错误网络不稳定服务器问题。解决将代码中的url字符串完整地复制到电脑浏览器的地址栏中直接访问。如果浏览器能返回正确的JSON数据说明URL和参数没问题。如果浏览器报错则检查经纬度、时区格式是否正确。在代码中打印出完整的URL确认拼接无误。检查open-meteo.com等服务状态是否正常。问题获取数据成功但屏幕显示乱码或温度值明显不对如-127原因JSON数据解析逻辑错误提取了错误的字段或数组索引。解决这是最关键的一步调试。务必打开串口监视器查看fetchWeatherData()函数中打印出的原始payloadJSON字符串。将这个JSON复制到在线的JSON格式化工具如 jsonformatter.org中使其结构清晰可见。然后逐层对照修改代码中的doc[路径][到][数据]部分确保路径与API返回的实际数据结构完全匹配。特别注意数组的索引[0]通常是今天[1]是明天。7.3 屏幕显示问题问题屏幕一片漆黑没有任何显示原因供电不足I2C地址错误屏幕初始化失败屏幕本身损坏。解决使用万用表测量VCC引脚电压是否在3.3V左右。检查代码中display.begin()函数的I2C地址。常见的OLED地址是0x3C也可能是0x3D。可以写一个简单的I2C扫描程序来探测地址。确认Adafruit_SSD1306对象初始化时屏幕尺寸参数是否正确对于64x48的屏可能是Adafruit_SSD1306 display(64, 48, Wire, -1);具体参考你安装的库的示例。问题屏幕有显示但内容错乱、重叠或闪烁原因显示缓冲区未正确清空display.display()调用时机不当程序逻辑导致刷新过快。解决确保在绘制新内容前调用了display.clearDisplay()。确保所有绘制命令print,drawLine等执行完毕后再调用display.display()一次性更新到屏幕。在loop()中更新屏幕后要有足够的延迟如delay(1000)避免刷新过快导致视觉闪烁和程序卡死。7.4 稳定性与功耗问题问题设备运行一段时间后死机或无响应原因可能是看门狗定时器WatchDog Timer, WDT超时复位内存泄漏网络操作阻塞。解决在长时间运行的循环或任务中适时调用ESP.wdtFeed()或yield()函数来喂狗防止WDT复位。避免在循环中动态分配大量内存如频繁创建String对象使用局部变量或全局缓冲区。为网络操作设置超时client.setTimeout()或http.setTimeout()防止因服务器无响应而永久阻塞。问题使用电池供电时续航极短原因未启用低功耗模式WiFi始终连接屏幕常亮。解决实现深度睡眠模式见6.3节。这是最有效的省电手段。在每次获取数据并显示后主动断开WiFi连接WiFi.disconnect(true)。考虑在显示一段时间后如30秒关闭屏幕背光如果支持或清屏。这个微型天气预报器项目麻雀虽小五脏俱全它串联起了硬件连接、嵌入式编程、网络通信和数据解析等多个物联网开发的关键技能点。从最初的屏幕乱码、网络连不上到后来稳定地每小时为我报告明日气温这个过程里调试串口日志、分析JSON数据、优化电源管理的每一步都让我对ESP8266这片小小的芯片有了更实在的理解。它现在安静地立在我的显示器旁边不再只是一堆零件而是一个真正有用的工具。如果你也做出来了试着给它设计个漂亮的外壳或者增加一两个你需要的功能那种亲手让想法变成实物的成就感才是DIY最大的乐趣。