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

~500 uA current consumed in __WFI()

Hello,

I just started 4 days ago. My project consists of two parts. The first module that I am working on should communicate with. a I2C sensor, go to sleep for 30 seconds and repeat. Current consumption is critical, as a 2200 mA 3.6V battery should last for > 1 year. I am replacing a PIC processor that only uses in the nA range in Deep Sleep. The processor is replaces, because in the Second part of this project, I will also need to communicate using BLE with another unit. 

I based my project on the TWI Sensor example, that I understand does not use a SoftDevice (SD).

I got TWI (I2C) com up and running, and I am using nrf_drv_timer_init() timer to fire an Event every 30 seconds.

Problem is that current consumption in __WFI()  is ~500 uA: Need it as low as possible (<= 10 uA). Searched for days on the forum: Nothing I have tested helps!

Program structure is roughly as follows:

You can get a copy of the whole Segger project if you need, it's no secret and is not very large, but a bit messy at this experimental stage.

main() {

// Various statements found on this forum to shut down peripherals:

   NRF_UART0->ENABLE = (UART_ENABLE_ENABLE_Disabled << UART_ENABLE_ENABLE_Pos);

   NRF_SAADC->ENABLE = SAADC_ENABLE_ENABLE_Disabled;

   twi_init();

   nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG; // Probably not necessary: Done in sdk_config.h

   nrf_drv_timer_init(&TIMER_LED, &timer_cfg, timer_led_event_handler);

   time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_LED, time_ms);

   nrf_drv_timer_extended_compare(
     &TIMER_LED, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);

   nrf_drv_timer_enable(&TIMER_LED);

    while (true)
    {

        // Rapid blink of LED 1 twice to see that things are running (500 ms)

        nrf_drv_twi_enable(&m_twi);

        float temperature = Read_Temperature_Sensor_Temperature(writeBuffer, dataBuffer, TEMP_SENSOR_ADDR);   

        nrf_drv_twi_disable(&m_twi); // Does not seem to reduce power...       

        // // http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.Rev2.errata%2Fdita%2Ferrata%2FnRF52832%2FRev2%2Flatest%2Fanomaly_832_87.html&cp=2_1_1_0_1_24


        NRF_LOG_INFO("Temperature: " NRF_LOG_FLOAT_MARKER " C \r\n", NRF_LOG_FLOAT(temperature));
        NRF_LOG_FLUSH();

        #if (__FPU_USED == 1)
        __set_FPSCR(__get_FPSCR() & ~(0x0000009F)); // Errata had missing underscores for this call
       (void) __get_FPSCR();
       NVIC_ClearPendingIRQ(FPU_IRQn);
       
        __WFI();       

       NRF_LOG_INFO("\r\n************  After After __WFI(); ***************"); 

    } // end while 

} // end main()

Questions

1) Can you please help tip me how to reduce the current consumption

2) The project I based my example on does not use a Softdevice. I see that many examples on how to reduce current does not compile when I do not have a SoftDevice
    a) Is there a way to include SoftDevice 132 (I will use nRF52832) in an existing project?
       
     b) I have seen the guide on how to prepare the Board with a Softdevice, but I do not understand how that works:
         If I flash a SoftDevice to the Board, won't that be overwritten when I debug my program on the board, or download a hex file?

3) Using an example as a starting point gets complicated with respect to sdk_config.h once one needs to base the project on two different projects.
    Is there any tool that can Merge several sdk_config.h files? I have so far done it manually, but it takes time...


Wish

It would be nice to have a Guide that shows how to Enable / Disable every peripheral, as this seems to be a recurring question on the forum.

