High power consumption of nRF52832 using TWI 100KHz ?

Hi, we are using nRF52832 for our project. SDK version is nRF5_SDK_17.1.0_ddde560. SoftDevice is S132.

The project requires TWI to read data from a sensor and send that data via BLE. The sensor will output 9 bytes every 2.5ms, or 3600B/s data rate. Currently, BLE consumes 0.1mA and it matches the estimated number. When data transfer via BLE is going on, our board consumes 3.8mA. We are trying to lower this number by determining if any part of the system consumes more power than usual.

So we first remove the code that sends data via BLE, which means only connect via BLE, and read data via TWI, but do not send it to the peer. We get a consumption of around 3.2mA
Then we remove the code that reads data from sensor via TWI. This time consumption reduces to 1.5mA. The sensor is still in its working state, just the code to read data in the sensor buffer is removed.

That means reading sensor data via TWI consumes 3.2-1.5=1.7mA. This is so high, especially for a quite low data rate. TWI clock is 100KHz. We check the sensor buffer every 60ms to see if any data is available. The buffer check is simply just 2 registers (head & tail) being read from the sensor. From this, we know how many bytes we can read from the sensor, and we read a burst of that many bytes from the sensor.

Is this number normal for TWI usage? Is there any way we can optimize the power consumption when using TWI? Please let us know soon. We really appreciate your speedy help.

Best regards,

Xander

  • A handy envelope shows 9 bytes or 81 bits at 100kHz is 810uSec active clock and data in 2500uSec, or about 32%. 32% active I2C data and clock with 4k7 pull-ups on SDA and SCK is (say) 400uA assuming something near 50% duty cycle on both. 1k0 pull ups this would be closer to 1mA, with 10k0 pull-ups closer to 200uA. Test this by switching to more power-efficient 400kHz to see if that part of the power reduces by x4 with the same value pull-ups.

    The key to the balance of power is likely to be "TWI"; TWI is inefficient since the CPU is awake more frequently. TWIM using DMA is much better, maybe approaching 9 times better, as although the same number of bytes are processed the 9 sleep/wakeup cycles and interrupt entry/exit cycles (power consumption overhead) are replaced by a single sleep/wakeup cycle and interrupt, particularly when errata workarounds are in effect. That means 9-byte TWIM, not 9 x 1-byte TWIM; 9 x 1-byte TWIM is even worse than 9 x 1-byte TWI and yes that is commonly used.

    Want optimum efficiency? Switch to SPIM (SPI with DMA), should that be an option, which does not require power-hungry pull-ups. I2C/TWI is old-school from the days when power consumption by other components was orders of magnitude higher; yes it's easy but no it's not a low-power solution. Data processing overhead for TWIM and SPIM both with DMA is similar.

  • A handy envelope shows 9 bytes or 81 bits at 100kHz is 810uSec active clock and data in 2500uSec

    I think you mean 72 bits? 

    1k0 pull ups this would be closer to 1mA

    We are using 50K pull-up resistors to 3V line for SDA/SCL so I think this consumption is still way too high than expected.

    TWIM using DMA is much better

    We are having a hard time figuring out how to use EasyDMA for TWI, especially after reading this one: Set easyDMA - Nordic Q&A - Nordic DevZone - Nordic DevZone (nordicsemi.com)
    We are currently doing I2C with NRF_TWI_MNGR_WRITE and NRF_TWI_MNGR_READ. In sdk_config.h, we already set TWI0_USE_EASY_DMA to 1. Is there anything else we should use?

    I read some other tutorials and they use the timer with PPI to fire the TWI task. I'm not sure if it's the right way to use EasyDMA.

    Our application needs to get the data from the sensor before the sensor's internal buffer is full. 2.5ms is the sample period of the sensor, but we can accumulate up to 60ms and then read many samples at once, reducing the wakeup frequency of the CPU. If we need to use PPI and timer for EasyDMA, should we make the timer period 2.5ms or 60ms?

  • Test this by switching to more power-efficient 400kHz to see if that part of the power reduces by x4 with the same value pull-ups.

    Yes it does. I changed to TWI at 400KHz and reading sensor data consumes 0.4mA instead of 1.7mA. I still don't understand why it can be this high?

  • 8-bit TWI isn't; it's 9-bit; there is an ACK bit after every 8-bit byte, and 9x9=81 bits. "Data received will be stored in RAM at the address specified in the RXD.PTR register. The TWI master will generate an ACK after all but the last byte received from the slave. The TWI master will generate a NACK after the last byte received to indicate that the read sequence shall stop"

    30k is an unlikely high value for a TWI/I2C/TWIM pull-up; try measuring it and see if that is the actual value.

    DMA with TWI aka TWIM is trivial, and no, fancy stuff is not required. Start with this bare-metal sample and set the number of received bytes to something larger than 1, such as 9 or higher. i2c_master/main.c

    0.4mA instead of 1.7mA? Either the CPU is not staying in sleep or the 30k pull-ups are 3k0 or so. Quite often the CPU is not staying in sleep, and that's another whole can of worms.

  • I have the PCB schematic and we place the PCB assembly from a fab so it shouldn't be wrong, however, I will contact the PCB designer team to confirm if the schematic I'm having is correct. And it is 50K, not even 30K.

    The resistor size is too small, 0201, and I don't have a probe that can measure the resistance of this tiny thing.

    If the CPU isn't staying in sleep, I think it should use a few mA of consumption, and increasing the TWI clock won't reduce 4x the consumption like this, right?

Related