High power consumption NRF52832 & SI7021



  • Sleep power consumption for my ebyte E104-BT5032A module is ~12uA with the Si7021 module connected and powered, but I'm seeing that jump to ~460uA when I include SI7021.h and actually communicate with it.

    I'm assuming that the Wire library is turning on features that are not powered down after communication or before sleep?

    SI7021 library manually included from: https://github.com/mysensors/MySensorsArduinoExamples/archive/master.zip

    #define MY_NODE_ID 67
    
    #define MY_RADIO_NRF5_ESB
    #include <MySensors.h>
    
    #include <SI7021.h>
    static SI7021 sensor;
    
    #define SLEEP_SHORT_MS (5000)
    #define LED_INFO_PIN (5)
    #define SLEEP_MS (30000)
    
    MyMessage            msgHum( 4, V_HUM );
    MyMessage           msgTemp( 5, V_TEMP );
    
    void setup() {
      pinMode( LED_INFO_PIN, OUTPUT );
      while(not sensor.begin());
      blink(LED_INFO_PIN, 5);
    }
     
    void present() {}
    
    void loop() {
      blink(LED_INFO_PIN, 1);
    
      const float temperature = float( sensor.getFahrenheitHundredths() ) / 100.0;
      const float humidity    = float( sensor.getHumidityBasisPoints() ) / 100.0;
      
      sleep(SLEEP_SHORT_MS);
        
      send( msgTemp.set( temperature, 2 ) );
    
      sleep(SLEEP_SHORT_MS);
      send( msgHum.set( humidity, 2) );
    
      sleep( SLEEP_MS );
    }
    
    void blink(uint8_t led, uint8_t count){
      for(int i = 0; i < count; i++){
        digitalWrite( led, HIGH );
        wait( 5 );
        digitalWrite( led, LOW );
        if( i < count - 1 ) wait(100);
      }
    }
    


  • Looks like it's probably related to this: https://github.com/sandeepmistry/arduino-nRF5/issues/291



  • Well, adding

      *(volatile uint32_t *)0x40004FFC = 0;
      *(volatile uint32_t *)0x40004FFC;
      *(volatile uint32_t *)0x40004FFC = 1;
    

    just after the Si7021 sensor reading worked. Sleep current is back down to 12uA.
    https://infocenter.nordicsemi.com/topic/errata_nRF52832_Rev1/ERR/nRF52832/Rev1/latest/anomaly_832_89.html#anomaly_832_89

    Probably not the best place for it. I think it should probably live in TwoWire:end() https://github.com/sandeepmistry/arduino-nRF5/blob/8f41ab685197bfc27b56705ee8a7f63f653344ae/libraries/Wire/Wire_nRF52.cpp#L132

    Working code

    #define MY_NODE_ID 67
    
    #define MY_RADIO_NRF5_ESB
    #include <MySensors.h>
    
    #include <SI7021.h>
    static SI7021 sensor;
    
    #define SLEEP_SHORT_MS (5000)
    #define LED_INFO_PIN (5)
    #define SLEEP_MS (30000)
    
    MyMessage            msgHum( 4, V_HUM );
    MyMessage           msgTemp( 5, V_TEMP );
    
    void setup() {
      pinMode( LED_INFO_PIN, OUTPUT );
      blink(LED_INFO_PIN, 5);
    }
     
    void present() {}
    
    void loop() {
      blink(LED_INFO_PIN, 1);
      sensor.begin(); //needs to be reinitialized after hack to disable
      const float temperature = float( sensor.getFahrenheitHundredths() ) / 100.0;
      const float humidity    = float( sensor.getHumidityBasisPoints() ) / 100.0;
    
      *(volatile uint32_t *)0x40004FFC = 0;
      *(volatile uint32_t *)0x40004FFC;
      *(volatile uint32_t *)0x40004FFC = 1;
      
      sleep(SLEEP_SHORT_MS);
        
      send( msgTemp.set( temperature, 2 ) );
    
      sleep(SLEEP_SHORT_MS);
      send( msgHum.set( humidity, 2) );
    
      sleep( SLEEP_MS );
    }
    
    void blink(uint8_t led, uint8_t count){
      for(int i = 0; i < count; i++){
        digitalWrite( led, HIGH );
        wait( 5 );
        digitalWrite( led, LOW );
        if( i < count - 1 ) wait(100);
      }
    }
    




  • thanks, i've been fighting with this (i think) in a 51822. I was reviving getting these working and i keep chewing through batteries.



  • @waspie Looks like there is a related issue with NRF51822
    #35 in https://infocenter.nordicsemi.com/pdf/nRF51822-pan_v2.0.pdf?cp=5_4_1_8

    But I don't think you'll need to do hack I listed above (not sure it'll even work for NRF51822). You can probably replace the three lines above with

    NRF_TWI0->ENABLE = 0;
    NRF_TWI1->ENABLE = 0;
    

    Just be sure to call Wire.begin() before each sensor read. Or if you're using a library, make sure you call the service that calls Wire.begin(), in my case that was sensor.begin().

    I'll try with one of my NRF51 modules tomorrow and report back.



  • @ncollins said in High power consumption NRF52832 & SI7021:

    NRF_TWI0->ENABLE = 0;
    NRF_TWI1->ENABLE = 0;

    thanks, added those lines after reading and an appropriate .begin prior and it compiled and sent and works so far.
    Won't know about consumption for a while - it doesn't act up while I'm watching it... it seems to get stuck at some point (1 week? 2 weeks? 10 days?) and then dies. And yes, it is set to reboot every 24 hours 🙂

    So it's something else you or I have not pinpointed yet.



  • @waspie Mind sharing your sketch?

    I've run into a few issues with NRF51 modules:

    • Using attachInterrupt leads to at least 1ma power consumption. This can be worked around with the LPCOMP approach that's mentioned in several threads
    • LPCOMP stops registering interrupts after reading internal battery. Something to do with the hwCPUvoltage call taking over LPCOMP and not restoring initial values. You can just call your LPCOMP activate code after battery read

    Issues with all NRF5 modules:



  • @ncollins
    Thanks, I backed off the changed when I read the one pull that got reversed. Hadn't seen there was an update.

    Im not using any interrupts on my NRF51 modules - only si7021/htu21s

    thanks for the update on the PRs. I'll give that a go after I see how long the battery lasts this go 'round.
    So far holding steady at 3+ volts with 3 minute read times but again, it does go for a while before randomly killing itself.



  • @ncollins sure:

    be aware, i'm not a coder. i just hack crap together to the point that it works then move on.

    
    
    // SUMMARY: This demo sketch runs on MultiSensor Version 7 board with an I2C Si7021 module to transmit temperature, humidity, and battery voltage to a MySensors gateway using MySensors protocols.
    
    // Note: because this is a passive node, node ID must be set manually to a unique sensor node ID:
    #define MY_NODE_ID 150  // Passive mode requires static node ID
    
    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2017 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * REVISION HISTORY
     * Version 1.0 - tekka
     *
     * DESCRIPTION
     * Passive node example: This is a passive & independent reporting node
     *
     */
    
    // This demo sketch uses the LowPowerLab SI7021 library and also some of its sample code:  https://github.com/LowPowerLab/SI7021
    
    // This demo sketch also draws from the MySensor's example MockMySensors sketch.
    
    // This demo sketch also draws from some of the code posted by smilvert here: https://forum.mysensors.org/topic/7961/why-do-passive-nodes-need-to-set-their-node-id-manually/14
    
    
    #define SHORT_WAIT 50
    
    #include <Wire.h>
    #include <SparkFunHTU21D.h>
    
    HTU21D myHumidity;
    
    // Enable debug prints
    //#define MY_DEBUG
    
    // Enable passive mode
    #define MY_PASSIVE_NODE
    #define MY_PARENT_NODE_IS_STATIC
    #define MY_PARENT_NODE_ID 0
    #define MY_TRANSPORT_MAX_TSM_FAILURES 2
    #define MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS 3000
    #define MY_TRANSPORT_WAIT_READY_MS 10000
    #define MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS 5000
    // Enable and select radio type attached
    //#define MY_RADIO_NRF24
    #define MY_RADIO_NRF5_ESB
    //#define MY_RADIO_RFM69
    //#define MY_RADIO_RFM95
    
    
    
    
    #include <MySensors.h>
    
    #define CHILD_ID_TEMP 0  //definitions contributed by smilvert (see above credit)
    #define CHILD_ID_HUM 1
    
    // Initialize general message
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    
    #define ID_S_MULTIMETER        28
    MyMessage msg_S_MULTIMETER_V_VOLTAGE(ID_S_MULTIMETER,V_VOLTAGE);
    //float lastTemperature=0;
    float lastSentTemp=0;
    int lastSentHumd=0;
    //float lastHumidity=0;
    float lastVoltage=0;
    float batteryVoltage=0;  
    float temperature=0;
    int humidity=0;
    unsigned long time;
    
    void setup()
    {
      myHumidity.begin();
      
      NRF_CLOCK->INTENSET=B11;  //enable interrupts for EVENTS_HFCLKSTARTED and  EVENTS_LFCLKSTARTED
      NRF_CLOCK->TASKS_HFCLKSTART=1;  //start the high frequency crystal oscillator clock
      while (!(NRF_CLOCK->EVENTS_HFCLKSTARTED)) {} //wait until high frequency crystal oscillator clock is up to speed and working
      wait(SHORT_WAIT);
    }
    
    void presentation()
    {
    	// Send the sketch version information to the gateway and controller
    	sendSketchInfo("NRF51822 Temp & Humidity", "1.0");
    
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID_TEMP, S_TEMP);
      wait(SHORT_WAIT);
      present(CHILD_ID_HUM, S_HUM);
      wait(SHORT_WAIT);
      present(ID_S_MULTIMETER,S_MULTIMETER,"Electric Station");
      wait(SHORT_WAIT);
    }
    
    
    void loop() {
      myHumidity.begin(); //power consumption add
        // get humidity and temperature in one shot, saves power because sensor takes temperature when doing humidity anyway
        float temperature = myHumidity.readTemperature();
        temperature = (temperature*1.8)+32;
        wait(SHORT_WAIT);
        float humidity = myHumidity.readHumidity();
        
        //temperature = float(temperature*1.8)+32;
        batteryVoltage=((float)hwCPUVoltage())/1000.0;  //take voltage measurement after transmission to hopefully measure lowest voltage that occurs.
    
    	if ( (temperature > lastSentTemp + .1) || (temperature < lastSentTemp - .1) ) {
    		send(msgTemp.set(temperature,2));
    		lastSentTemp = temperature;
    	}
    
    	if ( (humidity > lastSentHumd + 1) || (humidity < lastSentHumd - 1) ){
    		send(msgHum.set(humidity,0));
    		lastSentHumd = humidity;
    	}
    
      //if ( batteryVoltage > (lastVoltage+.1) || batteryVoltage < (lastVoltage-.1) ) {
        send(msg_S_MULTIMETER_V_VOLTAGE.set(batteryVoltage,2));  //send battery voltage with 2 decimal places
        //lastVoltage = batteryVoltage;
      //}
      time = millis();
        if (time > 64800000 ) {
          reboot();
        }
      NRF_TWI0->ENABLE = 0; //possible power consumption adds
      NRF_TWI1->ENABLE = 0;
      sleep(180000);  //sleep for three minutes
    }
    
    void reboot() {
      wdt_disable();
      wdt_enable(WDTO_15MS);
      while (1) {}
    }
    


  • @waspie Thanks for sharing. First thing I notice is you can probably remove:

      NRF_CLOCK->INTENSET=B11; 
      NRF_CLOCK->TASKS_HFCLKSTART=1;  
      while (!(NRF_CLOCK->EVENTS_HFCLKSTARTED)) {} 
    

    from your setup(). I believe this is legacy code that is now built in to MySensors / nRF5-arduino, and managed based on the features you're utilizing.

    I just tested power consumption on NRF51822 with SI7021. Similar to your sketch but using the LowPowerLab SI7021 library.

    I didn't have to do any hack or workaround to get ~7uA power consumption.
    IMG_1273.JPG

    I'm using MySensors 2.3.2, SandeepMistry/nRF-Arduino 0.6. Just to be sure, I also reburned the bootloader.

    I will try to get your sketch running on my NRF51, see if I can rule out the specific library as a cause for your power issues.

    #define MY_RADIO_NRF5_ESB
    
    #define MY_NODE_ID 68
    #define MY_PARENT_NODE_ID 13
    #define MY_PARENT_NODE_IS_STATIC
    #define MY_PASSIVE_NODE
    #define MY_TRANSPORT_UPLINK_CHECK_DISABLED
    #define MY_TRANSPORT_CHKUPL_INTERVAL_MS 2000
    #define MY_TRANSPORT_WAIT_READY_MS  1000
    #define MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS 2000
    
    #define SLEEP_SHORT_MS (5000)
    
    #define SLEEP_MS 1000 * 60 * 1
    
    #define REBOOT_HRS 24
    #define REBOOT_MS 1000 * 60 * 60 * REBOOT_HRS
    #define BATTERY_SEND_MS REBOOT_MS
    
    unsigned long sleepTime = BATTERY_SEND_MS;
    unsigned long lastReboot = 0;
    unsigned long lastBatterySent = 0;
    unsigned long lastTemperatureSent = 0;
    bool firstBoot = true;
    
    #include <MySensors.h>
    #include <SI7021.h>
    
    MyMessage     msgBattery( 1, V_VOLTAGE );
    MyMessage msgTemperature( 3, V_TEMP );
    MyMessage    msgHumidity( 4, V_HUM );
    
    static SI7021 sensor;
    
    void setup() {
      enableReset();
      sensor.begin();
    }
    
    void loop() {
      bool sendBattery = millis() - lastBatterySent >= BATTERY_SEND_MS || firstBoot;
      bool shouldReboot = millis() - lastReboot >= REBOOT_MS;
    
      const float temperature = float( sensor.getFahrenheitHundredths() ) / 100.0;
      const float humidity    = float( sensor.getHumidityBasisPoints() ) / 100.0;
    
      sleep(SLEEP_SHORT_MS);
        
      send( msgTemperature.set( temperature, 2 ) );
    
      sleep(SLEEP_SHORT_MS);
      
      send( msgHumidity.set( humidity, 2) );
      
      if(sendBattery){
        sleep(SLEEP_SHORT_MS);
        bool sent = send(msgBattery.set(getInternalVoltage(),3));
        if(sent) lastBatterySent = millis();
      }
    
      if(shouldReboot){
        lastReboot = millis();
        hwReboot();
      }
    
      firstBoot = false;
      
      sleep(SLEEP_MS);
    }
    
    void present() {}
    
    float getInternalVoltage(){
      return ((float)hwCPUVoltage())/1000.0;
    }
    
    void enableReset(){
      NRF_POWER->RESET = 1;
      while (NRF_POWER->RESET != 1);
    }
    


  • @ncollins thanks bud!

    with the htu21 the sleeping consumption is sub 5ua. its been 4 days and hovering around 3 volts. i'm keeping my fingers crossed. Would love to reliably use these. Since I had so much trouble with them I designed and put into use atmega328p boards quite a while ago now so I'm happy with those but I still had a crap ton of these nrf51 and nrf52 boards made thinking i would get a lot of use out of them.

    Things are improving. With some of the more recent developments and the reboot strategy I at least have reliable motion sensors working now. They've been up for about 2 months now, huge improvement!



  • it happened...i'm losing it already.
    3e0350bd-d03f-4284-929b-503e2202682e-image.png



  • I think it's a symptom of the "deadlock" scenario. I had a similar experience with NRF51 soil level sensors that were on the edge of their usable range. Looks like they get stuck in a loop, drain a huge amount of power (these were AA and AAA LiFePO4), trigger undervoltage/brown out, then restart, effectively clearing the deadlock.

    I'm guessing that high interference or weak signal (too far away) increases the number of transmission attempts, compounding the likelihood of lockup.

    Screen Shot 2020-12-09 at 8.36.55 AM.png



  • I think that's an accurate description. Range won't be a factor this time in particular as its probably 10 feet (3 meters) away from the parent. I'll grab it and reflash it in a few days with the updated code.

    I see our graphs show identical behavior, interesting.

    edit
    If I want to try out the new code is this the one i'm after:
    https://github.com/mysensors/MySensors/pull/1455

    ? Its a little unclear to me



  • @waspie I haven't tried the code from the redesign branch, as there are a lot of additional enhancements that may not have been fully tested yet.

    I've been testing this file on NRF52s, hal/transport/NRF5_ESB/driver/Radio_ESB.cpp, specifically from this commit https://github.com/mysensors/MySensors/pull/1448/files.

    Given the redesign merge request was submitted a few days after this Fix ESB deadlock, the Fix ESB Deadlock might not be that effective. I haven't been testing on NRF51.

    I'd suggest asking on github, as a comment on the NRF5 ESB redesign commit, for suggestions on the best way to test the latest improvements.



  • that's the reversion isn't it? so wouldn't that be the same as no changes at all? or is this supposed to be the pre-reversion test fix? i think i'll try that code in 1455. nothing to lose but another cr2032 heh

    good idea on asking, will do



  • @waspie ...potentially. It's a little confusing, to be honest.

    I used #1448 based on this comment in #1445 (the revision commit).
    Screen Shot 2020-12-10 at 3.44.31 PM.png



  • @ncollins 1455 is the latest and greatest
    https://github.com/mysensors/MySensors/pull/1455
    d00616 replied to use it.

    6 days on no dip (yet)

    edit i guess its 3 days since the spike (plugged in) was on 12/10

    df543d7f-e870-4e25-bc24-3fa9849b0db2-image.png



  • @waspie Looking a lot better. This node is in the same location that it was before the update?



  • @ncollins
    yep!
    while its only a few days I'm not seeing those dips that you can notice prior to the big drop. might be nothing, might be something. who know!



  • @waspie said in High power consumption NRF52832 & SI7021:

    1455 is the latest and greatest

    so would it be a good idea to flash all my nodes? got 10 laying around..:)



  • @Omemanti
    If you're experiencing this issue I'd certainly try 1. I don't know that I'd got hog wild just yet unless they're easy to get to and easy to hook up.



  • I don't know if any of you guys are still around and using this stuff -
    I moved and am reviving a few of these 51/52 boards that I had built. Prior to moving I had decent luck with all these fixes though I don't quite remember where I was with any of this stuff seeing as it was 3 years ago.

    I had a few motion sensors and some temp/humd based on these fixes and they were working great, no dips.

    Not sure any of you will ever see this but hey it all worked.


Log in to reply
 

Suggested Topics

  • 3
  • 1
  • 2
  • 6
  • 1

59
Online

11.4k
Users

11.1k
Topics

112.6k
Posts