跳转到内容

功耗优化

功耗优化

本节介绍优化电子纸显示项目功耗的详细技术。虽然深度睡眠提供了最大的节能效果,但几项额外的优化可以进一步将电池续航从数月延长到一年以上。完成本节后,你将能够:

  • 测量和分析 ESP32 + 电子纸系统的功耗预算
  • 对每个功耗域实施硬件和软件优化
  • 计算不同配置下的预期电池续航
  • 在功能和功耗之间做出权衡决策

开始本节前,请确保:

  • 理解深度睡眠配置(参见 02-08)
  • 了解电池管理基础(参见 02-09)
  • 可使用具有 µA 分辨率的万用表
ESP32 功耗分解
┌─────────────────────────────────────────────────────┐
│ 总功耗 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
│ │ WiFi 发送│ │ WiFi 接收│ │ CPU + 外设 │ │
│ │ ~200-260 │ │ ~100-130 │ │ ~20-50 mA │ │
│ │ mA │ │ mA │ │ │ │
│ └──────────┘ └──────────┘ └───────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
│ │ 电子纸 │ │ 电子纸 │ │ 深度睡眠 │ │
│ │ 刷新 │ │ 空闲 │ │ ~5-50 µA │ │
│ │ ~20-30mA │ │ ~0 µA │ │ │ │
│ └──────────┘ └──────────┘ └───────────────────┘ │
└─────────────────────────────────────────────────────┘

各状态的系统电流消耗:

状态电流持续时间每周期能耗
WiFi 连接120 mA3 秒0.100 mAh
MQTT 数据交换80 mA1 秒0.022 mAh
显示刷新25 mA3 秒0.021 mAh
深度睡眠0.01 mA(10 µA)3593 秒0.010 mAh
每周期合计3600 秒0.153 mAh

显示刷新消耗的能量比 WiFi 连接还少! 优化 WiFi 连接时间对电池续航影响最大。

刷新间隔周期数/年能耗/年所需电池(1年目标)
每 30 分钟17,5202,680 mAh~3,000 mAh
每 1 小时8,7601,340 mAh~1,500 mAh
每 2 小时4,380670 mAh~800 mAh
每 6 小时1,460223 mAh~300 mAh
每 12 小时730112 mAh~150 mAh
每天一次36556 mAh~100 mAh

WiFi 连接是最大的能量消耗者。积极优化:

优化前(标准连接):

// ~5-8 秒,120 mA 平均
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}

优化后(快速连接):

// 减少连接尝试——不需要完美 RSSI
WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE);
WiFi.setAutoReconnect(false);
WiFi.setSleep(WIFI_PS_MIN_MODEM); // 空闲时调制解调器睡眠
WiFi.begin(ssid, password);
// 5 秒后超时——稍后重试比耗尽电池更好
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 10) {
delay(500);
attempts++;
}
if (WiFi.status() != WL_CONNECTED) {
// 跳过此周期——使用缓存数据
Serial.println("WiFi 超时,跳过此周期");
goToSleep();
return;
}

优化要点:设置严格连接超时,跳过而非无限重试。

进入深度睡眠前,明确禁用所有外设:

void prepareForSleep() {
// 禁用 WiFi 硬件
client.disconnect();
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
// 关闭显示屏电源
display.powerOff(); // GxEPD2 方法
// 将所有 GPIO 设置为安全状态
pinMode(EPD_CS, INPUT_PULLDOWN);
pinMode(EPD_DC, INPUT_PULLDOWN);
pinMode(EPD_RST, INPUT_PULLDOWN);
// 如果不用于电池监测,禁用 ADC
// adc_power_off();
// 关闭蓝牙
btStop();
}
void goToSleep() {
prepareForSleep();
esp_sleep_enable_timer_wakeup(SLEEP_INTERVAL_US);
esp_deep_sleep_start();
}

优化显示更新序列:

void updateDisplayOptimized() {
unsigned long start = millis();
// 快速初始化——尽可能跳过完整上电序列
display.init(4000000, true, 10); // 更高 SPI 速度
// 如果可用,使用局部刷新(主要时间节省)
// 某些显示屏支持仅更新屏幕的一部分
// 最小化绘图操作
display.fillScreen(GxEPD_WHITE);
// 仅绘制最小内容
display.setFont(&FreeMonoBold12pt7b);
display.setCursor(5, 20);
display.print(temperature);
// 单次 display() 调用——不是多次
display.display();
unsigned long elapsed = millis() - start;
Serial.print("显示更新时间:");
Serial.print(elapsed);
Serial.println("ms");
}
GPIO 状态电流泄漏建议
高电平输出~0 µA✅ 用于 CS 取消选中
低电平输出~0 µA✅ 控制引脚安全
输入下拉~1 µA✅ 未使用引脚
输入浮空~10-50 µA❌ 避免——不可预测
// 休眠的安全 GPIO 配置
void configureGpioForSleep() {
const int pins[] = {5, 17, 16, 4, 23, 18}; // 所有使用的引脚
for (int pin : pins) {
gpio_set_direction((gpio_num_t)pin, GPIO_MODE_INPUT);
gpio_set_pull_mode((gpio_num_t)pin, GPIO_PULLDOWN_ONLY);
}
}

