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

UART current consumption

Hello,

I developed an application for a custom nrf52832 board. It uses the Nordic UART Service (NUS) to transmit data over BLE. This works fine.

At the moment I am trying to optimize the current consumtion of this application on the custom nrf52832 board. I have already made some measurements and I figured out the following:

If I initialize the UART by calling the uart_init() function, my current consumption increases by 1,35mA (V_cc = 1.8V). This looks a bit too high for me.

Can you please answer my following questions:

1. Is this the normal current consumption of the UART?

2. Are there any ways to lower the current consumption of the UART?

Thank you very much in advance.

Parents
  • Hi,

    1. Is this the normal current consumption of the UART?

    This depends a bit on which UART are used. Both the UART and the UARTE peripherals has a run current of 55 uA, but in addition, both requires the HFCLK to run, which is about 400 uA. The UARTE peripheral also adds the EasyDMA current of about 1.2 mA to the current, when the UART is active. These are numbers for 3.0V supply, I would expect them to be higher at 1.8V.

    2. Are there any ways to lower the current consumption of the UART?

    You can try to for the UART library to use the legacy UART peripheral, by setting the following configs in your sdk_config.h file:

    #ifndef UART_LEGACY_SUPPORT
    #define UART_LEGACY_SUPPORT 0
    #endif
    
    
    #ifndef UART0_CONFIG_USE_EASY_DMA
    #define UART0_CONFIG_USE_EASY_DMA 0
    #endif

    With these configs, I measure about 450 uA base current.

    Another option is to disable the RX part of the UART if you do not need this in your application. We have implemented this in NRF_LOG, and I measure 4 uA base current with this, as the UART peripheral is only active when a TX operation is happening. Since UART is asynchronous, there is no way to achieve this for RX, except having RX enabled at all times, or use additional control-signals to notify the chip in advance that a transfer will happen, to make it enable the RX mode.

    Best regards,
    Jørgen

  • I did my testing with ble_app_uart from SDK 17.0.2 on a nRF52 DK (PCA10040).

    Starting with unmodified example, I measure this current (1.875 mA):

    By adding the two changes to the sdk_config.h file I posted in my previous post (458 uA):

    Without adding the two previous changes, but setting the RX pin to UART_PIN_DISCONNECTED in comm_params passed to APP_UART_FIFO_INIT, the current is reduced to ~4 uA:

    Best regards,
    Jørgen

  • I'm not able to reproduce this behavior. I'm still seeing low current consumption after connection as long as the RX pin is set to disconnected.

    You say "when my device is connected to the central and data is sent over NUS", can you describe exactly at what point the current increases? What steps did you do after establishing the connection to the device?

  • Hello,

    thank you very much for your reply.

    Sorry for my inaccurate description in my previous reply to you.

    I start with initializing log, timers, buttons_leds and power_managment:

            log_init();
            timers_init();
            buttons_leds_init(&erase_bonds);
            power_management_init();

    Current consumption: 0.391mA

    If I initialize uart after that with RX_PIN_NUMBER, my current increases to 1.768mA. (Case 1)

    If I initialize uart after that with UART_PIN_DISCONNECTED, my current increases to 0.392mA (Case 2)

    ----------------------------------------

    Case 1:

    After Initialize ble_stack, gap_param, gatt, services, advertising, conn_param:

        ble_stack_init();
        gap_params_init();
        gatt_init();
        services_init();
        advertising_init();
        conn_params_init();

    Current while advertising: 2.03mA

    Current while connected (no data transfer): 1.85mA

    After intializing SAADC and start using NUS:

              saadc_sampling_event_init();
              saadc_init();
              saadc_sampling_event_enable(){
                    ...
                    nrf_drv_clock_hfclk_request(NULL); 
                    ...
              };

    Current: 2.84mA

    -----------------------------------------

    Case 2:

    After Initialize ble_stack, gap_param, gatt, services, advertising, conn_param:

        ble_stack_init();
        gap_params_init();
        gatt_init();
        services_init();
        advertising_init();
        conn_params_init();

    Current while advertising: 0.377mA

    Current while connected (no data transfer): 0.144mA

    After intializing SAADC and start using NUS:

              saadc_sampling_event_init();
              saadc_init();
              saadc_sampling_event_enable(){
                    ...
                    nrf_drv_clock_hfclk_request(NULL); 
                    ...
              };

    Current: 2.81mA

    ----------------------------------------

    Do you know why my overall current consumption is finally the same?

  • The SAADC also enables the EasyDMA once started. You can try enabling low-power mode in your sdk_config.h file:

    // <q> SAADC_CONFIG_LP_MODE  - Enabling low power mode
     
    
    #ifndef SAADC_CONFIG_LP_MODE
    #define SAADC_CONFIG_LP_MODE 1
    #endif

    Note that requesting the HFCLK will cause ~400 uA current @ 3.0 V increase in current as well.

  • Hello, thank you very much for your answer.

    enabling low-power mode

    I applied your suggested change in the sdk_config, but unfortunaly it does not change anything.

    Note that requesting the HFCLK will cause ~400 uA

    I know that, but I have to use the HFCLK for the accuracy of the SAADC.

    I figured out, that when I use NUS without the SAADC, the current consumption with UART_PIN_DISCONNECTED is significantly lower than with RX_PIN_NUMBER. So it looks like it have something to do with the SAADC.

    Do you have any suggestions?

    Thank you very much in advance.

  • Do you have multiple channels enabled in the SAADC? I have seen before that this could prevent the low power mode from working correctly. Also, what sample rate are you using for the SAADC?

    This Github repository has a few examples of low power SAADC with one and multiple channels.

    This post has an example for multichannel low power SAADC.

