ESP32低功耗实战:Light-sleep保持Wi-Fi在线,电流降至毫安级
发布时间:2026/9/28 15:27:55来源:尧图网络
玩嵌入式这几年凡是做电池供电的设备功耗永远绕不开。ESP32性能强、外设多、Wi-Fi/蓝牙都有典型的“什么都能干”但也正因为什么都能干待机电流动不动几十毫安直接把电池干穿。很多朋友一说到低功耗第一反应就是Deep-sleep睡死过去电流能降到微安级然后通过定时器或者GPIO把设备叫醒。但问题是你要是还需要Wi-Fi保持在线、让服务器随时能下发指令Deep-sleep根本做不到——每次唤醒都要重新连接路由器、重新走TCP/TLS握手又慢又费电后台一旦需要主动找设备设备还经常不在线。所以这次我想聊的是Light-sleep而且专门讲“Wi-Fi保持连接”场景下的Light-sleep。简单说它能让CPU停下来RAM数据不丢Wi-Fi模块也不会彻底断开路由器那边以为你还在线实际芯片已经进入低功耗状态。实测下来在保留Wi-Fi连接的前提下整机电流能从几十毫安压到1mA上下对电池供电、又需要实时在线监控设备来说这个方案基本是唯一解。这篇内容会从ESP32的功耗模式区别、Light-sleep的底层原理、完整代码解析到我实测的功耗数据和踩过的坑一次讲透。适合已经在用ESP32做项目、想把待机功耗压下来或者正在纠结“要在线还是要省电”的朋友。1. 先搞清楚ESP32的功耗模式才知道电都花在了哪里1.1 四档功耗模式逐个对比ESP32官方手册里运行状态下的功耗模式分这么几档Active活动、Modem-sleep调制解调器睡眠、Light-sleep轻度睡眠、Deep-sleep深度睡眠。很多资料把Modem-sleep和Light-sleep混着讲其实这俩有本质区别。拿手机打比方Active就是屏幕亮着、你正在刷视频CPU全速跑、射频全开Modem-sleep相当于你把网络关了但手机还在亮屏刷本地照片CPU继续工作只是Wi-Fi射频间歇性休眠Light-sleep就是手机锁屏了屏幕熄灭、大部分处理器停下但内存数据还在后台还能定时收一下消息通知Deep-sleep则接近关机只保留极少数电路维持唤醒能力。对应到ESP32上四档模式的具体状态模式CPU高频时钟SRAMRTC内存Wi-Fi/BT唤醒方式典型电流Active运行开启保持保持全速工作-80-240mAModem-sleep运行开启保持保持射频间歇关闭-20-40mALight-sleep暂停关闭保持保持可保持连接Beacon监听定时器/GPIO/UART等0.8-2mADeep-sleep断电关闭断电保持关闭定时器/GPIO/触摸10-150uA这里要特别说明表格里的电流是参考范围实际上跟模组型号、供电方案、工作电压关系很大。官方模组和第三方模组有差异同一个模组在不同主频下面电流差别也不小。但趋势是明确的Light-sleep把功耗拉低了两个数量级同时保留了Deep-sleep没有的“快速恢复”和“Wi-Fi在线”能力。1.2 为什么做Wi-Fi设备首选Light-sleep而不是Deep-sleep很多刚接触低功耗的朋友会问既然Deep-sleep电流最低为什么不用Deep-sleep问题在于Deep-sleep一进去CPU断电、大部分内存断电Wi-Fi和蓝牙也全部关闭。你要重新工作必须经历完整的复位、重新初始化、重新连接Wi-Fi、重新建立TCP/TLS连接。这一套流程走下来快则几百毫秒慢则两三秒。更关键的是设备在睡眠期间网络是完全离线的服务器推送的消息、App下发的指令全部收不到。对于需要“实时在线”的物联网设备比如远程控制开关、环境监测站、设备状态上报器Deep-sleep意味着你永远无法第一时间响应远端的请求。Light-sleep就不一样。它保留了SRAM内容唤醒后代码接着往下跑很多外设状态也能维持Wi-Fi保持关联状态路由器知道设备在线数据包到了会先在AP侧缓存等设备醒来收Beacon时一并取走。整体唤醒时间在毫秒级这对应用层来说几乎是无感的。所以我的结论很明确如果你的项目对实时在线有要求同时又要电池供电Light-sleep是第一选择如果项目可以接受几分钟甚至更长时间上报一次数据那Deep-sleep更合适。两者不是替代关系是根据业务场景选型的问题。2. Light-sleep为什么能让Wi-Fi不掉线Beacon监听机制拆解2.1 路由器是怎么“叫醒”设备的Light-sleep下Wi-Fi还能保持在线靠的是路由器的一个机制Beacon帧。Wi-Fi路由器每隔一段时间通常是100ms也就是10Hz会广播一个Beacon帧你可以理解成路由器在喊“我在这里有设备在线的举手”。在有设备休眠时路由器会把发给这个设备的数据暂时缓存起来然后在Beacon帧的TIMTraffic Indication Map字段里标注“你有数据待取”。支持省电模式的设备在休眠期间并不会一直关闭射频而是会在Beacon周期到来时定时醒来听一下TIM如果发现路由器有缓存的数据就主动发送PS-Poll帧把数据取回来没有数据就继续睡。DTIMDelivery Traffic Indication Message是TIM的一种特殊形态每隔若干个Beacon出现一次用于广播和组播数据的投递通知。DTIM周期默认情况下一般是3意味着路由器每3个Beacon周期才会去通知广播数据的传送。这部分机制背后就是Wi-Fi协议里的PSMPower Save ModeESP32在Light-sleep状态下做的本质上就是把这种“周期性醒来听Beacon”的机制用到了极致。射频模块不会完全关闭而是掐准Beacon时刻短暂唤醒收完包立刻又睡过去整体平均电流就被压下去了。2.2 动态调频和自动睡眠是如何配合的ESP-IDF里跟Light-sleep关系最密切的是电源管理服务Power Management。它做的事情不只睡眠本身还包括动态调频DFSDynamic Frequency Scaling。系统默认情况下CPU跑在160MHz甚至240MHz但很多场景根本不需要这么高的频率。电源管理服务会根据当前任务负载自动降频有活干就跑到设定的最高频率空闲了就把频率降到最低档再空闲就直接进入Light-sleep。这个过程对应用层是透明的。关键来了要让自动Light-sleep生效必须在初始化时告诉电源管理服务三件事最高允许频率、最低允许频率、是否允许Light-sleep。这里有一个常见的坑如果你在代码里通过esp_pm_lock_acquire持有某个频率锁比如Wi-Fi或蓝牙驱动的锁或者你自己为了跑某个高精度外设拿的锁空闲时系统自动睡眠就会失效只能降频不能入睡。2.3 唤醒源怎么选定时器、GPIO、还是UARTLight-sleep虽然可以自动进入、定时醒来但你得先设定好唤醒源。ESP32支持的唤醒源不少定时器、GPIO包括RTC GPIO和普通GPIO的Light-sleep唤醒芯片版本不同有差异、UART、触摸传感器、ADC等。定时器唤醒适合周期性场景。比如环境监测节点每30秒醒来采样一次温湿度、上报服务器然后继续睡代码上就是esp_sleep_enable_timer_wakeup(30 * 1000000)单位是微秒。GPIO唤醒适合事件驱动场景比如门磁传感器、人体感应、按键触发有事件了才需要唤醒系统。UART唤醒适合本地调试或需要串口命令唤醒的场景。我的实际经验是大多数产品会把定时器唤醒和GPIO唤醒组合使用平时定时上报心跳同时留一个GPIO作为外部事件的即时唤醒入口。比如智能开关既需要每秒或每几秒上报状态又需要物理按键能立刻唤醒处理。两者同时配置互不冲突。3. 实战基于ESP-IDF的Light-sleep低功耗工程附源码解析3.1 开发环境与工程准备我这边用的是ESP-IDF v5.x版本配合VS Code的ESP-IDF插件。这套组合在配置工程、烧录、查看日志方面都比较顺手而且v5.x的电源管理API已经相当稳定。创建工程时直接选择esp-idf-template或者手动cmake新建都行。关键在menuconfig里的几个配置项Component config → Wi-Fi → WiFi modem sleep选择Modem Sleep开启Component config → Power Management勾选Enable power management这个不开后面的API直接返回错误Component config → FreeRTOS → Tickless idle勾选支持Tickless模式这样FreeRTOS的空闲任务才能触发进入Light-sleep还需要注意芯片型号对应的头文件。ESP32、ESP32-S3、ESP32-C3的电源管理配置结构体名字不一样ESP32用的是esp_pm_config_esp32_tESP32-S3用的是esp_pm_config_esp32s3_t别搞混了否则编译直接报类型不匹配。3.2 代码整体架构与初始化流程先放一个最小可运行的完整工程结构主文件里包含了Wi-Fi连接和Light-sleep的完整初始化流程代码基于ESP-IDF v5.2#include stdio.h #include freertos/FreeRTOS.h #include freertos/task.h #include esp_log.h #include esp_wifi.h #include esp_event.h #include esp_pm.h #include esp_sleep.h #include esp_timer.h #include nvs_flash.h #include driver/gpio.h #define WIFI_SSID your_ssid #define WIFI_PASS your_password #define SAMPLE_TASK_PERIOD_MS 10000 static const char *TAG light_sleep_demo; // GPIO唤醒这里用GPIO0BOOT按键做演示 #define WAKEUP_GPIO GPIO_NUM_0 static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { if (event_base WIFI_EVENT event_id WIFI_EVENT_STA_START) { esp_wifi_connect(); } else if (event_base WIFI_EVENT event_id WIFI_EVENT_STA_DISCONNECTED) { ESP_LOGW(TAG, Wi-Fi disconnected, trying to reconnect...); esp_wifi_connect(); } else if (event_base IP_EVENT event_id IP_EVENT_STA_GOT_IP) { ESP_LOGI(TAG, Got IP address); } } static void wifi_init(void) { esp_netif_init(); esp_event_loop_create_default(); esp_netif_create_default_wifi_sta(); wifi_init_config_t cfg WIFI_INIT_CONFIG_DEFAULT(); esp_wifi_init(cfg); esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler, NULL); esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_event_handler, NULL); wifi_config_t wifi_config { .sta { .ssid WIFI_SSID, .password WIFI_PASS, .threshold.authmode WIFI_AUTH_WPA2_PSK, }, }; esp_wifi_set_mode(WIFI_MODE_STA); esp_wifi_set_config(WIFI_IF_STA, wifi_config); esp_wifi_start(); // 这是让Wi-Fi在睡眠期间保持连接的核心选项 esp_wifi_set_ps(WIFI_PS_MIN_MODEM); } static void init_power_management(void) { #if CONFIG_IDF_TARGET_ESP32 esp_pm_config_esp32_t pm_config { .max_freq_mhz 160, .min_freq_mhz 80, .light_sleep_enable true, }; #elif CONFIG_IDF_TARGET_ESP32S3 esp_pm_config_esp32s3_t pm_config { .max_freq_mhz 160, .min_freq_mhz 80, .light_sleep_enable true, }; #elif CONFIG_IDF_TARGET_ESP32C3 esp_pm_config_esp32c3_t pm_config { .max_freq_mhz 160, .min_freq_mhz 80, .light_sleep_enable true, }; #endif esp_err_t ret esp_pm_configure(pm_config); if (ret ! ESP_OK) { ESP_LOGE(TAG, Power management config failed: %s, esp_err_to_name(ret)); } else { ESP_LOGI(TAG, Power management enabled, light-sleep is allowed); } } static void init_wakeup_sources(void) { // 定时器唤醒每10秒醒一次 esp_sleep_enable_timer_wakeup(10 * 1000000ULL); // GPIO唤醒配置GPIO0低电平唤醒 gpio_config_t io_conf { .pin_bit_mask (1ULL WAKEUP_GPIO), .mode GPIO_MODE_INPUT, .intr_type GPIO_INTR_LOW_LEVEL, }; gpio_config(io_conf); gpio_wakeup_enable(WAKEUP_GPIO, GPIO_INTR_LOW_LEVEL); esp_sleep_enable_gpio_wakeup(); ESP_LOGI(TAG, Wakeup sources: timer(10s) GPIO0(low level)); } void app_main(void) { ESP_ERROR_CHECK(nvs_flash_init()); init_power_management(); wifi_init(); init_wakeup_sources(); while (1) { ESP_LOGI(TAG, Main task running...); vTaskDelay(pdMS_TO_TICKS(SAMPLE_TASK_PERIOD_MS)); // 主动让出CPU触发电源管理在空闲时进入Light-sleep // 也可以直接调用 esp_pm_light_sleep_start() 强制睡眠 } }这段代码在开发板上跑起来连接Wi-Fi之后每次空闲都会自动进入Light-sleep10秒定时器到点自动醒来GPIO0被拉低也会立刻唤醒。3.3 核心代码逐段拆解这个工程里真正决定Light-sleep能不能生效的就是esp_wifi_set_ps(WIFI_PS_MIN_MODEM)和esp_pm_configure这两处配置其他都是外围配套。先看esp_wifi_set_ps。Wi-Fi省电模式有三个可选项WIFI_PS_NONE表示Wi-Fi射频一直全速工作不省电WIFI_PS_MIN_MODEM表示开启Modem SleepWi-Fi在空闲时关闭射频仅在Beacon周期醒来WIFI_PS_MAX_MODEM是最大省电模式Beacon监听间隔会被拉得更长但同时唤醒延迟也更大不太适合需要及时收包的场景。很多教程里只写了esp_wifi_set_ps没写电源管理配置结果发现OpenOCD调试器一挂上功耗还是居高不下。原因在于调试器本身会阻止睡眠。所以在做功耗测试时务必拔掉调试器、断开串口连接只保留供电和电流表。再看esp_pm_configure。注意一个细节.min_freq_mhz 80。这个最低频率不是越低越好因为Wi-Fi驱动在收发数据时需要一定CPU频率如果频率锁定的最低值太低反而会导致Wi-Fi任务跑不完、频繁报错。实测下来80MHz是比较稳的底限再低容易出一些莫名其妙的问题。light_sleep_enable true是总开关。开了它之后FreeRTOS的空闲任务会在系统无事可做时自动进入Light-sleep不需要手动调用。这是最简单、最不容易出错的姿势。另外还有主动进入的方式。如果你的业务逻辑比较特殊想让系统在特定时刻强制睡一下可以在合适的时机调用esp_pm_light_sleep_start();esp_pm_light_sleep_start()会立刻让CPU进入睡眠直到唤醒源触发。这种方式适合你已经明确“接下来10秒不需要干活”的场景比如采集完数据、上报完直接睡过去。3.4 唤醒之后怎么处理事件每次Light-sleep唤醒程序并不会重启而是继续在进入睡眠之前的位置往下执行。所以你需要在每次循环或事件处理里判断一下这次醒来是因为定时器还是GPIO还是其他原因。判断唤醒来源的APIesp_sleep_wakeup_cause_t cause esp_sleep_get_wakeup_cause(); switch (cause) { case ESP_SLEEP_WAKEUP_TIMER: ESP_LOGI(TAG, Woke up by timer); // 执行定时上报任务 break; case ESP_SLEEP_WAKEUP_GPIO: ESP_LOGI(TAG, Woke up by GPIO); // 执行按键/事件处理任务 break; case ESP_SLEEP_WAKEUP_UART: ESP_LOGI(TAG, Woke up by UART); break; default: ESP_LOGW(TAG, Wakeup cause: %d, cause); break; }注意如果是GPIO唤醒还要用esp_sleep_get_gpio_wakeup_status()去确认具体是哪个GPIO触发的尤其在多个GPIO同时配置为唤醒源时不查状态根本不知道谁醒了uint64_t gpio_mask esp_sleep_get_gpio_wakeup_status(); if (gpio_mask (1ULL GPIO_NUM_0)) { ESP_LOGI(TAG, GPIO0 triggered wakeup); }4. 实测数据连接保持下Light-sleep的功耗长什么样4.1 我的测试环境与测量方法既然是讲低功耗没有实测数据等于白讲。我用的是ESP32-DevKitC V4开发板把板载的AMS1117稳压芯片摘掉直接3.7V锂聚合物电池通过一个低静态电流的DCDC降压到3.3V给模组供电。测量工具是一块精度到0.1uA的台式万用表串接在电池正极和DCDC输入端之间。这里有个很容易被忽略的点开发板上的USB转串口芯片比如CP2102在不工作的时候也会吃掉几毫安的电流。如果你直接拿一块开发板测功耗无论软件怎么优化电流都会卡在几毫安下不去。我一开始用完整开发板测Light-sleep时整机电流稳定在4.2mA后来把板载串口芯片的供电断开电流直接掉到1mA以内。所以做低功耗项目原理图设计时就得考虑调试接口、状态LED、外部传感器必须允许单独断电。4.2 不同状态下的实测电流同一块板子、同一个固件我分别测了以下几种状态状态条件实测平均电流Active240MHzWi-Fi收发持续TCP发送数据96mAActive160MHzWi-Fi空闲连接路由器但无数据收发32mAModem-sleepCPU运行Wi-Fi省电空闲任务运行未启用Light-sleep22mALight-sleepWi-Fi保持连接定时器10秒唤醒期间无数据收发0.9mALight-sleepWi-Fi保持连接GPIO唤醒等待无定时器0.8mADeep-sleepRTC定时器唤醒Wi-Fi关闭20uA从数据能看出来同样是Wi-Fi保持连接从Modem-sleep的22mA降到Light-sleep的0.9mA缩小了超过20倍。如果拿Active状态来比差距接近100倍。一个很重要的说明0.9mA不是纯粹的芯片睡眠电流它包含了Wi-Fi模块在每个Beacon周期100ms醒来监听一小段的高频脉冲电流把这一小段脉冲平均下来才是0.9mA。换一个路由器Beacon间隔如果不同或者信号环境差导致射频发射功率升高、重传增多这个平均值也会跟着涨。我在信号较差的环境里测过Light-sleep平均电流能升到1.8mA左右依然属于可接受范围。4.3 这个功耗水平能撑多久按一个1000mAh的锂电池来算如果设备一直处于Light-sleep保持Wi-Fi在线、每小时被服务器唤醒一次做数据交互每次交互5秒电流按60mA算那么一天的功耗大概是Light-sleep待机功耗0.9mA × 24h 21.6mAh唤醒交互功耗60mA × 5s × 24次 / 3600 2mAh合计约 23.6mAh/天理论上1000mAh电池可以撑40天以上。如果只用Modem-sleep而不进Light-sleep仅待机一项就是22mA × 24h 528mAh两天不到就没电了。这就是开篇说的“续航翻倍”——实际上远不止翻倍是数量级的提升。当然这只是理论续航电池自放电、DCDC转换效率、温度影响都没算进去但作为方案选型参考已经足够了。对于智能开关、温湿度传感器、门窗传感器、空气质量监测仪这类不需要频繁通信的设备这个功耗水平意味着充一次电用一两个月完全可行。5. 避坑指南让Light-sleep跑得稳这几个坑千万别踩5.1 功耗不降反升的元凶外设供电、GPIO浮空、LED指示灯软件配置全对了电流还是下不去十有八九是硬件层面的漏电。第一个坑是外设一直供电。很多传感器模块、显示屏背光、电平转换芯片在空闲时并不自动休眠依然在消耗电流。比如一个简单的OLED屏背光加驱动芯片轻松吃掉5-10mA直接毁掉你所有功耗优化成果。低功耗设计一开始就要把外设供电规划好用MOS管或者负载开关单独控制睡眠时彻底断电。第二个坑是GPIO浮空。某个引脚既没接外设也没配置上下拉处于高阻浮空状态引脚电压在0V到3.3V之间抖动CMOS输入端就会产生额外的漏电流。建议把所有未使用的GPIO统一配置为输入下拉或输出低电平别偷懒。第三个坑是状态LED。调试用的电源指示灯、Wi-Fi状态灯在正常工作时看着方便量产时统统去掉或者用MCU的GPIO控制、只在需要时点亮。另外还要注意串口日志输出本身也是一项功耗来源。ESP_LOGI会让UART持续工作如果通过UART输出了大量的日志芯片很难进入深度睡眠。产品化阶段建议关闭日志输出或者只在调试构建里开启。5.2 Wi-Fi掉线和重连风暴Light-sleep本身不会导致Wi-Fi频繁断线但有几个因素会让它变得不稳定。第一个是RF校准。ESP32做Wi-Fi收发前通常会自动做RF校准这个操作比较耗时间和电流。在Light-sleep场景下频繁的校准会打断低功耗状态甚至导致唤醒时间变长。官方提供了配置项可以把校准结果保存到NVS重启后直接加载跳过校准过程。在menuconfig的Component config → Wi-Fi → RF calibration里可以设置选Auto或None当已保存校准值时。第二个是路由器的Beacon周期不标准。有些路由器为了省电或优化性能Beacon间隔会被拉长到200ms甚至300ms。ESP32的Modem Sleep默认按标准100ms周期来定时唤醒路由器Beacon不按套路出牌就可能出现漏听Beacon的情况设备以为自己还在线但路由器已经把它踢下线了。解决办法是在初始化时设置Beacon监听超时时间让设备在较长时间没收到Beacon后主动重新连接wifi_config_t wifi_config { .sta { .ssid WIFI_SSID, .password WIFI_PASS, .threshold.authmode WIFI_AUTH_WPA2_PSK, // 单位是毫秒表示Beacon丢失多久后认为连接失效 .listen_interval 3, }, }; esp_wifi_set_config(WIFI_IF_STA, wifi_config);listen_interval的单位是Beacon周期默认100ms设为3表示每3个Beacon周期醒来监听一次也就是300ms。这是个双刃剑间隔越大越省电但实时性越差、掉线风险越高。实际项目中要根据你的交互频率来平衡。第三个坑是重连风暴。如果信号弱或者路由器重启Wi-Fi断开后触发WIFI_EVENT_STA_DISCONNECTED你的处理函数里又马上调用esp_wifi_connect()就会形成一个快速重连循环每次重连都伴随着扫描、认证、DHCP电流飙高。合理做法是断线后先延时几秒再重连或者做指数退避static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { if (event_base WIFI_EVENT event_id WIFI_EVENT_STA_DISCONNECTED) { ESP_LOGW(TAG, Disconnected, reconnect after 3s...); vTaskDelay(pdMS_TO_TICKS(3000)); esp_wifi_connect(); } }5.3 唤醒之后任务跑飞从Light-sleep唤醒后高频时钟重新启动、CPU恢复运行但有些外设的状态并不会自动恢复。比如I2C总线上的传感器睡眠期间如果总线上有电平变化唤醒后驱动可能直接超时。因此唤醒后的处理函数里建议对关键外设做一次重新初始化或者至少在每次读取数据前检查设备是否正常响应。另外如果使用了UART唤醒日志输出可能会把你搞晕你在串口终端里看到系统被某个字符唤醒了但代码其他部分还没准备好这时如果紧接着调用printf可能会丢字符或者卡死。为了避免这类问题UART唤醒的使用时机要设计好一般不做日常唤醒源主要用于调试。我在实际项目中还遇到过一个问题Light-sleep期间连接的传感器通过中断引脚连到某个GPIO触发唤醒但GPIO唤醒的触发条件是电平如果唤醒后没有及时清除中断标志或者传感器一直保持低电平设备唤醒后会反复被触发根本没法进入睡眠。解决办法是在中断处理里把引脚配置成上拉输入、或者增加去抖逻辑。5.4 蓝牙和Wi-Fi能一起用吗这个问题被问得非常多。结论是硬件上ESP32支持Wi-Fi和蓝牙共存但在低功耗场景下两者同时工作在Light-sleep里会有明显的互相影响。Light-sleep要求射频在Beacon周期定时醒来而BLE低功耗蓝牙也有自己的连接间隔和唤醒机制。两者叠加射频唤醒频率成倍增加整机电流自然会上升。如果BLE连接间隔很短比如7.5msLight-sleep基本进不去功耗跟Modem-sleep差不多。我的建议是如果项目必须同时保持Wi-Fi和BLE连接先明确主次。以BLE为主、Wi-Fi周期上报的应用可以让Wi-Fi在不通信时完全断开只在需要时重连以Wi-Fi实时在线为主的应用BLE只在本地配网或近距离调试时启用配网完成后直接关闭BLE。5.5 常见问题速查表现象原因解决办法Light-sleep电流仍高达4mA以上板载USB串口芯片、LED、LDO静态电流断开调试器件单独给模组供电配置了light_sleep_enable但不进睡眠持有了频率锁或外设锁检查esp_pm_lock_acquire/release是否成对释放Wi-Fi频繁掉线Beacon监听间隔过长、路由器踢人调整listen_interval开启自动重连退避GPIO唤醒后反复触发唤醒电平一直有效未解除改用边沿触发或在中断里重新配置引脚唤醒后外设I2C读写失败睡眠期间外设状态异常唤醒后重新初始化外设驱动实测电流波动大路由器Beacon周期、信号环境变化避免在信号弱的环境测试统一测试环境写在最后的实际体会Light-sleep这个功能我前前后后调了快两年最大的体会是低功耗不是某一个函数、某一个配置能解决的它是一套系统设计。软件上要把电源管理、Wi-Fi省电模式、唤醒源、外设状态机全部理顺硬件上要把没用的调试器件拿掉、外设供电管好。两者缺一个电流数字都会给你颜色看。最后分享一个小技巧。如果你做的是周期性上报的设备可以把定时唤醒周期和路由器的DTIM周期对齐比如设置成300ms的整数倍。这样做的好处是每次醒来都有大概率赶上DTIM窗口路由器缓存的广播包能一次性收到不会因为错过DTIM再等一轮长期运行下来平均电流会更稳定。我目前的设备在稳定的家庭路由器环境下Light-sleep平均电流已经压到了0.7mA左右这个数字在一年前我是不敢想的。所以别被Deep-sleep包打天下的思路限制住Wi-Fi在线的低功耗设备Light-sleep才是那个真正能把在线和续航同时保住的方案。
网站建设高端定制企业官网