基于ESP32-C3与SHT31打造双模低功耗桌面气象站

ESP32-C3低功耗设计SHT31
于 2026-05-28 13:25:20 修改
·本内容遵循CC 4.0 BY-SA版权协议

1. 项目概述:打造你的桌面级智能气象站

几年前,我还在用手机App查看天气,直到一次露营,手机没电让我彻底抓瞎。从那时起,我就琢磨着做一个不依赖手机、能独立运行且足够省电的微型气象站。经过几轮迭代,最终定型为这个基于ESP32-C3和SHT31的方案。它不仅仅是一个显示温湿度的“电子表”,而是一个融合了本地传感、网络数据获取和智能功耗管理的完整物联网节点。

这个项目的核心价值在于其“双模”设计思路。在室内模式下,它就是一个高精度的温湿度计,依靠本地的SHT31传感器工作,响应快、数据准。切换到室外模式,它则化身为一个迷你气象台,通过WiFi从全球最可靠的气象数据源之一——挪威气象研究所(met.no)的免费API——获取你所在位置的实时天气、预报、风速、气压等信息,并显示在1.8英寸的OLED屏幕上。更重要的是,为了让它能塞进任何角落并用一块小电池驱动数周,我为其设计了深度睡眠机制:闲置20秒后自动进入“冬眠”,功耗降至微安级,仅需轻按按钮即可瞬间唤醒,这背后是ESP32-C3芯片强大的低功耗管理能力在支撑。

无论你是刚接触Arduino和物联网的新手,想通过一个完整项目练手,还是有一定经验的开发者,希望找到一个结构清晰、兼顾传感器应用、网络通信和电源管理的参考案例,这个项目都能提供一条明确的路径。你最终得到的,不仅是一个实用的桌面摆件,更是一套可复用于其他低功耗物联网设备(如土壤监测、门窗感应器)的代码框架和设计思想。

2. 核心硬件选型与设计思路解析

为什么是ESP32-C3和SHT31这个组合?这背后是一系列针对成本、性能、功耗和易用性的权衡。市面上MCU和传感器选择众多,但这个搭配在当下这个时间点,对于个人DIY项目而言,性价比和完成度几乎是最优解。

2.1 微控制器:ESP32-C3为何是“甜点”

ESP32系列芯片选择很多,经典的ESP32、ESP32-S3性能更强,但ESP32-C3对于本项目来说是“恰到好处”的甜点。首先,它基于RISC-V架构,功耗控制天生有优势。在深度睡眠模式下,其电流可以低至5μA左右,这对于依赖电池供电的设备是决定性因素。其次,它集成了WiFi和蓝牙5.0(本项目虽未用蓝牙,但为未来扩展留了可能),单芯片解决通信问题,避免了外接模块的复杂度和额外功耗。最后,也是很重要的一点,ESP32-C3的“SuperMini”开发板尺寸极小(约24mm x 18mm),引脚间距友好,非常适合这种追求紧凑的作品。相比更早的ESP8266,ESP32-C3的内存更大,支持更现代的TLS加密,连接像met.no这样的HTTPS API更加稳定可靠。

注意:购买ESP32-C3开发板时,请确认其USB转串口芯片型号。CH340/CH341芯片在主流操作系统上驱动兼容性较好,而某些使用非标芯片的板子可能在Mac或Linux上遇到识别问题,给新手带来不必要的麻烦。

2.2 传感器:SHT31的精度与稳定性

温湿度传感器从几块钱的DHT11到上百元的工业级产品都有。我选择SHT31,是因为它在精度、稳定性、响应速度和价格之间取得了很好的平衡。SHT31是Sensirion公司的明星产品,典型精度可达±2%RH(湿度)和±0.3°C(温度),并且具有优异的长期稳定性。它采用标准的I2C接口,与ESP32-C3的通信只需两根线(SDA, SCL),接线简单,且Arduino社区有成熟稳定的库(Adafruit_SHT31)支持,几乎无需操心底层驱动。

为什么不选更便宜的DHT11?DHT11的湿度精度在±5%RH,温度±2°C,且响应慢,在快速变化的环境中数据滞后明显。对于希望获得可靠环境参考数据的项目,这点投资是值得的。为什么不选更贵的SHT40?SHT40精度更高,但价格也上了一个台阶。对于室内环境监测,SHT31的精度已经绰绰有余,是性价比之选。

