Go Down

Topic: Lowest consumption issue (Read 4562 times) previous topic - next topic

jmsalomr

Hi,

Removing the pin initialization, in my case gives me just 17 uA in both sleep() and deepSleep() modes. No differences between them. Good numbers!

Best regards.

Gormd

Hej jmsalomr

Sounds like you are having some funn with Sigfox - my I ask what you are going to do in the agriculture area?

I have actually had some practice with the MKRFOX1200 now - in the field it works nicely, but connected to the computer for compiling from the Arduiono IDE - it really has its own life :-)

Would be nice to hear your experience with the SiPy and Sigfox comparing to MKRFOX1200:-)

Best regards

sslupsky

Hi Gormd,  I read with interest your suggestions regarding attaching the interrupt.  Indeed, when I do this the board reset and sleep function are reliable.  I was also able to achieve a reliable sleep() and reset if I instantiated an RTCZero object and invoked the begin() method.  I am wondering if you have any thoughts on this?

Code: [Select]

RTCZero rtc;

setup() {
  rtc.begin(false);
}



I took a dive into the ArduinoLowPower code and (the RTCZero library on which it depends) and it appears to me that the attachment of the interrupt is handled by the sleep() method?  See the attached code snippets from ArduinoLowPower.cpp.  It is odd to me that this doesn't appear to be working.  The ArduinoLowPower class instantiates an RTCZero object in the private section.  So, it is my understanding, attaching an interrupt as you described would require instantiating another RTC object?  Shouldn't there be a compiler error if you attempt to use attachInterrupt on a private object?

Code: [Select]

class ArduinoLowPowerClass {
public:
void idle(void);
void idle(uint32_t millis);
void idle(int millis) {
idle((uint32_t)millis);
}

void sleep(void);
void sleep(uint32_t millis);
void sleep(int millis) {
sleep((uint32_t)millis);
}

void deepSleep(void);
void deepSleep(uint32_t millis);
void deepSleep(int millis) {
deepSleep((uint32_t)millis);
}

void attachInterruptWakeup(uint32_t pin, voidFuncPtr callback, uint32_t mode);

#ifdef BOARD_HAS_COMPANION_CHIP
void companionLowPowerCallback(onOffFuncPtr callback) {
companionSleepCB = callback;
}
void companionSleep() {
companionSleepCB(true);
}
void companionWakeup() {
companionSleepCB(false);
}
#endif

#ifdef ARDUINO_ARCH_NRF52
void enableWakeupFrom(wakeup_reason peripheral, uint32_t pin = 0xFF, uint32_t event = 0xFF, uint32_t option = 0xFF);
wakeup_reason wakeupReason();
#endif

private:
void setAlarmIn(uint32_t millis);
#ifdef ARDUINO_ARCH_SAMD
RTCZero rtc;
#endif
#ifdef BOARD_HAS_COMPANION_CHIP
void (*companionSleepCB)(bool);
#endif
};


Code: [Select]

void ArduinoLowPowerClass::idle(uint32_t millis) {
setAlarmIn(millis);
idle();
}

void ArduinoLowPowerClass::setAlarmIn(uint32_t millis) {

if (!rtc.isConfigured()) {
attachInterruptWakeup(RTC_ALARM_WAKEUP, NULL, 0);
}

uint32_t now = rtc.getEpoch();
rtc.setAlarmEpoch(now + millis/1000);
rtc.enableAlarm(rtc.MATCH_HHMMSS);
}

void ArduinoLowPowerClass::attachInterruptWakeup(uint32_t pin, voidFuncPtr callback, uint32_t mode) {

if (pin > PINS_COUNT) {
// check for external wakeup sources
// RTC library should call this API to enable the alarm subsystem
switch (pin) {
case RTC_ALARM_WAKEUP:
rtc.begin(false);
rtc.attachInterrupt(callback);
/*case UART_WAKEUP:*/
}
return;
}

EExt_Interrupts in = g_APinDescription[pin].ulExtInt;
if (in == NOT_AN_INTERRUPT || in == EXTERNAL_INT_NMI)
    return;

//pinMode(pin, INPUT_PULLUP);
attachInterrupt(pin, callback, mode);

// enable EIC clock
GCLK->CLKCTRL.bit.CLKEN = 0; //disable GCLK module
while (GCLK->STATUS.bit.SYNCBUSY);

GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK6 | GCLK_CLKCTRL_ID( GCM_EIC )) ;  //EIC clock switched on GCLK6
while (GCLK->STATUS.bit.SYNCBUSY);

GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(6));  //source for GCLK6 is OSCULP32K
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);

GCLK->GENCTRL.bit.RUNSTDBY = 1;  //GCLK6 run standby
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);

// Enable wakeup capability on pin in case being used during sleep
EIC->WAKEUP.reg |= (1 << in);

/* Errata: Make sure that the Flash does not power all the way down
      * when in sleep mode. */

NVMCTRL->CTRLB.bit.SLEEPPRM = NVMCTRL_CTRLB_SLEEPPRM_DISABLED_Val;
}



Finally, have you by chance tried the same on a MKRWAN1300?  I cannot seem to get the MKRWAN1300 below 1.16mA.  I have removed the pin initialization from wiring.c and used the method suggested here to attach the interrupt.  Still 1.16mA.  I am trying to ascertain if the current is being used by the SAMD or the Murata LoRa module but its difficult to tell.

Thank you and kind regards,

sslupsky

Hi jmsalomr,

Would it be possible for you to post your sketch that achieved the 17uA ?

Thank you,

sslupsky

For anyone following this thread, there is a hardware problem with the MKRWAN1300 that prevents it from achieving a sleep current below 1.15mA.  There will be a board revision to 2.0 that will correct the problem.

Go Up