Author Topic: Low power sleep and Reset  (Read 3505 times)

mlewus

  • NewMember
  • *
  • Posts: 9
Low power sleep and Reset
« on: August 09, 2018, 04:32:58 PM »
 I have been experimenting with the M0 as more powerful replacement for the ATMega328 in a sensor node network.  i’ve been having considerable difficulty getting low power mode to work properly. I am using a new unmodified Moteino M0 powered through the lithium ion battery port to avoid the battery charger consuming current. I am using the same low power example script from the Moteino M0 guide page that resets the FLASH and RFM69 for lowest power.  The only change is that I am not using any serial output  and I added a trap to stop the program if the flash or radio do not init properly

Here is the problem. When I apply power, the board initializes and then goes into sleep mode where it consumes less than 10 µA. However, if I press the reset button on the board, it restarts but the Winbond Flash init fails. If I press the reset button a second time the flash initializes ok and goes into sleep. The radio also appears to initialize and go into sleep. But now the board consumes 1.5mA which implies the radio did not go to sleep. Further resets also lead to power draws of 1.5mA.  The only way to fix it is to disconnect the power at which point he goes back to 10 µA.

The sketch simply puts the radio and flash to sleep and then goes into a deep sleep loop, waking briefly every 10 seconds. So there’s no opportunity for any sort of conflict between interrupts on the mcu/radio/flash or anything of that nature.

The reset button completely and asynchronously resets the MCU but does not hardware reset the memory chip or the radio, so there is a lot of opportunity for mayhem after MCU reset.

Has anyone else seen this problem?

.

Uncle Buzz

  • Full Member
  • ***
  • Posts: 146
  • Country: fr
Re: Low power sleep and Reset
« Reply #1 on: August 09, 2018, 05:14:27 PM »
I think the reset function is for the MCU only, so the SAMD21 is reseting and restart the sketch, and try to initialize radio and flash while they are sleeping from previous run.
Maybe the first try to initialize the flash while it's sleeping wakes it up, so at second reset of the MCU it will reply correctly, but the radio needs more communication to wake up.
It's only an assumption, some other guys could have better answers.

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: Low power sleep and Reset
« Reply #2 on: August 10, 2018, 09:17:04 AM »
Guys,
I appreciate the feedback, details and suggestions,

I will need to look into this and try to reproduce it, certainly something of interest to resolve if possible.

The 4MBIT Windbond chip I use (since introduction) has a default sleep mode (not the lowest) which it enters even if you don't use it.
If you specifically put it to sleep then it needs a certain way to be woken up or it will not respond.
Code that queries it any other way may get stuck if not done properly (fail safe).
So there might be a bug somewhere in the bootloader, will need to see.

mlewus, - In the interim, could you share your exact modified code, might save me a little time.
Thanks!!

mlewus

  • NewMember
  • *
  • Posts: 9
Re: Low power sleep and Reset
« Reply #3 on: August 10, 2018, 02:37:18 PM »
Here is the code I used:
Code: [Select]
  //Standby sleep example for MoteinoM0 with external interrupt wakeup
//expected current in standby sleep: 7.5uA
const int pin = 0; //pin to use as interrupt (can be any digital pin)

#define WITHRFM69  //comment this out if you don't have a radio installed on your MoteinoM0

#ifdef WITHRFM69
  #include <RFM69.h>    //get it here: https://www.github.com/lowpowerlab/rfm69
  #define NODEID        2   //must be unique for each node on same network (range up to 254, 255 is used for broadcast)
  #define NETWORKID     100  //the same on all nodes that talk to each other (range up to 255)
  #define GATEWAYID     1
  #define FREQUENCY     RF69_915MHZ
  #define IS_RFM69HW    //uncomment only for RFM69HW! Leave out if you have RFM69W!
  RFM69 radio;
#endif
  #define SS_FLASHMEM 8
#include <SPIFlash.h> //get it here: https://www.github.com/lowpowerlab/spiflash
SPIFlash flash(SS_FLASHMEM, 0xEF30); //EF30 for 4mbit  Windbond chip (W25X40CL)

void setup()
{
  delay(500);
  pinMode(13, OUTPUT);
  pinMode(0, INPUT); //don't use internal pullup min power, makes pin 0 active low
  attachInterrupt(pin, wakeupISR, HIGH); //note: RISING and FALLING do not seem to work, use OW or HIGH
  while (!flash.initialize()){
  blink(25);   
  }
  flash.sleep();

#ifdef WITHRFM69
  while(!radio.initialize(FREQUENCY,NODEID,NETWORKID))
      blink(250); 
 
  #ifdef IS_RFM69HW
    radio.setHighPower(); //uncomment only for RFM69HW!
  #endif
    radio.sleep();
#endif

  for (byte count=0; count < 5; count++)
  {
    blink(250);
  }
}

void loop()
{
  standbySleep();

  //interrupt happened: WAKE UP and blink the LED!
  blink(50);
}

void blink(int ms) {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(ms);
  digitalWrite(LED_BUILTIN, LOW);
  delay(ms);
}

byte toggle=true;
void wakeupISR(void)
{
  //nothing here, just a placeholder
}