2.3 显示与交互:OLED屏与单按钮哲学

显示部分选用1.8英寸、128x160分辨率的TFT屏(驱动芯片多为ST7735)。这个尺寸在桌面上清晰可见,又不会显得笨重。选择TFT而非单色OLED,主要是为了更好的视觉效果,可以显示图标(如晴天、雨云)和更多信息(温度曲线)。ST7735有成熟的GFX库(如TFT_eSPI或LovyanGFX)支持,图形渲染效率高。

整个设备的交互遵循“极简”哲学:仅一个按钮。短按用于切换室内/室外模式,长按用于进入深度睡眠(或从睡眠中唤醒)。这种设计减少了硬件复杂度,也迫使软件逻辑必须清晰——所有状态切换都围绕这一个输入展开。按钮选择6x6mm的贴片轻触开关,便于焊接在紧凑的板子上或固定在壳体上。

2.4 供电设计:小电池的长续航秘诀

供电部分是低功耗设计的核心。我选择了一块从废弃电子烟中拆出的450mAh 3.7V锂离子电池。这种电池体积小、易获得,但关键是如何用好它。ESP32-C3的工作电压范围是3.0V-3.6V,而锂电池满电4.2V,放完电约3.0V。因此,一个高效的降压稳压电路(LDO或DC-DC)是必须的,大多数ESP32-C3开发板已经集成了这个电路。

长续航的秘诀在于软件与硬件的协同:1. 在不操作时,迅速降低屏幕背光至几乎看不见的2%;2. 在无任何操作20秒后,让MCU进入深度睡眠(Deep Sleep)。此时,只有RTC(实时时钟)模块和用于唤醒的GPIO(连接按钮)保持极低功耗的运行,整机电流可降至50μA以下。按此计算,450mAh的电池理论上可待机超过一年(450mAh / 0.05mA ≈ 9000小时)。当然,每次唤醒联网获取天气数据会消耗较多电量(约几十到一百毫安,持续几秒),但得益于高效的睡眠,即使每天唤醒几十次,续航数周也毫无压力。

3. 电路连接与实体搭建详解

“没有PCB”是本项目倡导的灵活性的体现,但也对动手能力提出了要求。正确的连接是后续一切工作的基础,这里我会详细拆解每一步,并分享让焊接更可靠、布局更美观的技巧。

3.1 引脚定义与接线图

首先,我们必须明确每个元件需要连接到ESP32-C3的哪个引脚。以下是经过验证的稳定连接方案:

元件 引脚/接口 连接到 ESP32-C3 说明
SHT31 传感器 VCC 3.3V 绝对禁止接5V,会烧毁传感器
GND GND 共地
SDA GPIO4 (默认I2C SDA) 数据线,需上拉电阻
SCL GPIO5 (默认I2C SCL) 时钟线,需上拉电阻
ST7735 TFT屏 VCC 3.3V 屏幕电源
GND GND 共地
SCLK GPIO6 SPI时钟
MOSI GPIO7 SPI数据主出从入
RESET GPIO10 复位引脚,低电平有效
DC (A0) GPIO8 数据/命令选择
CS GPIO2 片选,低电平有效
BLK 3.3V (或通过GPIO控制) 背光,常亮或PWM调光
轻触开关 一端 GPIO9 配置为上拉输入
另一端 GND 按下时,GPIO9被拉低
锂电池 正极 开发板 BAT+ 或 VIN 注意板子是否有充放电管理
负极 开发板 GND

重要提示:I2C总线(SDA, SCL)上通常需要连接上拉电阻(通常为4.7kΩ或10kΩ)到3.3V,以确保信号稳定。许多ESP32开发板内部已启用上拉,但若通信不稳定,请务必在外部焊接这两个电阻。

3.2 焊接与布局实战技巧

