This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Increase current consumption with TWI after calling nrf_twi_uinit

Hi,

I am working with a custom board with a third party NRF52832 module. On my board I have a DS3231M real time clock IC communicating with the NRF52832 via I2C/TWI and 2 push buttons that uses GPIOTE. My application requires very low power consumption and I am struggling with keeping the current consumption low while communicating with the DS3231M via TWI. My program is modified from the ble_app_uart example (PCA10040 S132) and I am using SES for editing.

The RTC module has 2 power source (let me call it RTC_VCC and VBat). To reduce power consumption, I have connected RTC_VCC to a GPIO pin (P0.03) and will only set P0.03 to high whenever I need to communicate with the RTC module via TWI. P0.03 will be set to 0 whenever TWI communication is completed. VBat is connected to VCC (3.3V) on my board (same supply as the NRF52832). This setup is used so that the RTC module can use minimum current.

Here is description of the problem:

In my main program, I first declare the TWI instance

/* TWI instance ID. */
#define TWI_INSTANCE_ID     0

/* TWI instance. */
static const nrf_drv_twi_t m_twi = NRF_DRV_TWI_INSTANCE(TWI_INSTANCE_ID);

My TWI is initialized as follows:

/**
 * @brief TWI initialization.
 */
void twi_init (void)
{
    ret_code_t err_code;

    const nrf_drv_twi_config_t twi_config = {
       .scl                = NRF_GPIO_PIN_MAP(0,29),
       .sda                = NRF_GPIO_PIN_MAP(0,30),
       .frequency          = NRF_DRV_TWI_FREQ_100K,
       .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
       .clear_bus_init     = false
    };

    err_code = nrf_drv_twi_init(&m_twi, &twi_config, twi_handler, NULL);
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&m_twi);
}

In my main program, 1 second after initializing TWI, I enable the DS3231M by setting P0.03 to HIGH to turn on the RTC. I do nothing (no TWI communication at all), use app_timer to delay for a short time, then turn off the DS3231M by clearing P0.03. I did not un-init the TWI. After that I broadcast for 3 seconds before going to sleep:

static void sleep_mode_enter(void)
{
    // Sleep
    uint32_t err_code = sd_app_evt_wait();
    APP_ERROR_CHECK(err_code);
}

With this, when the NRF52832 goes to sleep, I am getting a sleep current of about 10uA.

Next, just added 4 more lines to disable and uninit the TWI:

    nrf_drv_twi_disable(&m_twi);
    nrf_drv_twi_uninit(&m_twi);
    *(volatile uint32_t *)0x40003FFC = 0;
    *(volatile uint32_t *)0x40003FFC;
    *(volatile uint32_t *)0x40003FFC = 1; 

With TWI disable and uninit, when the NRF52832 goes to sleep, I am getting a sleep current of about 80uA. This does not make sense to me.

I also tried another scenario where I use TWI to communicate with the DS3231M (write to a register). If I do not disable and uninit TWI, I am getting a sleep current of 440uA

If I use TWI to communicate with the DS3231M (write to a register) and disable and uninit TWI, I am getting a sleep current of about 70uA.

 

Why is the sleep current at 10uA when I do not disable and uninit TWI? And why does the sleep current increase after I perform TWI communication and disable and uninit TWI? Is it not possible to perform TWI communication, disable and uninit TWI and have a sleep current of 10uA?

Parents
  • Hi. It looks to me like the current is drifting up and down again after uninitializing the TWI? This could be that the TWI pins are left in a floating input state while the input buffer is still connected. After the uninit function and the 0x40003FFC power cycle can you try to set the TWI pins back to the default state (0x02, disconnected input)? Like this:

    NRF_GPIO->PIN_CNF[SDA_PIN] = 0x2;
    NRF_GPIO->PIN_CNF[SCL_PIN] = 0x2;

    Or, if you want to keep the internal pullups so that the pins are not floating:

    NRF_GPIO->PIN_CNF[SDA_PIN] = 0xD;
    NRF_GPIO->PIN_CNF[SCL_PIN] = 0xD;

    https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52832.ps.v1.1/gpio.html?cp=4_2_0_19_2_9#register.PIN_CNF-0

    BTW: The 10 uA you are seeing after the TWI transfer when you are not uninitializing the TWI, could also be caused by the GPIOTE IN event (if you are using this for the buttons). The solution is to use the GPIO PORT event instead. In the GPIOTE driver this is called "hi_accuracy" mode, and if you set this argument to false when initializing the input pin the GPIOTE peripheral will not consume any current.

    Further, you can also try to just turn off the TWI peripheral through writing 0 to the ENABLE register, instead of completely uninitializing it:

    https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52832.ps.v1.1/twim.html?cp=4_2_0_32_7_5#register.ENABLE

    (Note that enabling it again is not 1, but 6 in the TWIM peripheral)

  • Thanks Stian,

    I think the problem has something to do with the GPIO and button setup. I was using an external pull up resistor and an additional resistor capacitor pair for button debouncing. In my GPIOTE  I had disable pullups. This seemed to have caused the high current consumption (I am not too sure).

    Now I have removed the pull up resistor and also the resistor-capacitor pair. Just connecting the push button to ground on one side and the other side to GPIO pin on the NRF52832 and configuring  GPIOTE with pull up. I am now getting about 40uA with TWI communication and disable+uninit TWI. But I think it can be further improved. Because the DS3231M RTC module should only be consuming 5-10uA according to the datasheet.

    I have not tried your suggestions yet.

    My gpio_init function looks like this now:

    static void gpio_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_drv_gpiote_init();
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_SIMPLE(false);
    
        err_code = nrf_drv_gpiote_out_init(MOTOR, &out_config);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_gpiote_out_init(RTC_EN, &out_config);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
        in_config.pull = NRF_GPIO_PIN_PULLUP;
    
        err_code = nrf_drv_gpiote_in_init(BUTTONPRESS, &in_config, stop_pin_handler);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_gpiote_in_event_enable(BUTTONPRESS, true);
    }



    I also realised that enabling another input pin increased the current to about 80uA.

Reply
  • Thanks Stian,

    I think the problem has something to do with the GPIO and button setup. I was using an external pull up resistor and an additional resistor capacitor pair for button debouncing. In my GPIOTE  I had disable pullups. This seemed to have caused the high current consumption (I am not too sure).

    Now I have removed the pull up resistor and also the resistor-capacitor pair. Just connecting the push button to ground on one side and the other side to GPIO pin on the NRF52832 and configuring  GPIOTE with pull up. I am now getting about 40uA with TWI communication and disable+uninit TWI. But I think it can be further improved. Because the DS3231M RTC module should only be consuming 5-10uA according to the datasheet.

    I have not tried your suggestions yet.

    My gpio_init function looks like this now:

    static void gpio_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_drv_gpiote_init();
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_SIMPLE(false);
    
        err_code = nrf_drv_gpiote_out_init(MOTOR, &out_config);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_gpiote_out_init(RTC_EN, &out_config);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
        in_config.pull = NRF_GPIO_PIN_PULLUP;
    
        err_code = nrf_drv_gpiote_in_init(BUTTONPRESS, &in_config, stop_pin_handler);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_gpiote_in_event_enable(BUTTONPRESS, true);
    }



    I also realised that enabling another input pin increased the current to about 80uA.

Children
No Data
Related