Parents
  • Hi,

    A current consumption of about 500 μA indicate that the high frequency clock is running, probably because a peripheral is requesting it. Therefore, you should always make sure to disable any peripherals that use the high frequency clock (which is most peripherals, except RTC, LPCOMP and a few others).

    1) You should disable peripherals (typically all except the RTC in a typical application) before going to sleep. This includes that you need to disable UART logging. For a typical SDK example all you need for it to be low power is to build the release version (in SES there is a drop-down where you select between Release and Debug) and disable logging in the projects sdk_config.h. (You should also activate the DC/DC by calling sd_power_dcdc_mode_set(NRF_POWER_DCDC_ENABLE) after initializing the SoftDevice but is has less of an impact).

    2a) The SoftDevice "protects" a number of system resources, so that they can only be accessed via SoftDevice APIs when the SoftDevice is enabled. Therefor you typically cannot use the same code with and without a SoftDevice. However, the legacy driver layer (SDK 15) handles this for you, so you should be able to use mostly the same code with and without a SoftDevice as long as you access HW peripherals via the SDK drivers.

    2b) The SoftDevice must be programmed to the beginning of the flash (starting with the MBR ad address 0), so you must adjust your application to start at a higher flash address when using a SoftDevice. The start address depends on the SoftDevice version and can be found in the SoftDevice release notes. You must also adjust the memory size and start address, as the SoftDevice will use some memory. This depends on the configuration. There are a number of things to remember here, so I suggest you start with the Getting Started section in the SDK documentation. You should probably also refer to this section of the SoftDevice specification in order to understand how the application communicates with the SoftDevice. Lastly I recommend you to look at the BLE examples in the SDK to see practical examples of how to use the SoftDevice. There you can also see memory layout and other project settings when using a SoftDevice.

    3) We do not have any tool for merging sdk_config.h files. You have to do it manually, copying/editing as needed.

    Regarding your wish, you typically only need to use the driver API to disable a peripheral. Most peripherals have functions called *_uninit() and *_disable().

Reply
  • Hi,

    A current consumption of about 500 μA indicate that the high frequency clock is running, probably because a peripheral is requesting it. Therefore, you should always make sure to disable any peripherals that use the high frequency clock (which is most peripherals, except RTC, LPCOMP and a few others).

    1) You should disable peripherals (typically all except the RTC in a typical application) before going to sleep. This includes that you need to disable UART logging. For a typical SDK example all you need for it to be low power is to build the release version (in SES there is a drop-down where you select between Release and Debug) and disable logging in the projects sdk_config.h. (You should also activate the DC/DC by calling sd_power_dcdc_mode_set(NRF_POWER_DCDC_ENABLE) after initializing the SoftDevice but is has less of an impact).

    2a) The SoftDevice "protects" a number of system resources, so that they can only be accessed via SoftDevice APIs when the SoftDevice is enabled. Therefor you typically cannot use the same code with and without a SoftDevice. However, the legacy driver layer (SDK 15) handles this for you, so you should be able to use mostly the same code with and without a SoftDevice as long as you access HW peripherals via the SDK drivers.

    2b) The SoftDevice must be programmed to the beginning of the flash (starting with the MBR ad address 0), so you must adjust your application to start at a higher flash address when using a SoftDevice. The start address depends on the SoftDevice version and can be found in the SoftDevice release notes. You must also adjust the memory size and start address, as the SoftDevice will use some memory. This depends on the configuration. There are a number of things to remember here, so I suggest you start with the Getting Started section in the SDK documentation. You should probably also refer to this section of the SoftDevice specification in order to understand how the application communicates with the SoftDevice. Lastly I recommend you to look at the BLE examples in the SDK to see practical examples of how to use the SoftDevice. There you can also see memory layout and other project settings when using a SoftDevice.

    3) We do not have any tool for merging sdk_config.h files. You have to do it manually, copying/editing as needed.

    Regarding your wish, you typically only need to use the driver API to disable a peripheral. Most peripherals have functions called *_uninit() and *_disable().