对于这种“飞线”项目,焊接质量和布局合理性直接决定了成品的稳定性和美观度。

  1. 先规划,后焊接:在动手前,用纸笔画一个简单的布局图。将ESP32-C3板子放在中心,屏幕和传感器围绕其布置。考虑好走线路径,尽量让电源线(3V3, GND)和信号线分开,避免平行长距离走线以减少干扰。
  2. 使用合适的线材:如果想做“裸露线材美学”风格,可以使用不同颜色的单芯硬线(如AWG22),它们能自己保持形状,营造出一种结构感。如果想最终放进外壳,则使用多股细丝的硅胶线,它们更柔软,便于在壳内排布。
  3. 焊接顺序:建议先焊接GND(地线),建立一个共同的参考点。然后焊接3.3V电源线。最后焊接信号线(SDA, SCL, MOSI等)。焊接每个点时,确保烙铁温度足够(约350°C),使用含松芯的焊锡,让焊点饱满呈圆锥形,避免虚焊或冷焊。
  4. 关于电池:如果电池没有保护板,强烈建议外接一个锂电池保护板(带过充、过放、短路保护)。这能极大提高安全性,防止电池因过度放电而损坏。将保护板串联在电池和ESP32开发板的电源输入之间。

3.3 功能测试与排错

全部连接完成后,先不要急着组装或放入外壳,进行上电前测试和初步功能测试。

  1. 上电前检查:用万用表蜂鸣档,仔细检查3.3V和GND之间是否短路。确认电池极性没有接反。
  2. 上电观察:连接电池或USB线。观察ESP32-C3板上的电源指示灯是否正常亮起。触摸主要芯片(ESP32-C3、稳压芯片)是否异常发烫。如有异常,立即断电。
  3. 串口信息:通过USB连接电脑,打开Arduino IDE的串口监视器,设置波特率为115200。如果程序已烧录,你应该能看到启动日志,包括连接WiFi的尝试、传感器初始化成功与否等信息。这是最直接的调试窗口。

如果屏幕不亮,检查背光(BLK)是否已供电。如果传感器读数失败,检查I2C地址(SHT31默认0x44)是否正确,并用I2C扫描程序确认总线是否能发现设备。

4. 软件环境配置与固件深度定制

硬件是骨架,软件是灵魂。这部分我们将深入代码,不仅告诉你“怎么填”,更解释“为什么这么填”,以及如何根据你的需求进行个性化调整。

4.1 开发环境与核心库安装

首先,确保你的Arduino IDE已安装ESP32开发板支持。

  1. 打开Arduino IDE,进入“文件”->“首选项”,在“附加开发板管理器网址”中输入:https://espressif.github.io/arduino-esp32/package_esp32_index.json
  2. 打开“工具”->“开发板”->“开发板管理器”,搜索“esp32”,安装“Espressif Systems”提供的ESP32开发板包。
  3. 安装完成后,在“工具”->“开发板”中选择“ESP32C3 Dev Module”。根据你的具体板子,可能需要调整“Flash Size”和“Partition Scheme”。

接下来,安装必要的库。打开“项目”->“加载库”->“管理库...”,搜索并安装以下库:

  • Adafruit SHT31 Library:用于驱动SHT31传感器。
  • LovyanGFX:一个非常高效且功能强大的图形库,支持ST7735等多种屏幕。它比传统的Adafruit_GFX + ST7735组合性能更好,功能更丰富。
  • 此外,项目可能还需要 ArduinoJson(用于解析API返回的天气数据)和 WiFi(ESP32内置)等库。

4.2 核心配置文件 settings.h 逐行解读

项目代码中最重要的就是settings.h文件,它是设备连接世界的“身份证”和“住址簿”。

CPP
// WiFi 配置 - 设备的网络通行证
constexpr char SSID[] = "Your_WiFi_SSID"; // 你的WiFi名称,区分大小写
constexpr char PASSWORD[] = "Your_WiFi_Password"; // WiFi密码
 
// 地理位置配置 - 获取天气数据的坐标
constexpr double LATITUDE = 39.9042; // 你的纬度,例如北京
constexpr double LONGITUDE = 116.4074; // 你的经度
 
// 显示与UI配置
constexpr int SCREEN_WIDTH = 160; // 屏幕宽度(像素)
constexpr int SCREEN_HEIGHT = 128; // 屏幕高度(像素)
constexpr int DEFAULT_BRIGHTNESS = 255; // 初始亮度 (0-255)
constexpr int SLEEP_BRIGHTNESS = 5; // 休眠前调暗的亮度 (约2%)
 
