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.

  • 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.

  • Hi,

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

    I don't know details about your code, but clearly you have some code calling nrfx_gpiote_in_uninit (probably indirectly). Either you have to remove that code (if it is not needed), or you have to add GPIOTE configurations to you sdk_config.h file.

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

     If that is the case, then you only need to disable the TWI peripheral. As long as you make sure to call the _disable() function, that should be OK.

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

    To be honest the code snippet is a bit messy, so it is not clear to me what you want to do and what you are doing. Is that the code you are using to test? Then I suggest a cleanup to make it clearer what you want to do. You disable some peripherals which are never enabled, and you handle the FPU IRQ even though you don't use FPU. You call WFI__ in an eternal loop where you also use the TWI, but it is never disabled and it is not clear to me what will wake the device from the sleep (make it return from the call to __WFI() - probably a timer event as it seems you have a timer running. Note that the nrf_drv_timer does not use a RTC. It uses a TIMER peripheral, which uses the high frequency clock. So if this is actually the code you are testing with, then the current consumption you see is as expected.

  • I just tried to show you an outline of the code.

    As I said in my first post, I can send you the complete project:: It is not big.

    Th IRQ related statements before the __WFI() call was found in an Errata related to the 52832 where the FPU could generate unwanted interrupts and thus wake up the cpu from sleep.

    As it is, I only needed more tips on how to disable individual modules, but no-one seem to provide examples of such code.

  • Hi, 

    gos said:
    As I said in my first post, I can send you the complete project:: It is not big.

    Absolutely, there i no problem uploading your code to this case. That said, I do believe that the only thing you ave to do is to disable whatever you have earlier enabled as I have described. And please note that you cannot keep the timer running (like it seems you do from your code snippet). The timer will result in about 0.5 mA current consumption like any other peripheral using the high frequency clock. If you need to keep time in a low power way, use the RTC (most easily done via the app timer library).

    gos said:
    Th IRQ related statements before the __WFI() call was found in an Errata related to the 52832 where the FPU could generate unwanted interrupts and thus wake up the cpu from sleep.

    I see. Provided you use a fairly recent SDK, you do not need to do that. It is all handled for you by the SDK.

    gos said:
    As it is, I only needed more tips on how to disable individual modules, but no-one seem to provide examples of such code.

     Yes, and as I have attempted to point out: all you need to do is disable the peripherals by calling the appropriate disable function from the drivers. I don't really know what more you want to know? You only need to disable peripherals you have enabled earlier. If you did not enable the peripheral in your application, nobody else did (expect for a few low power peripherals used by the SoftDevice which you do not need to think about).

  • Hello Einar,

    I turned things around: I started with the \examples\peripheral\blinky example:

    It uses 1.9 - 2.2 uA in __WFI() !

    Then I started to integrate the app_timer as you suggested above. After a lot of tweaking of includes and sdk_config.h (merging parts from other projects that did have app_timer sections) it compiles and runs.

    But the app_timer does ever call the event_handler. I will tweak more on this example, if I do not get it to work, I will start another thread on the app_timer subject: Easier for others to get help from the same thread that way.

    I saw your app_timer Tutorial but it's for an older SDK so everything did not work following it, but it gave me valuable hints...

    I'll tag your above answer as the answer to the original question.

Related