You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP32C6外部IO触发深度睡眠唤醒实现问题咨询

ESP32-C6 深度睡眠IO唤醒问题排查与优化方案

一、当前代码问题分析

  • 内部上下拉失效:深度睡眠默认关闭RTC外设电源域,INPUT_PULLUP设置的内部上拉在睡眠时会失效,导致引脚处于浮空状态,无法稳定检测电平变化。
  • 唤醒条件逻辑缺陷:代码依赖digitalRead()的当前状态配置唤醒条件,但浮空状态下读取结果不可靠,会导致唤醒条件配置错误。
  • 缺少电源域控制:未调用esp_sleep_pd_config管理RTC外设电源状态,无法在保留内部上下拉和低功耗之间做选择。

二、esp_sleep_pd_config 用法说明

该函数用于配置睡眠期间各电源域的供电状态,原型:

void esp_sleep_pd_config(esp_sleep_pd_domain_t domain, esp_sleep_pd_option_t option);

核心参数说明:

  • domain:针对IO唤醒,需指定ESP_PD_DOMAIN_RTC_PERIPH(包含GPIO上下拉、RTC GPIO等外设的电源域)
  • option:
    • ESP_PD_OPTION_OFF:关闭电源域,功耗最低,但该域所有外设功能失效(如内部上下拉)
    • ESP_PD_OPTION_ON:保持电源域开启,保留外设功能,但功耗略高
    • ESP_PD_OPTION_AUTO:系统自动决策,深度睡眠下默认关闭RTC_PERIPH

三、低功耗最优方案选择

针对你的长期开关电平监测、低功耗优先需求,推荐两种方案:

方案1:外接上下拉电阻(最低功耗)

  • 硬件:在GPIO4与VCC间接10kΩ上拉电阻(开关接地时),或GPIO4与GND间接下拉电阻(开关接VCC时)
  • 软件配置:
    esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
    
  • 优势:深度睡眠电流可低至几μA,功耗最优
  • 劣势:需要额外硬件电阻

方案2:保留内部上下拉(无额外硬件)

  • 软件配置:
    esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
    
  • 优势:无需额外硬件,代码实现简单
  • 劣势:深度睡眠功耗略高(比方案1高10-20μA左右)

四、修复后的代码示例

以下是基于方案2(无外接电阻)的修复代码:

#include <Arduino.h>
#include <esp_sleep.h>

#define WAKEUP_PIN 4
uint64_t gpio_pin_mask = (1ULL << WAKEUP_PIN);
RTC_DATA_ATTR uint8_t last_btn_state = 0; // 用RTC内存保存上次引脚状态,睡眠不丢失

void setup() {
  Serial.begin(115200);
  delay(500); // 等待串口初始化完成

  // 配置GPIO为输入上拉
  pinMode(WAKEUP_PIN, INPUT_PULLUP);

  // 检查唤醒原因
  esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause();
  if (wakeup_reason == ESP_SLEEP_WAKEUP_EXT1) {
    Serial.println("唤醒:检测到引脚电平变化");
    // 此处添加WiFi连接、POST请求逻辑
  } else {
    Serial.println("首次启动/非IO唤醒");
    last_btn_state = digitalRead(WAKEUP_PIN);
  }

  // 保持RTC外设域开启,保留内部上下拉
  esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);

  // 根据上次状态设置唤醒条件,检测电平变化
  if (last_btn_state == HIGH) {
    Serial.println("设置唤醒条件:引脚变低");
    esp_sleep_enable_ext1_wakeup(gpio_pin_mask, ESP_EXT1_WAKEUP_ANY_LOW);
  } else {
    Serial.println("设置唤醒条件:引脚变高");
    esp_sleep_enable_ext1_wakeup(gpio_pin_mask, ESP_EXT1_WAKEUP_ANY_HIGH);
  }

  Serial.println("进入深度睡眠...");
  delay(100); // 确保串口输出完成
  esp_deep_sleep_start();
}

void loop() {
  // 深度睡眠后不会执行到此处,可留空
}

代码关键点

  • RTC_DATA_ATTR修饰变量:将状态保存在RTC内存中,深度睡眠后不丢失,避免重启时因引脚浮空读取错误状态。
  • 唤醒原因判断:区分首次启动和IO唤醒,方便后续业务逻辑扩展。
  • 明确电源域配置:确保内部上下拉在睡眠时持续生效。

五、额外注意事项

  • ESP32-C6的GPIO4属于RTC GPIO,支持EXT1唤醒且可通过RTC_PERIPH域保留上下拉功能。
  • 若选择方案1(外接电阻),需移除INPUT_PULLUP配置,并设置ESP_PD_OPTION_OFF以最大化降低功耗。
  • 串口初始化后添加延迟,避免唤醒时串口未就绪导致输出丢失。

内容的提问来源于stack exchange,提问作者DaveL17

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 17:35:17