// 功耗管理配置
constexpr unsigned long ACTIVE_TIMEOUT_MS = 5000; // 5秒后调暗亮度
constexpr unsigned long SLEEP_TIMEOUT_MS = 20000; // 20秒后进入深度睡眠

配置要点与避坑指南:

  • WiFi加密类型:确保你的路由器使用的是WPA2或WPA3加密。古老的WEP加密可能无法连接。
  • 坐标精度:经纬度建议使用小数点后4-6位,这足以精确定位到一个街区。在Google Maps上右键点击你的位置,选择“这是什么?”即可看到坐标。
  • 亮度设置SLEEP_BRIGHTNESS设为5(约最大亮度的2%)而不是0,是因为有些屏幕在亮度为0时可能会完全关闭,难以判断设备是否仍在运行。保留微光是一个更好的用户体验设计。
  • 超时时间ACTIVE_TIMEOUT_MSSLEEP_TIMEOUT_MS可以根据你的使用习惯调整。如果你希望它常亮更久,就增大这两个值。

4.3 主程序逻辑与模式切换剖析

主程序(*.ino文件)的结构体现了状态机思想,清晰处理了设备的不同工作状态。

CPP
void loop() {
unsigned long currentMillis = millis(); // 获取当前运行时间
 
// 1. 检查按钮状态,处理模式切换和睡眠唤醒
handleButton();
 
// 2. 根据当前模式更新显示内容
if (currentMode == MODE_INDOOR) {
updateIndoorDisplay(); // 读取SHT31并显示
} else if (currentMode == MODE_OUTDOOR) {
// 检查是否需要更新网络天气数据(例如每10分钟一次)
if (currentMillis - lastWeatherUpdate > WEATHER_UPDATE_INTERVAL) {
fetchWeatherData(); // 连接WiFi,调用API,解析数据
lastWeatherUpdate = currentMillis;
}
updateOutdoorDisplay(); // 显示获取到的天气信息
}
 
// 3. 闲置超时管理
if (currentMillis - lastActiveTime > ACTIVE_TIMEOUT_MS) {
dimDisplay(); // 调暗屏幕
}
if (currentMillis - lastActiveTime > SLEEP_TIMEOUT_MS) {
enterDeepSleep(); // 进入深度睡眠
}
}

handleButton()函数的细节:这里需要实现防抖(Debounce)和长短按识别。简单的防抖可以在检测到按键按下后,延迟20-50毫秒再次读取引脚状态,确认按下有效。长短按识别则通过计时实现:按下时间超过500毫秒视为长按,触发睡眠;短于500毫秒视为短按,触发模式切换。

fetchWeatherData()函数的关键这是与met.no API交互的核心。你需要使用WiFiClientSecure建立安全的HTTPS连接,向类似 https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=YOUR_LAT&lon=YOUR_LON 的地址发送GET请求。服务器返回的是JSON格式的数据,你需要使用ArduinoJson库来解析出你需要的字段,如air_temperature(气温)、relative_humidity(湿度)、wind_speed(风速)、symbol_code(天气图标代码,如clearsky_day)。

实操心得:解析JSON时,务必先在串口监视器打印出完整的API响应,然后用ArduinoJson Assistant(在线工具)帮你生成解析代码。这能避免因JSON结构理解错误导致的程序崩溃。另外,对网络请求一定要设置超时(例如10秒),并做好异常处理,防止一次网络失败导致设备长时间卡死。

5. 低功耗与电源管理深度优化

让一个联网设备靠小电池长期工作,是本项目的一大挑战和亮点。低功耗设计是一个系统工程,需要硬件、固件和软件策略协同。

5.1 ESP32-C3的睡眠模式解析

ESP32-C3提供了多种睡眠模式,本项目使用的是最省电的深度睡眠模式(Deep Sleep)

  • 工作原理:在此模式下,CPU、大部分RAM以及所有由APB_CLK时钟驱动的外设都会断电。仅保留RTC控制器、RTC外设(如GPIO、UART)以及RTC快速内存(一小块用于保存唤醒后恢复运行的数据)处于工作状态。
  • 唤醒源:可以被多种方式唤醒,如定时器、外部引脚(EXT0/EXT1)、触摸引脚等。本项目采用外部引脚(GPIO)唤醒,即通过按钮将指定的GPIO(如GPIO9)拉低来唤醒芯片。
  • 功耗表现:深度睡眠下,整机电流(包括必要的稳压电路损耗)可以控制在50μA以下,甚至更低。