void standbySleep() {
  //Disable USB (optional)
  USBDevice.detach(); // make sure USB turned off

  //Standby - lowest power sleep mode
  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
  __DSB();
  __WFI(); // Wait For Interrupt call

  //Sleep until woken by interrupt...

  //Enable USB
  USBDevice.attach();
}

Something very strange is going on here. I tried adding
Code: [Select]
flash.wakeup();
before 
Code: [Select]
while (!flash.initialize()){
to make sure the device was not sleeping. It worked. I was able to reset multiple times and the flash init did not get stuck. Now hang on to your foil hats... I removed that change from the code just to verify I had it solved, and it still worked. I tried this on a second new board and got the same result so it's not a fluke. It won't init after reset until you send it a wakeup() command prior to flash.initialize() exactly once. Then it's happy to initialize after processor reset without the wakeup() command.

The datasheet (p.30) says
Quote
While in the power-down state only the Release from Power-down / Device ID instruction, which restores the device to normal operation, will be recognized. All other instructions are ignored.

That would have explained why the wakeup() call fixed it, but a quick look at the library shows that SPIFlash::initialiaze() already calls wakeup() prior to doing any other operations, so the wakeup() call I made from setup() should not have had any effect. But it did.

I am going to leave my wakeup() call in setup() and move on. If I can be of any assistance with troubleshooting this further please let me know.

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: Low power sleep and Reset
« Reply #4 on: August 10, 2018, 02:46:19 PM »
Something very strange is going on here. I tried adding
Code: [Select]
flash.wakeup();
before 
Code: [Select]
while (!flash.initialize()){
to make sure the device was not sleeping. It worked. I was able to reset multiple times and the flash init did not get stuck. Now hang on to your foil hats... I removed that change from the code just to verify I had it solved, and it still worked. I tried this on a second new board and got the same result so it's not a fluke. It won't init after reset until you send it a wakeup() command prior to flash.initialize() exactly once. Then it's happy to initialize after processor reset without the wakeup() command.

The datasheet (p.30) says
That would have explained why the wakeup() call fixed it, but a quick look at the library shows that SPIFlash::initialiaze() already calls wakeup() prior to doing any other operations, so the wakeup() call I made from setup() should not have had any effect. But it did.

I am going to leave my wakeup() call in setup() and move on. If I can be of any assistance with troubleshooting this further please let me know.

I think that makes a lot of sense and completely explains this behavior. I was thinking perhaps the bootloader triggers something on the FLASH-MEM causing it to fail to re-initialize but it's not within the bootloader's responsibility to sleep or wakeup the flash. The FLASH-MEM is supposed to be awake right after an OTA transfer, waiting for a software reset and bootloader doing the reflash. So we're good on the bootloader then.

This means IF you decide to explicitly sleep() the FLASH, you have to explicitly call wakeup() or it becomes unresponsive (unless power is cycled).
Which also means if resets are expected then wakeup() should be called() before initialize because it causes no harm even if the flash was somehow not sleeping.

So we have a solution, and a question -  should this wakeup() call be in the flash.initialize() in the first place to save people the trouble or running into this themselves?

mlewus

  • NewMember
  • *
  • Posts: 9
Re: Low power sleep and Reset
« Reply #5 on: August 11, 2018, 12:31:47 PM »
I looked at the library and wakeup()  is already there,  in the initialize function. Here is the code from the github SPIFlash.cpp master branch:
Code: [Select]
/// setup SPI, read device ID etc...
boolean SPIFlash::initialize()
{
#if defined (SPCR) && defined (SPSR)
  _SPCR = SPCR;
  _SPSR = SPSR;
#endif
  pinMode(_slaveSelectPin, OUTPUT);
  SPI.begin();
#ifdef SPI_HAS_TRANSACTION
  _settings = SPISettings(4000000, MSBFIRST, SPI_MODE0);
#endif

  unselect();
  wakeup();
 
  if (_jedecID == 0 || readDeviceId() == _jedecID) {
    command(SPIFLASH_STATUSWRITE, true); // Write Status Register
    SPI.transfer(0);                     // Global Unprotect
    unselect();
    return true;
  }
  return false;
}

And I still have not come up with an explanation for why I was able to remove the wake up call from my code after I woke it up once and now it works every time. Makes we wish I had a debugger and logic analyzer :)
« Last Edit: August 12, 2018, 03:49:41 AM by mlewus »

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: Low power sleep and Reset
« Reply #6 on: August 13, 2018, 11:15:10 AM »
Wow, I forgot I must have added that years ago!

mlewus

  • NewMember
  • *
  • Posts: 9
Re: Low power sleep and Reset [solved]
« Reply #7 on: August 13, 2018, 08:03:25 PM »
I’m guessing the wakep() call in the code being required (once) has something to do with SPIFlash::initialize() failing before it makes the call to SPIFlash::wakeup(), or it may be a timing problem. But alas, for me it’s too many projects and too little time. If anyone else runs into this I suggest using this code in setup. It adds a bit of delay to initialization but otherwise won’t hurt anything, and it has been proven on two different Moteino M0s.

Inside setup, add:
Code: [Select]
delay(10);
SPIFlash flashdev;
flashdev.wakeup();
.
.
.

Time to move on.