Closed J-D-HW closed 9 months ago
Hello @JochemHomewizard,
Thanks for reporting this issue to us. So far in my (limited) testing, I haven't noticed this problem. One thing I didn't understand clearly is if you have tried the ulp_lp_core_i2c
controller without enabling deep sleep? I would like to understand if the abnormal signal levels are anyway related to the deep sleep power mode or are being purely driven by the LP_I2C peripheral irrespective of the power mode. Could you please help share this data?
Thanks for your reply. I just tried running this code with deep sleep turned off, and I see the same kind of output with the logic low at ~900mV. It seems to be purely caused by LP_I2C.
Thank you for the confirmation. We will look into this and keep the issue updated with our findings.
I have tested on the same development board. When using a self-made I2C using simple GPIO-bitbanging we see the same behaviour. If we configure the GPIO using RTC_GPIO_MODE_INPUT_OUTPUT_OD
everything works as intended.
// main code
rtc_gpio_init(GPIO_I2C_SDA);
rtc_gpio_set_direction(GPIO_I2C_SDA, RTC_GPIO_MODE_INPUT_OUTPUT_OD);
rtc_gpio_set_direction_in_sleep(GPIO_I2C_SDA, RTC_GPIO_MODE_INPUT_OUTPUT_OD);
rtc_gpio_pulldown_dis(GPIO_I2C_SDA);
rtc_gpio_pullup_dis(GPIO_I2C_SDA);
rtc_gpio_init(GPIO_I2C_SCL);
rtc_gpio_set_direction(GPIO_I2C_SCL, RTC_GPIO_MODE_OUTPUT_ONLY);
rtc_gpio_set_direction_in_sleep(GPIO_I2C_SCL, RTC_GPIO_MODE_OUTPUT_ONLY);
rtc_gpio_pulldown_dis(GPIO_I2C_SCL);
rtc_gpio_pullup_dis(GPIO_I2C_SCL);
ulp_lp_core_load_binary(lp_core_main_bin_start, (lp_core_main_bin_end - lp_core_main_bin_start));
ulp_lp_core_cfg_t core_cfg = {
.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER,
.lp_timer_sleep_duration_us = MEASUREMENT_TIME * SEC_TO_USEC, // Wakes up every 'measurement time' seconds to measure once
};
ulp_lp_core_run(&core_cfg);
esp_deep_sleep_start();
// LP core code
void send_bit(uint8_t level)
{
rtcio_ll_set_level(GPIO_I2C_SDA, level);
ulp_lp_core_delay_us(250);
rtcio_ll_set_level(GPIO_I2C_SCL, 1);
ulp_lp_core_delay_us(250);
rtcio_ll_set_level(GPIO_I2C_SCL, 0);
ulp_lp_core_delay_us(250);
}
void get_ack(bool *ack_received)
{
rtcio_ll_set_level(GPIO_I2C_SDA, 1);
ulp_lp_core_delay_us(250);
rtcio_ll_set_level(GPIO_I2C_SCL, 1);
ulp_lp_core_delay_us(250);
*ack_received = rtcio_ll_get_level(GPIO_I2C_SDA);
rtcio_ll_set_level(GPIO_I2C_SCL, 0);
ulp_lp_core_delay_us(250);
}
void send_byte(uint8_t data)
{
for (uint8_t i = 0; i < 8; i++)
{
send_bit(data & 0x80);
data <<= 1;
}
bool ack_received;
get_ack(&ack_received);
}
send_start();
send_byte(AHT20_I2C_ADDR << 1); // 0x38 0b0111000
send_byte(AHT20_CMD_MEASURE_BYTE1);
send_byte(AHT20_CMD_MEASURE_BYTE2);
send_byte(AHT20_CMD_MEASURE_BYTE3);
send_stop();
When looking at this, we see no open drain
is selected which should be used for I2C AFAIK. But this does not fix the issue.
Hey @sudeep-mohanty, sorry to bother but do you have an update maybe?
Hello @DCSBL, Apologies for not reverting earlier. I still haven't managed to reproduce this problem yet but with some consultation it could be an issue with the IO lines not being in Open-drain mode. With this context, would you mind trying out this patch in your setup and let us know the results? Thanks! -
Thanks! It seems to be the case indeed, as fixing this while using direct GPIO bit-bang fixed the issue for us after selecting OD.
would you mind trying out this patch in your setup and let us know the results?
@JochemHomewizard can I assign this to you? After this we will get back to you Sudeep!
@sudeep-mohanty Thanks for the patch! With your patch it works without any issues. This solved the problem.
Thanks for testing out the patch @JochemHomewizard! Glad it worked. I shall do some further tests on the changes and formalize the fix asap! Thanks!
Answers checklist.
General issue report
For my project I read a temperature sensor (AHT20) using I2C. It reads it's temperature during deep sleep using the ULP Core on the ESP32-C6. I noticed not all measurements are performed correctly and sometimes the values seem to be very off. In order to find the cause of this I used a logic analyser which showed the following signal:
From this logic output I was able to conclude that the logic low of the signal isn't always zero. Sometimes it's zero but often it sticks at ~900mV. This issue with the logic low always takes place at the same places during transmissions.
Also there seem to be small voltage spikes when the ACK is send.
This is the code I'm running in order to initialise the I2C communication before going into deep sleep:
The ULP uses the following functions to write and read data during deep sleep:
For the temperature sensor I used the recommended circuit:
A few things I tried:
Since this issue only occurs while reading the I2C sensor with the ULP core during deep sleep, it seems to be related to ulp_lp_core_i2c. Also note that the exact same thing happens with a completely different I2C sensor.