在代码中,进入深度睡眠非常简单:

CPP
esp_deep_sleep_enable_gpio_wakeup(BIT(GPIO_NUM_9), ESP_GPIO_WAKEUP_LEVEL_LOW);
esp_deep_sleep_start();

第一行代码配置了从深度睡眠中被唤醒的条件:当GPIO9被拉低(即按钮按下)时唤醒。第二行代码则让芯片立即进入深度睡眠。

5.2 外设功耗控制策略

MCU睡了,如果外设还在耗电,那就前功尽弃。

  1. 屏幕功耗:在进入深度睡眠前,除了调暗背光,最好通过代码将屏幕的复位引脚(RESET)拉低,或者通过片选(CS)将其彻底置于非活动状态。有些库提供了sleep()powerOff()函数。最彻底的方法是直接断开屏幕的电源,但这需要额外的MOSFET开关电路,增加了复杂度。对于本项目,将背光调到极暗并让MCU进入深度睡眠后,屏幕本身的功耗已经微乎其微。
  2. 传感器功耗:SHT31传感器在空闲时功耗本身就很低(约2μA)。我们可以在进入睡眠前,通过I2C发送一个命令让其进入休眠模式(如果支持),或者直接忽略,其功耗在整体中占比很小。
  3. WiFi与射频:这是耗电大户。在每次完成网络数据获取后,务必调用WiFi.disconnect(true)WiFi.mode(WIFI_OFF)来彻底关闭WiFi射频。这比仅仅断开连接要省电得多。

5.3 软件层面的省电技巧

  1. 快速工作,尽快睡觉:主循环loop()要高效。读取传感器、更新显示、检查网络这些操作,完成后如果没有其他事情,不要让程序空转。可以适当加入delay(10)让出CPU时间,但更好的做法是使用非阻塞式定时器,让MCU在等待期间可以处理其他任务或进入轻睡眠。
  2. 降低CPU频率:ESP32-C3默认运行在160MHz。在不需要高速处理时(例如仅更新显示时),可以通过setCpuFrequencyMhz(80)将频率降至80MHz,能显著降低动态功耗。
  3. 优化网络请求
    • 减少请求频率:天气数据变化不会那么快,将更新间隔设置为10分钟、甚至30分钟是完全合理的。
    • 精简数据包:请求API时,可以只请求你需要的字段(如果API支持),减少数据传输量和解析时间。
    • 重试策略:网络请求失败后,不要立即无限重试。实现一个指数退避的重试机制,比如失败后等待1秒重试,再失败等2秒,最多重试3次后就放弃,等待下一个周期。这能避免因网络临时故障导致设备长时间处于高功耗的联网状态。

6. 外壳设计与个性化制作

一个精致的项目离不开得体的“外衣”。外壳不仅保护内部电路,更是作品质感的体现。这里提供三种思路,从简到繁。

6.1 方案A:3D打印现成外壳

这是最快捷的方式。你可以在开源模型社区(如Thingiverse, Printables)搜索“ESP32-C3 enclosure”或“mini weather station”,找到适配你屏幕尺寸和主板的外壳模型。下载STL文件后,用3D打印机(PLA或PETG材料)即可打出。通常这类外壳由前盖、后盖和可能的内部支架组成,通过螺丝或卡扣固定。

打印与后处理建议

  • 层高:选择0.2mm层高以获得较好的表面质量。
  • 填充率:15%-20%即可保证强度,又节省材料和时间。
  • 支撑:如果外壳有悬空部分(如按钮孔上方的顶盖),需要生成支撑。
  • 打磨与上色:打印完成后,可以用砂纸打磨去除层纹,然后喷上底漆和喜欢的颜色漆,质感会提升好几个档次。

6.2 方案B:利用现成容器改造

