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

  • Hello,

    thank you very much for your response.

    I was able to disable the RX part of the UART by setting the RX pin to UART_PIN_DISCONNECTED. After I call the uart_init() function my increase in current consumption is far lower than 1.35mA.

    However, when my device is connected to the central and data is sent over NUS, the overall current consumption is the same as before.

    It looks like, that this change is revoked at some point when the SoftDevice starts.

    1. Do you have any suggestions what could cause this behaviour?

    2. Do you have an idea how to solve this issue?

    Thank you so much in advance.

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

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

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

Related