SPI Sleep Power too high

Hi Nordic Community

I am struggling to understand how to lower my sleep power consumption for SPI.

I am using the nRF52840DK and I have connected a Waveshare eInk screen (gdew042t2) using SPI. I have also connected a DS3231 RTC as well as a SHT31 thermometer via I2C.

I am using nRF Connect SDK v2.0.0.

Everything works, but when I monitor power usage, the chip is always drawing around 2mA of power, even when sleeping. 

In my investigations I think I have narrowed down the power draw to the eInk screen.

created a very basic project based off the Blinky app to test this. I set the project to blink twice and then permanently sleep. I added in the standard Power Management features (prj.conf adds CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_SERIAL=n) and (main.c adds #include <pm/pm.h> #include <pm/device.h>).

1) I only add SPI to the project by adding CONFIG_SPI=y to prj.conf. 

The power draw of the device when sleeping is around 5mA. If I pull out the CS pin connecting the screen to the DK the power usage instantly drops to ~4µA which is what I expect for a sleeping DK. I have a PPK logic port attached to the CS pin and I can see it showing HIGH when plugged in and LOW when physically pulled out.

2) I add in more code to add the screen to the project. I add CONFIG_HEAP_MEM_POOL_SIZE=16384, CONFIG_MAIN_STACK_SIZE=2048, CONFIG_DISPLAY=y and CONFIG_GD7965=y to prj.conf). I also add set(SHIELD waveshare_epaper_gdew042t2) to CMakeLists.txt.

The power draw of the device when sleeping is now around 2mA (same as my full project). If I pull out the CS pin connecting the screen to the DK the power usage stays the same. The PPK logic port attached to the CS pin stays HIGH. If I disconnect all the Pins to the screen then the power usage drops to ~600µA.

The drivers for the screen use the arduino_spi devicetree bindings. I am not sure if this is relevant but the SCK, MISO and MOSI Pins are specified in the  DTSI file in both the "default" and "sleep" groups but the CS PIN is specified in the main DTS file and not mentioned in the DTSI "default" and  "sleep" groups.

Is there a specific way to put SPI to sleep that I am not aware of?

I am hoping you can point me in the right direction to try and reduce the power usage.

Here are some of the relevant settings:

waveshare_epaper_gdew042t2.overlay

#include "waveshare_epaper_common.dtsi"

/ {
  chosen {
    zephyr,display = &gd7965;
  };
};

&arduino_spi {
  gd7965: gd7965@0 {
    compatible = "gooddisplay,gd7965","gooddisplay,gdew042t2";
    label = "GD7965";
    spi-max-frequency = <4000000>;
    reg = <0>;
    width = <400>;
    height = <300>;
    dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */
    reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */
    busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */
    pwr = [03 00 26 26 09];
    softstart = [17 17 17];
    cdi = <0xd7>;
    tcon = <0x22>;
  };
};

waveshare_epaper_common.dtsi

&arduino_spi {
  status = "okay";
  cs-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>, /* D10 */
                   <&arduino_header 12 GPIO_ACTIVE_LOW>; /* D04 */

  sdhc0: sdhc@1 {
    compatible = "zephyr,mmc-spi-slot";
    reg = <1>;
    status = "okay";
    label = "SDHC0";
    spi-max-frequency = <24000000>;
  };
};

nrf52840dk_nrf52840 (only showing the arduino_spi part)

arduino_spi: &spi3 {
  status = "okay";
  cs-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>; /* D10 */
  pinctrl-0 = <&spi3_default>;
  pinctrl-1 = <&spi3_sleep>;
  pinctrl-names = "default", "sleep";
};

nrf52840dk_nrf52840-pinctrl.dtsi (only showing spi3)

spi3_default: spi3_default {
  group1 {
    psels = <NRF_PSEL(SPIM_SCK, 1, 15)>,
                <NRF_PSEL(SPIM_MISO, 1, 14)>,
                <NRF_PSEL(SPIM_MOSI, 1, 13)>;
    };
};

spi3_sleep: spi3_sleep {
  group1 {
    psels = <NRF_PSEL(SPIM_SCK, 1, 15)>,
                 <NRF_PSEL(SPIM_MISO, 1, 14)>,
                 <NRF_PSEL(SPIM_MOSI, 1, 13)>;
    low-power-enable;
  };
};

CMakeLists.txt

added the line

set(SHIELD waveshare_epaper_gdew042t2)
  • Hi

    This sounds very strange. I haven't heard of any SPI devices that uses the CS pin active high, and from what I can see from a quick googling that doesn't seem to be the case for this device either, so the current consumption numbers you're describing sounds off. Are you sure you're powering all devices correctly, and that the power source is in fact able to power all devices at once?

    There shouldn't be a "special" way to disable the SPI compared to any of the other peripheral, but you should make sure the screen is also put in sleep mode I guess. This seems to be explained in the datasheet under "deep sleep". https://thingpulse.com/wp-content/uploads/2019/07/GDEW042T2-V3.1-Specification_.pdf 

    Can you show me a snippet of the Power Profiler graph as well, so I can see if there's anything "off" with your current consumption graph.

    Best regards,

    Simon

  • Hi Simon

    I have made a tiny bit of progress but my problem still remains.

    I was using a custom driver board for the Waveshare screen. I have replaced it with an official Waveshare driver board. The power usage has improved but it still isn't "sleeping".

    1) In my simple test app described above, if I do nothing else but enable SPI in the prj.conf file the power usage now shows ~5µA when sleeping, so this looks good.

    2) If I then enable the display and GD7965 driver (as described in point 2 above) the power usage shows a consistent ~520µA when sleeping. If I pull out the CS pin it stays the same. If I boot the device without the screen attached at all it stays the same.

    If I use my full application the display works and updates but never goes below 520µA power usage. I am wondering if there is something wrong with the GD7965 driver preventing SPI (or something else) from sleeping...?

    I have attached my little test project. It doesn't actually update the screen but it illustrates the power usage as I described in points 1 and 2 above. You shouldn't need the screen itself to see the issue.

    nrf_test_blinky.zip

    Here are some screenshots of the power usage from my full app. I am showing a screen update here in the middle with sleep before and after. You can also see the logic levels measured on the CS pin.

    Sleep power usage:

    Active power usage:

    Thanks for your help!

    Regards,

    Gary

  • Hi

    I tested this on my end and could indeed see the same behavior. A few things that could cause this:

    • In SPIM3 on the nRF52840, you need to disable the peripheral through the ENABLE register to get the current down. TASKS_STOP alone does not work. This will be updated in future versions of the nrfx drivers.
    • It could also be erratum 89, but that should be taken care of in the driver already.
    • Finally, it could be possible that the driver implements polling of some kind, and that the CPU wakes up too often.

    Best regards,

    Simon

  • Hi Simon

    Thanks for the guidance.

    I am very new to Nordic hardware and especially the Zephyr RTOS so this has been quite challenging.

    I'll work my way though your suggestions and see if I can make any difference to the power usage.

    My project updates the screen very infrequently (max once per minute) so I don't need to keep the screen immediately ready. Is there any way in Zephyr to force shut down of the device/screen or force disable SPI or disconnect all the relevant GPIO pins and then re-enable when I need to update? Nothing I have tried in the power management file has had any effect.

    Regards,

    Gary

  • Hi Gary

    Yes, it's possible to turn the device off in system OFF mode to save the highest amount of power. https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/samples/boards/nrf/system_off/README.html 

    Please note that the timers/radio will not be running as the entire device will be off, so you need to wake it with an external event on one of the GPIOs of some kind.

    Best regards,

    Simon

Related