Children
  • Hello Einar,

    Thanks for a fast reply. However, you are talking a bit over my head at this stage (beginner)

    << Therefore, you should always make sure to disable any peripherals that use the high frequency clock (which is most peripherals, except RTC, LPCOMP and a few others).>>

    As I stated in the question: I do not know the commands to do this. I have read the docs and forums, but still do not understand what the commands are...

    Q1

    I only use TWI (I2C) and the Timer at this stage. Can you please give me the commands to disable the other peripherals?

    Q2

    You say that the SoftDevice needs to be flashed before it can be used;
    But what about the example Segger projects that use a SoftDevice: They compile and run without flashing the SoftDevice separately: I guess the SoftDevice is a part of these projects?

    How can I make a SoftDevice a part of my Project that currently does not use a SoftDevice?

  • Hi,

    Q1. You can find information about this by referring to the documentation for the relevant drivers. For the TWIM driver: "The instance can be disabled using nrf_drv_twi_disable and uninitialized using nrf_drv_twi_uninit." For the timer driver, you have to refer to the API documentation, where you can see the following functions: nrf_drv_timer_uninit() and nrf_drv_timer_disable().

    Q2. The example SES projects are configured to automatically flash the SoftDevice for projects that use it, so you do not need to do it manually there. If you start off with an example what does not use a SoftDevice then  you either need to update the example to flash the SoftDevice for you , or you should flash it manually. See Running examples that use a SoftDevice. The easiest is to just start off with a SES project that use a SoftDevice from the SDK, as that would give you the other project configuration for free as well (memory layout configuration, required defines depending on SoftDevice etc.).

  • Your suggestion is not trivial to follow.

    E.g. when I try to disable GIIOTE according to your API reference, there is a _uninit method that only points to a define statement:

    define nrf_drv_gpiote_in_uninit   nrfx_gpiote_in_uninit

    So, I included the following in my code:

    #include "nrf_drv_gpiote.h"
    #include "nrf_gpiote.h"

    And the .c file: nrfx_gpiote.c

    It seems that the unint must be done for every port (?) so I wrote the following code:

    // Should this really be performed on a per pin basis??

    for(int i=0; i<28; i++) {
       //nrfx_gpiote_in_uninit(i); // undefined reference
       nrf_drv_gpiote_in_uninit(i);
    }

    Both suggestions compile, but does not LINK: undefined reference nrfx_gpiote_in_uninit

    nrfx_gpiote.c includes a function void nrfx_gpiote_uninit(void) 
    but that function is greyed out (due to some defines i guess)

    I can uninit the UART, but that causes the program to crash at runtime....

    So, you see the problem: This is NOT easy for a beginner.

    I am back to my original request: Please Help!

  • Hi,

    I am trying to help :) Bu please be aware that even though we aim to make the SDK as user friendly as possible it is still quite complex, and you should expect to use some time on reading documentation, referring to examples and browsing this forum. It is not realistic (or even possible) to understand everything immediately when you start working with it. I strongly advise you to spend a bit of time with the documentation, as that will probably save you time in the long run.

    You do not write which linker error you get, but a typical reason for linker errors with our SDK is if you are referring a function (in a driver in this case) which has been stripped out of the implementation (.c) file because the driver is not enabled in the projects sdk_config.h. Have you enabled the GPIOTE driver in sdk_config.h? Note that you only strictly need to care about the configuration structs for the legacy driver (not nrfx), as the apply_old_config.h file will cause any legacy configuration to overwrite the nrfx configuration defines in sdk_config.h.

  • Hello,

    The link error is above: undefined reference nrfx_gpiote_in_uninit

    There are no GPIOTE in sdk_config.h for the TWI Sensor example as I said that I have based my code on.

    It is also quite confusing what should be done in defines in code and in sdk_config.h and what should be done by calling functions to reduce power.

    If I do nrf_drv_uart_uninit(&UART_0);    the program crashes, 

    From the docs in nRF52832_PS_v1.4.pdf it is stated that the Processor reduces power for unused peripherals: But it is hard to know what peripherals are unused:

    I only explicitly use TWI and the RTC (Timer), and do not do ÙART logging.

    What about the statements I already have included in my source listed in my original question: 
    Are they any useful?

    I still do not have a clue what peripherals uses this extra current.

    That's why I asked for command that shut them down one by one to see what happens.

    I also read this forum post on the issue:

    https://devzone.nordicsemi.com/f/nordic-q-a/4329/what-is-sure-way-to-power-down-unwanted-nrf51822-subsystems

    and that'w why I tried some of the statements in my code, but they don't help.

Related