第 9 篇:低功耗设计——18650 电池如何续航 3 个月

插座类设备插着电能活,但温湿度传感器、门磁、人体感应这些设备只能靠电池。ESP32 吃电大户,怎么让它省着吃?这篇教你把功耗从 80mA 压到 μA 级。


1. ESP32 各模式功耗实测

模式 功耗(ESP32-C3) CPU WiFi BLE 唤醒后状态
Active (WiFi TX) ~80mA 全速 发射 -
Active (接收) ~50mA 全速 接收 -
Modem Sleep ~3mA 运行 间歇唤醒 保持
Light Sleep ~0.8mA RAM 保持
Deep Sleep ~5μA 仅 RTC 保持

从 80mA → 5μA,差了 16000 倍。 关键在于:大部分时间让 ESP32 沉睡,需要时才醒来。


2. Deep Sleep 工作模式

时间线(周期 60 秒):

  0s    1s     2s           5s          60s   61s
  │ 醒来 │ WiFi连接 │ 读传感器+发MQTT │ 沉睡  │ 醒来  │
  │      │          │                 │       │       │
  ├──────┼──────────┼─────────────────┼───────┼───────┤
  │80mA  │  80mA   │      80mA       │ 5μA   │ 80mA  │

  平均功耗 ≈ (80mA × 5s + 5μA × 55s) / 60s ≈ 6.7mA

  2000mAh 电池续航 ≈ 2000 / 6.7 ≈ 298 小时 ≈ 12 天

3. 优化——从 12 天到 90 天

上面的方案只能撑 12 天,离 3 个月差得远。优化措施:

优化 1:减少 WiFi 连接时间

WiFi 连接是最大的耗电环节(5 秒中占了 4 秒)。ESP32 支持保存 PHY 校准数据:

// 首次连 WiFi 后保存 PHY 校准数据到 NVS
// 后续唤醒直接用,省去扫描信道的 2-3 秒
esp_wifi_set_storage(WIFI_STORAGE_FLASH);

优化后:WiFi 连接从 4s → 1.5s。

优化 2:增大上报间隔

60 秒 → 300 秒(5 分钟):

平均功耗 ≈ (80mA × 2.5s + 5μA × 297.5s) / 300s ≈ 0.67mA
续航 ≈ 2000 / 0.67 ≈ 2985 小时 ≈ 124 天 ≈ 4 个月 ✅

优化 3:用 ESP-NOW 替代 WiFi

如果不需要连互联网,只是把数据传到室内的网关(树莓派/另一块 ESP32),用 ESP-NOW 替代 WiFi:

  • ESP-NOW 连接:<100ms(WiFi 要 1-4s)
  • 无需 DHCP、DNS、TCP 握手

4. Deep Sleep 完整代码

#include "esp_sleep.h"
#include "esp_wifi.h"
#include "driver/rtc_io.h"

#define SLEEP_SECONDS  300   // 5 分钟醒来一次

RTC_DATA_ATTR static int boot_count = 0;  // 睡醒次数(RTC 内存保持)

void app_main(void) {
    boot_count++;
    ESP_LOGI("WAKE", "第 %d 次醒来", boot_count);

    // 1. 初始化 NVS(必须在 WiFi 之前)
    nvs_flash_init();

    // 2. 连接 WiFi
    wifi_init_sta_fast();  // 快速连接模式

    // 3. 连 MQTT → 读传感器 → 上报
    mqtt_app_start();
    float temp, humi;
    sht30_read(&temp, &humi);

    char payload[64];
    snprintf(payload, sizeof(payload),
        "{\"t\":%.1f,\"h\":%.1f,\"boot\":%d}", temp, humi, boot_count);
    esp_mqtt_client_publish(mqtt_client, "sensor/bedroom", payload, 0, 1, 0);

    // 4. 等待 MQTT 发送完毕(QoS 1 需要等 ACK)
    vTaskDelay(pdMS_TO_TICKS(2000));

    // 5. 断电前清理
    esp_mqtt_client_stop(mqtt_client);
    esp_mqtt_client_destroy(mqtt_client);
    esp_wifi_stop();
    esp_wifi_deinit();

    // 6. 设置定时唤醒 + 进入 Deep Sleep
    ESP_LOGI("SLEEP", "进入深度睡眠,%d 秒后醒来", SLEEP_SECONDS);
    esp_sleep_enable_timer_wakeup(SLEEP_SECONDS * 1000000ULL);
    esp_deep_sleep_start();
    // ← 这行之后,CPU 完全断电,醒来时从 app_main 重新开始
}

5. GPIO 唤醒——需要立即响应时

温湿度可以定时上报,但门磁不行——门一开必须立刻通知。

// 用 GPIO 唤醒 Deep Sleep
// GPIO_NUM_4 接门磁传感器(磁铁靠近=高电平,移开=低电平)

esp_sleep_enable_ext0_wakeup(GPIO_NUM_4, 0);  // 低电平唤醒

// 醒来后检查是哪种唤醒源
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
if (cause == ESP_SLEEP_WAKEUP_EXT0) {
    ESP_LOGI("WAKE", "门磁触发!有人在开门");
    // 立即连 WiFi 发告警
}

功耗:外部 GPIO 唤醒几乎不增加功耗(RTC GPIO 在 Deep Sleep 时仍在监听)。


6. 低功耗设计 Checklist

检查项 方法
用 Deep Sleep 而非 Light Sleep esp_deep_sleep_start()
WiFi 连上就发,发完就断 不要保持长连接
保存 PHY 校准数据 esp_wifi_set_storage(WIFI_STORAGE_FLASH)
关闭不用的外设 I2C/SPI 在读写完后 driver_uninstall
降低 CPU 频率 esp_pm_configure 最低到 40MHz
外设供电用 GPIO 控制 SHT30 的 VCC 接 GPIO → 不读时完全断电
减少 LED 闪烁 每 LED 灯耗电 2-5mA

传感器独立供电的技巧

// SHT30 的 VCC 不接 3.3V,接 GPIO5
gpio_set_direction(GPIO_NUM_5, GPIO_MODE_OUTPUT);
gpio_set_level(GPIO_NUM_5, 1);   // 给传感器上电
vTaskDelay(pdMS_TO_TICKS(100));  // 等传感器稳定
sht30_read(&t, &h);              // 读取
gpio_set_level(GPIO_NUM_5, 0);   // 传感器完全断电 → 省 0.5mA

下一篇:微信小程序入门——用 WebSocket 连接 MQTT,手机上看温湿度

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