espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
12.93k stars 7.09k forks source link

I2C timeout after light sleep (IDFGH-13075) #14020

Open mycael opened 2 weeks ago

mycael commented 2 weeks ago

Answers checklist.

General issue report

Hello ! I am a beginner in the world of ESP and zigbee and I am building a CO2 measurement system using the zigbee network for home automation. I use an ESP32-C6 and an SCD40 component which works in I2C. So far, everything is working perfectly. The component joins the zigbee network well and regularly reports the values measured by the sensor and read by I2C. Since I would like the system to run on battery power, I want to use "light sleep" mode. I was inspired by the example provided in ESP-IDF: "Sleepy End Device Example".

In the _appmain function, I added the call to the function: esp_zb_power_save_init();

With this function identical to the example:

static esp_err_t esp_zb_power_save_init(void)
{
 esp_err_t rc = ESP_OK;
#ifdef CONFIG_PM_ENABLE
 int cur_cpu_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ;
 esp_pm_config_t pm_config = {
 .max_freq_mhz = cur_cpu_freq_mhz,
 .min_freq_mhz = cur_cpu_freq_mhz,
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
 .light_sleep_enable = true
#endif
 };
 rc = esp_pm_configure(&pm_config);
#endif
 return rc;
}

In the function _static void esp_zbtask(void *pvParameters):

/* initialize Zigbee stack */
 esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZED_CONFIG();
 esp_zb_sleep_enable(true);
 esp_zb_init(&zb_nwk_cfg);

In the function _void esp_zb_app_signal_handler(esp_zb_app_signal_t *signalstruct):

case ESP_ZB_COMMON_SIGNAL_CAN_SLEEP:
 ESP_LOGI(TAG, "Zigbee can sleep");
 esp_zb_sleep_now();
 break;

My I2C initialization function :

static esp_err_t i2c_master_init(void)
{
    int i2c_master_port = I2C_MASTER_NUM;
    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ,
        .clk_flags = I2C_SCLK_SRC_FLAG_LIGHT_SLEEP,
    };
    i2c_param_config(i2c_master_port, &conf);
    return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}

The ESP switches to "light sleep" mode since I have the information on the console: "Zigbee can sleep" and I see that consumption is dropping. But the I2C communication no longer works and the reading functions return a timeout error code.

I use the old I2C driver (i2c.h) and not the new one (i2c_master.h). Is the new one likely to work better?

I must be missing something, but I don't see what... Any suggestions?

Thank you for your help !

mythbuster5 commented 2 weeks ago

yes,please try new one. new one support sleep retention..

suda-morris commented 2 weeks ago

https://github.com/espressif/esp-idf/commit/27b2f7a10b662fdbe4991e12ba9c04870083a453

Currently this commit only exist on the master branch and release/v5.3 branch.

mycael commented 2 weeks ago

Thank you for your help ! I will try to move towards the new i2c drivers. Until now, I haven't found some example. This will help for sure. For now I managed to get I2C and light sleep mode to work by disabling the CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP option. But it's probably less effective, therefore.