Reply Children
  • Hello, 

    sorry for my late reply.

    Thank you for your answer.

    Do you have multiple channels enabled in the SAADC?

    Yes, I am using 4 channels.

    what sample rate are you using for the SAADC

    1kHz (1ms) for all channels.

    I also use the SAADC in non-blocking mode and with double buffering. For accuracy I need the HFCLK.

    I already evaluated the SAADC readings and they are fine.

    example for multichannel low power SAADC

    I will take a look to this examples. I hope that I can find the reason for the increase in current consumption.

  • Hello,

    I figured out that when I use UART_PIN_DISCONNECTED for the rx part of the UART, the current consumption increases by ~1.5mA when I call the following:

    void saadc_init(void)
    {
        ...
        err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0],SAADC_SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);   
        err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1],SAADC_SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
        ...
    }

    Unfortunaly, I am not able to determine why this causes the increase in current consumption. The call of the nrf_drv_saadc_buffer_convert(..) function is equal to the "Low Power SAADC" example with multiple channels.

    1. Do you have any ideas why this causes the increase in current consumption when I use UART_PIN_DISCONNECTED for the rx part of the UART?

    2. Do you have any ideas how to solve this issue?

    Thank you very much in advance.

  • 1. When you did not set UART_PIN_DISCONNECTED for the UART RX pin, EasyDMA was already enabled due to the UART being in RX mode. When you removed the RX part of UART, EasyDMA was not started until you start the SAADC (which uses the same EasyDMA feature for storing samples in RAM). EasyDMA current is only introduced once, not multiplied by the numbers of peripheral utilizing EasyDMA concurrently.

    2. How large is the SAADC_SAMPLES_IN_BUFFER define? In order to achieve low current, the buffers can only hold a single sample for each enabled channel. Depending on your acquisition time, 4 channels with a sample rate of 1 kHz means that the SAADC will be enabled ~5-20% of the time anyway, and with the overhead of stopping/starting the SAADC, you may not be able to see low currents like in the examples I linked. Handling this much interrupts to change buffers every 1 ms may also not work well in all application.

  • Hello,

    thank you very much for your reply.

    EasyDMA current is only introduced once

    This sounds very reasonable. 

    1. Do you know what the typical current consumption of EasyDMA is?

    I want to analyze the current consumption of each peripheral. As I already mentioned in my original question my current increases by ~1.35mA when call uart_init().

    2. Do you know how the current consumption is distributed? (How much current draws EasyDMA and how much current draws the 16MHz clock?)

    3. Is there somewhere a summary of the typical current draws of each peripheral?

    How large is the SAADC_SAMPLES_IN_BUFFER define

    It is defined to 4. I already figured out that there is no point of using the Low Power Mode of SAADC for this application. Especially because I need EasyDMA, allowing sampling of channels directly to RAM using PPI, without CPU intervention. This is not available in Low Power Mode.

    Thank you so much in advance for answering my questions.

  • Michael01101 said:
    1. Do you know what the typical current consumption of EasyDMA is?

    Unfortunately, we do not have current numbers for each component in the chip alone. EasyDMA is always used in combination with a peripheral, so it is not easy to measure its current consumption alone.

    Michael01101 said:
    2. Do you know how the current consumption is distributed? (How much current draws EasyDMA and how much current draws the 16MHz clock?)

    The major part of SAADC active current is from EasyDMA. The majority of the TIMER running current is from the HFCLK.

    Note that these values are in the nRF52840 PS and not fully accurate for nRF52832, however it gives you an idea of the magnitude of currents consumed. The currents are typical values and for 3.0V supply voltage.

    Michael01101 said:
    3. Is there somewhere a summary of the typical current draws of each peripheral?

    Current consumption for some peripherals (including the ones linked in 2., are presented in Current consumption chapter in the nRF52832 PS. For nRF52832, there is also current consumption numbers in the "Electrical Specifications" section of each peripheral chapter. The problem with these number is that they are typically run currents for the peripheral itself, and does not include current consumed by other requested resources (EasyDMA, Clock domains, etc).

Related