充满创意且低成本的方法。一个透明的亚克力小盒子、一个复古的胶卷盒、甚至一个精心挑选的茶叶罐,都可以成为气象站的家。

  1. 测量与规划:精确测量内部元件的尺寸和位置。用铅笔在容器上标记出屏幕开窗、按钮孔和充电孔的位置。
  2. 开孔:对于塑料或薄木片,可以用手钻或电钻配合合适尺寸的钻头开孔。对于亚克力或玻璃,则需要使用专门的开孔器,或者送到有激光切割服务的地方进行精准切割。
  3. 固定与布局:内部元件可以使用热熔胶、双面泡棉胶或尼龙柱进行固定。注意将电池放置在容易更换的位置,并确保所有连接线不会被挤压。

6.3 方案C:裸露线材的工业美学

如果你喜欢硬核的、赛博朋克风格,完全可以不做外壳,将电路本身作为视觉主体。

  1. 线材整理:使用不同颜色的单芯硬线,并精心规划走线路径,让电源线、地线、信号线平行且整齐地排列,形成一种“电路雕塑”的美感。
  2. 结构强化:可以用一小块洞洞板(Perfboard)作为“基板”,将ESP32-C3、屏幕和传感器用铜柱固定在上面,飞线则在背面进行。这样既稳固,又保持了开放式的视觉效果。
  3. 底座制作:为这个“电路雕塑”设计一个简洁的底座,可以用一块木头、一块亚克力板,甚至是一个手机支架,让它可以稳定地立在桌面上。

无论选择哪种方案,都要考虑散热(虽然本项目发热很小)、防尘以及可能的电池更换口。一个用心设计的外壳,会让整个项目的完成度和满足感倍增。

7. 进阶功能扩展与创意玩法

基础功能实现后,这个气象站平台还有巨大的潜力可供挖掘。这里分享几个我实践过或构思过的扩展方向。

7.1 数据上传与可视化

让数据不再局限于本地屏幕,上传到云端进行记录和可视化。

  • 平台选择:国内可用阿里云物联网平台、OneNET;国外可用Blynk、ThingSpeak或自建的MQTT服务器(如EMQX)。
  • 实现方法:在fetchWeatherData()函数中,除了解析数据显示,再添加一段代码,将传感器数据(室内温湿度)和获取的天气数据打包成一个JSON字符串,通过MQTT协议或HTTP POST请求发送到你的云平台。
  • 可视化:在云平台或通过Grafana等工具,创建仪表盘,绘制温湿度变化曲线图,显示历史最高/最低值等。你甚至可以设置报警规则,当室内温度超过30°C时,给你手机发送一条通知。

7.2 增加更多传感器

ESP32-C3的GPIO和接口资源还有富余,可以轻松集成更多传感器。

  • 大气压强传感器(BMP280/BME280):BME280本身也包含温湿度传感器,且能测量气压。气压数据对于天气预测(气压下降通常预示天气转坏)很有价值。你可以同时连接SHT31和BME280,对比两者的温湿度读数,或者用BME280替换SHT31。
  • 空气质量传感器(SGP30, CCS811):监测室内CO2和TVOC(总挥发性有机物)含量,让气象站升级为环境质量监测站。
  • 光照传感器(BH1750):感知环境光强度,可以用于自动调节屏幕亮度。

添加新传感器时,需要注意I2C地址冲突(每个设备需要有唯一地址),并考虑功耗。通常这些传感器都有低功耗模式。

7.3 优化用户交互

单按钮虽然简洁,但功能切换有限。可以考虑增加交互方式。

  • 旋转编码器:替换或增加一个旋转编码器,可以用于更流畅地切换显示页面、调整参数(如亮度、刷新频率)。
  • 光线感应自动亮度:增加一个光敏电阻或数字环境光传感器,实现屏幕亮度随环境光自动调节,更智能也更省电。
  • 蜂鸣器提示:增加一个无源蜂鸣器,在按钮操作、数据更新完成或异常报警时提供声音反馈。

这些扩展不仅增加了功能,更让你深入理解如何在一个资源有限的嵌入式系统中进行外设管理、任务调度和功耗权衡,是极好的学习过程。

8. 常见问题排查与维护指南

即使按照指南操作,也可能会遇到一些“坑”。这里汇总了我和其他制作者遇到过的一些典型问题及其解决方法。