更高的 SPI 速度减少活动时间:

// 标准速度
display.init(115200); // ~115kHz SPI — 3-5 秒刷新
// 优化速度
display.init(4000000); // ~4MHz SPI — 1-2 秒刷新
// 最大安全速度(取决于接线质量)
display.init(8000000); // ~8MHz SPI — ~1 秒刷新(需要短线)

注意:非常高的 SPI 速度可能在长线缆下导致通信错误。在每个速度下测试稳定性。

电池性能在低温下降级。相应调整调度:

void configureSleepInterval() {
// 从传感器读取温度
float temp = readTemperature();
unsigned long sleepUs;
if (temp < 0) {
// 非常冷——电池降级,减少更新频率
sleepUs = 6 * 3600 * 1000000ULL; // 每 6 小时
} else if (temp < 10) {
// 冷——中度降级
sleepUs = 3 * 3600 * 1000000ULL; // 每 3 小时
} else {
// 正常温度
sleepUs = 1 * 3600 * 1000000ULL; // 每 1 小时
}
esp_sleep_enable_timer_wakeup(sleepUs);
}
void setup() {
// 1. 快速启动——无不必要的延迟
Serial.begin(115200);
// 2. 快速 WiFi 连接
WiFi.mode(WIFI_STA);
WiFi.setSleep(WIFI_PS_MIN_MODEM);
// 3. 带严格超时的连接
WiFi.begin(ssid, password);
unsigned long timeout = millis() + 5000;
while (WiFi.status() != WL_CONNECTED && millis() < timeout) {
delay(100); // 短延迟——不是 500ms
}
if (WiFi.status() == WL_CONNECTED) {
// 4. 快速 MQTT 交换
fetchAndDisplayData(); // 总共 ~2 秒
}
// 5. 干净关机
prepareForSleep();
// 6. 进入深度睡眠
esp_sleep_enable_timer_wakeup(SLEEP_INTERVAL_US);
esp_deep_sleep_start();
}
Terminal window
# 用万用表测量(串联连接)
# 1. 将万用表设置为 DC mA 档
# 2. 断开 USB 电源
# 3. 将万用表连接在电池和 ESP32 之间
# 4. 记录各阶段的值
# 睡眠模式下 µA 测量:
# 1. 切换到 µA 档
# 2. 确保 ESP32 已进入深度睡眠(等待 5 秒)
# 3. 记录稳定读数
典型结果(所有优化启用后):
活动阶段: ~120 mA 持续 ~5 秒 (0.167 mAh)
睡眠阶段: ~10 µA 持续 3595 秒(0.010 mAh)
每周期总计: 0.177 mAh
每日: 4.25 mAh
电池续航: ~282 天(1200 mAh 电池)
  • 活动阶段时间低于 10 秒
  • 深度睡眠电流低于 50 µA
  • WiFi 在睡眠前正确断开
  • 即使快速启动,显示屏也能成功更新
  • 电池续航估算与实际测量相差在 20% 以内

问题 1:睡眠电流过高(>100 µA)

Section titled “问题 1:睡眠电流过高(>100 µA)”

症状:

  • 电池消耗比预期快
  • 万用表显示睡眠时 >100 µA

检查清单:

  • 任何外部外设在睡眠期间是否仍通电?
  • WiFi 是否完全禁用?(WiFi.mode(WIFI_OFF))
  • 所有 GPIO 是否处于安全状态?(无浮空输入)
  • 电压调节器是否已断电?
  • 电子纸显示屏电源是否关闭?(display.powerOff())

症状:

  • 活动阶段 >15 秒
  • WiFi 连接时间 >5 秒

解决方案:

  • 减少连接超时
  • 如果 WiFi 较慢,使用缓存数据
  • 提高显示刷新的 SPI 速度
  • 使用快速启动技术
技术节能工作量优先级
深度睡眠定时器~99.9%低⭐⭐⭐
WiFi 超时(最长 5 秒)~50% WiFi 能耗低⭐⭐⭐
睡眠前断开 WiFi~10 µA 节能低⭐⭐⭐
GPIO 安全状态~10-50 µA中⭐⭐
提高 SPI 速度~50% 显示时间中⭐⭐
禁用蓝牙~20 mA(如果启用)低⭐⭐⭐
降低 CPU 频率~10 mA 活动中⭐
  1. WiFi 连接主导活动功耗——首先优化连接时间
  2. 总活动时间应少于 5 秒以达到最佳电池续航
  3. 深度睡眠电流应低于 20 µA,配置正确
  4. 每微安都很重要——睡眠中 10 µA 的差异可以改变电池续航数周
  5. 启用所有优化后:1200 mAh 电池每小时更新可实现约 1 年电池续航

正在开发商业 IoT 产品?

我们提供 ESP32 ODM 定制设计与制造服务。从原型到量产——编写这套教程的团队,可以和你一起实现。

联系我们 →