Huge current consumption due to setWatch() ?!?

Posted on
  • Hi everyone,

    I made a cooking timer with Espruino 2v01 based on a NRF52832 on a custom PCB. It has 2 buttons and a 7-segment led display. The display is off until the user presses any button. It then turns on and the user can set the timer and then start it. The display turns off after a few seconds, but can be turned on again if the user presses any button (so he/she can know when the timer will end). When the timer is finished, some leds on the PCB blink a few times to alert the user. He/she then has to press any button to stop the alarm.

    My cooking timer works functionally well but consumes a lot of energy. About 7 mA at 6V (I have a LDO lowering the voltage to 3.3V then). I'm sure it's due to my code because I can go below 100 uA if only the GPIO are configured correctly. I have noticed that if I clear the 4 setWatch() I have with the clearWatch() command, it goes back to normal (less than 1 mA when connected by BLE, about 100 uA when disconnected). I'm not familiar with the way Espruino handles low-power modes on the NRF52832, but it seems that the device cannot turn off the external quartz nor decrease its frequency, thus consummating the 7 mA.

    Can someone help me to understand what's happening ? I need the setWatch() to turn the display on when the user presses a button, so just removing them is not an option ;-) There is maybe another way to implement the behavior I need, I'm open to any suggestion.

    The code is optimized with "simple optimization" and is minifyed from 20530 bytes to 11597 bytes. Here are the process.memory() results when it consumes 7 mA (first and second lines), I then clear all setWatch() at line 3 and call process.memory() again. At this point, the whole board consumes 1 mA (because of the BLE connexion), then about 100 uA after a few seconds.

    >process.memory()
    ={ free: 1093, usage: 1157, total: 2250, history: 1000,  gc: 0, gctime: 4.79125976562, "stackEndAddress": 536924016, flash_start: 0, "flash_binary_end": 390268,  "flash_code_start": 442368, flash_length: 524288 }
    >clearWatch()
    =undefined
    >process.memory()
    ={ free: 1157, usage: 1093, total: 2250, history: 1006,  gc: 0, gctime: 4.57763671875, "stackEndAddress": 536924016, flash_start: 0, "flash_binary_end": 390268,
      "flash_code_start": 442368, flash_length: 524288 }
    

    The code is in copy if needed.

    Thank you and best regards.


    1 Attachment

  • Do you have pullup/down resistors on SWITCH1/2? If not I'd change the pinmode to input_pullup/down.

    setWatch itself adds maybe 10uA, however if the input is changing then it'll cause the device to wake up, using a bunch of power. If there's no pullup/down that'd definitely cause noise to come in and wake it up.

    Out of interest what are you using on your board? I imagine it's not the nRF52 directly - is it a module of some kind?

  • I have a pullup resistor for both switches, so it's not the cause =(

    Yes I use the NRF52832 directly. Both schematic and layout are home-made (I'm an electronic engineer).

  • I noticd the save(); at the end of the code. Give it a try without that.

    During development - until my code is settled - I use this

    setTimeout(onInit,999); // while dev'g - remove before upload for save()
    

    Using this timeout let's the upload 'thread' complete and then start as if it would be a power-on w/ saved code. At the same time it makes my development life cycles easy, because I do not need to type onInit(); into the console after every upload to get the code (ball) rolling, nor do I save 'half baked' / dynamic states.

    When I'm done w/ developing, I remove or comment this line, make an upload, and then enter save() in the console. That way I do not save any intermediate, not recoverable states, and also do not start things twice... because that could be some of your issues that you have races going on.

    Upload of code to Espruino is different from uploading code to Arduino or a-like. Yes, @Gordon catered for that mode too, but that is using switches in the ide... Having save() in the code (at the end of it) is for sure calling for trouble, because Espruino is not designed for that.

    Regarding the pull-up resistors: if they are fixed - external - you cannot control them with software. To achieve absolute low power use the pins need to be re-configured to not cause any load - current flow - on the pins. Could you measure what is going on in regard to current sourcing/sinking by (all) your pins? And since you are an electronic engineer I assume you already took of potential noise creation states that would last over extended time periods.

    PS: May need to make myself a bit more familiar w/ your code to see what it going on and what the used coding pattern mean compared to the patterns more familiar to me in Espruino context.

  • Sat 2019.03.30

    entire pp   'My cooking timer . . . but consumes a lot of energy. About 7 mA at 6V (I have a LDO lowering the voltage to 3.3V then). . . . (less than 1 mA when connected by BLE, about 100 uA when disconnected) . . . but it seems . . . thus consummating the 7 mA.'

    As I'm reading this, at normal operation, 100uA is observed and during a BLE event, 1mA is consumed. Where, when is the 7mA drain observed as this value is far in excess of normal operation? Are the readings before or after the LDO? What are the values of the pullups?

    Please clarify @benoit

    A quick look over of the code page didn't reveal any loops, so for now I'm guessing the code is not the culprit.

    It would help greatly if a snapshot of the schematic (regardless of doneness or completeness) and even a picture of the setup might provide us clues.

  • Yes I use the NRF52832 directly

    Wow, nice - I've always been a bit wary of trying to do my own aerials!

    Do you get the high power draw if you upload just the setWatch commands, or what if you make the functions they call empty?

  • Thank @allObjects for the explanation regarding the save() command, it's very interesting. I will remove it from my code and enter it manually as you suggest.

    To achieve absolute low power use the pins need to be re-configured to not cause any load - current flow - on the pins. Could you measure what is going on in regard to current sourcing/sinking by (all) your pins?

    Thanks for the suggestion, however as I tried to show with the clearWatch() command, the problem must be located in the code (or in the way Espruino handles low-power mode on the NRF52832) and not in the hardware. Since entering the clearWatch() instruction doesn't change any pin configuration, the issue must be elsewhere.

    As I'm reading this, at normal operation, 100uA is observed and during a BLE event, 1mA is consumed. Where, when is the 7mA drain observed as this value is far in excess of normal operation? Are the readings before or after the LDO? What are the values of the pullups?

    The 7 mA drain is observed when the setWatch() are "active". If I clear them, the current decreases to 100 uA. This current is measured with a multimeter directly from the laboratory voltage source, which is at 6V to simulate two 3V batteries in serie. I will post the schematic tomorrow.

    Do you get the high power draw if you upload just the setWatch commands, or what if you make the functions they call empty?

    I will try tomorrow.

    Thanks guys for your inputs :-)

  • I notice @benoit that enterBatteryCheckState() is called during "run" when any of the switchxRising/Falling() code is executed. What is the load that is seen by analogRead() and by the display update? Does the current drop after the five second timeout?

    Try commenting your some of the nested setTimout() sections as there is a lot going on there.

    Divide and conquer as @Gordon suggested. This is going to be fun! Keep us posted on what is discovered.

  • Does the current drop after the five second timeout?

    No, it stays at about 7 mA even after the 5 seconds timeout.

    Regarding the checkBatteryState(), I will get rid of the R2 resistor to definitely remove any current that could flow in R2/R3 (I made a mistake as Q1 is referenced to VBAT which is 6V, and I cannot turn it off with a 3.3V signal). However, this current is about 6V/(200K + 100K) = 20 uA and should be the cause of the 7 mA drain.

    Here some parts of the schematics.


    2 Attachments

    • timer_1.jpg
    • timer_2.jpg
  • You can try using setSleepIndicator/setBusyIndicator to show if the device is coming out of sleep mode because of the watches?

  • Hi everyone, I had to work on other projects so I haven't had much time to investigate further, sorry for that. I'm back on that issue since a few days and I have new info :)

    I flashed the same code on the nrf52832 dev kit, made by Nordic. So no pull-up resistor that might act weird nor manufacturing problem. However, I have exactly the same issue : the dev board draws more than 7 mA when programmed.

    I manually copied-pasted my code function after function to see when it starts to draw 7 mA (it draws about 1.5 mA when connected with BLE, 0.5 mA in low power mode, so no hardware cause). I discovered that the current jumps to 7 mA when the free memory goes below 1300. Here is what I tried. I run espruino 2v01 for the record =)

    // I just copied-pasted my code before that lign, to fill the memory. The board draws about 1.5 mA up to now
    >process.memory()
    ={ free: 1302, usage: 948, total: 2250, history: 1189,
      gc: 0, gctime: 3.47900390625, "stackEndAddress": 536924016, flash_start: 0, "flash_binary_end": 390268,
      "flash_code_start": 442368, flash_length: 524288 }
    >var aa = "test"
    ="test"
    // it starts to draw more than 7 mA right at this moment
    >process.memory()
    ={ free: 1300, usage: 950, total: 2250, history: 1192,
      gc: 0, gctime: 3.47900390625, "stackEndAddress": 536924016, flash_start: 0, "flash_binary_end": 390268,
      "flash_code_start": 442368, flash_length: 524288 }
    

    So the problem is definitly not on the hardware side. It thus seems it's a memory issue and finally not a setwatch issue. Did somebody have the same issue ? Any idea how to fix it ?

    Thanks for your help :)

  • That is extremely odd. Could it be at all related to the code that is in it? Or could you try just filling up memory with something like a=new Uint8Array(20000); or similar.

    Espruino does attempt to do a garbage collect if there are less than 125 variable available, but that's not the case here at all. And even if it does do that it should only do it once when it has some free idle time.

  • Hi there,
    i have the same issue with setWatch. it increases on 400uA with setWatch. checked with pullup/down. looks like it loops reading pin without sleeping. NRF52832dk board

  • checked and it was because of i2c OLED ssd1306. seems to be this part consume a lot when board gone to sleep. Please, advice

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Huge current consumption due to setWatch() ?!?

Posted by Avatar for benoit @benoit

Actions