8.1 编译与上传问题

问题现象 可能原因 解决方案
编译错误:fatal error: Adafruit_SHT31.h: No such file or directory 库未安装或安装路径不正确 在Arduino IDE中通过库管理器重新安装。检查#include <>语句拼写是否正确。
上传失败:Failed to connect to ESP32: Timed out waiting for packet header 1. 板子型号选错
2. 串口被占用
3. 板子未进入下载模式
1. 确认选择“ESP32C3 Dev Module”。
2. 关闭其他可能占用串口的软件(如串口监视器)。
3. 对于某些板子,需要按住“BOOT”或“IO0”按钮再按一下“RST”进入下载模式,然后点击上传。
上传后程序不运行,屏幕无显示 1. 引脚定义错误
2. 屏幕初始化失败
3. 电源不足
1. 仔细核对settings.h和接线图中的每一个引脚号。
2. 打开串口监视器,查看启动日志,是否有屏幕初始化错误。
3. 尝试使用USB供电,排除电池电量不足或接触不良的问题。

8.2 硬件与连接问题

问题现象 可能原因 解决方案
屏幕花屏、闪烁或显示不全 1. SPI时钟频率过高
2. 电源干扰
3. 接线虚焊或过长
1. 在屏幕初始化代码中尝试降低SPI频率(如从27MHz降到20MHz)。
2. 在屏幕的VCC和GND之间并联一个100μF的电解电容,滤除电源噪声。
3. 检查并重新焊接屏幕排线,尤其是时钟和数据线。
SHT31传感器读数全为0或NaN 1. I2C地址错误
2. 上拉电阻缺失
3. 传感器损坏
1. 运行一个I2C扫描程序,确认总线上设备的地址。SHT31默认是0x44,也有可能是0x45。
2. 在SDA和SCL线上各接一个4.7kΩ电阻到3.3V。
3. 更换传感器测试。
按钮反应不灵或误触发 1. 按键消抖未做好
2. 上拉电阻未启用
1. 在代码中实现软件消抖逻辑(检测到按下后延迟20ms再判断)。
2. 确认按钮连接的GPIO在代码中设置为INPUT_PULLUP模式。
电池续航远低于预期 1. 深度睡眠未成功进入
2. 屏幕背光未关闭
3. WiFi未彻底关闭
1. 用万用表测量深度睡眠时的整机电流,应低于100μA。检查enterDeepSleep()函数是否被正确调用。
2. 确保在睡眠前调暗或关闭屏幕背光。
3. 在进入睡眠前,调用WiFi.disconnect(true); WiFi.mode(WIFI_OFF);

8.3 软件与网络问题

问题现象 可能原因 解决方案
无法连接到WiFi 1. SSID/密码错误
2. 路由器设置了MAC过滤或隐藏SSID
3. 信号太弱
1. 仔细检查settings.h中的配置,注意大小写和特殊字符。
2. 检查路由器设置,或将ESP32的MAC地址加入白名单。
3. 将设备靠近路由器测试。
无法从met.no获取天气数据 1. 网络连接问题
2. API请求格式错误或坐标无效
3. 服务器暂时不可用
1. 先在串口监视器查看WiFi是否连接成功。
2. 将浏览器中生成的API URL(含你的坐标)粘贴到串口输出中,看是否能返回JSON。检查坐标值是否在合理范围(纬度-90~90,经度-180~180)。
3. 等待一段时间再试,或检查met.no的服务状态页面。
设备运行一段时间后死机或重启 1. 内存泄漏
2. 看门狗超时
3. 电源波动
1. 检查代码中动态内存分配(如String类的大量拼接),尽量使用静态缓冲区或StringReserve
2. 在长时间循环或网络操作中,适时调用yield()delay(0)喂狗。
3. 在电池供电时,确保电池电压充足,或在电源输入端并联一个大电容(如1000μF)缓冲。

长期维护建议:定期检查电池电压,当续航明显缩短时考虑更换电池。如果设备放置在窗边或阳台,注意防潮和灰尘。软件上,可以关注met.no API的更新(虽然其v2.0版本非常稳定),以及所使用的Arduino核心库和第三方库的更新,适时升级以获得更好的稳定性和新功能。