Arduino Forum

Products => MKR Boards => MKRFOX1200 => Topic started by: philgeek on Sep 08, 2017, 10:53 am

Title: Lowest consumption issue
Post by: philgeek on Sep 08, 2017, 10:53 am
Hello

When using my MKRFOX1200 supplied through 3.3V / Vin , I Can't get a lower consumption than 1.2 mA during LowPower.deepsleep(120000); instruction time (using <ArduinoLowPower.h>).

My test bench uses the simpliest hardware and software (nothing enabled, no LED ... ).

I've double checked this measure using my multimeter (very low quality) in serie (current measure) and in parallel (voltage measure) accross a 100 Ohm resistor in serie with the power supply : 120 mV drop ...

Unfortunately it is not enough efficient to be powered during monthes through a pair of AA alcaline batteries, even if my module sleeps always ... I was expecting less than 100 uA reading the Atmel SAMD data sheet ...

I could see two possible issues :

- The mkrfox1200 hardware design doesn't allow to get better results (ex. due to the clock input ... I don't know ...)
- The Arduino LowPower library doesn't do enough and could be optimized ...

As I've not got enough time to check by myself those two issues, I just hope that someone or a support can tell me what objective can be set  and how to proceed in order to get it. I wouldn't like to spend efforts targetting a non feasible objective, and some other messages on the forum are not enough conclusive on this topic ...

Sleep mode conumption parameter should be written in the MKRFOX1200 documentation, when it's said that the board can be supplied through AA batteries ...

Sorry for the English and the message form, I'm constrained by a Parkinson disease ... however compatible Arduino practice  :)
Title: Re: Lowest consumption issue
Post by: philgeek on Sep 08, 2017, 01:35 pm
I did a mistake in my description, sorry : the board is supplied through the battery connector and not through Vin !
Title: Re: Lowest consumption issue
Post by: philgeek on Sep 11, 2017, 07:36 pm
I've got a piece of information from technical support / Carla :

"After run some tests on this board, we have reached 300uA with a MKR Fox 1200, so we recommend you to update the low power library to get the improvements."


I had not yet time enough to experiment. I've seen on github a 1.2.0 version (instead of 1.0.0 in my Arduino IDE) but I can't see any major change which could improve my configuration. Anyway, I will do the comparison, for sure.

And now, I know the target/feasibility thanks to Carla.

Again, I would appreciate to get results from others. Thanks. Philippe.
Title: Re: Lowest consumption issue
Post by: philgeek on Sep 12, 2017, 10:50 am
Reading the code of the low power library, I can see that the option BOARD_HAS_COMPANION_CHIP is not setup. Unfortunately this doesn't give us the capability to use the instruction LowPower.companionSleep(); and to ensure that the sigfox module by itself is set in deep sleep mode as well as the SAMD CPU.

In my test bench I did'nt initialised the sigfox module. I was expecting  the sigfox module to be its lowest consumption mode after reset. Furthermore I didn't call a SigFox.end() instruction. Maybe the mistake is there, I don't know ...

I definitively would appreciate to get support on this topic.

Please tell me anyway how you've got  happy with the lifetime of your "AA" battery back !

Philippe.
Title: Re: Lowest consumption issue
Post by: philgeek on Sep 13, 2017, 02:22 am
I've updated the Arduino Low Power library to 1.2.0, I've called sigfox.end();   : I get 500 uA (+/- 100 uA) during the sleep mode. Progress, yes, but not as much as expected reading the components data sheet + MKRFOX1200 schematics.

End of my posts on that subject.













Title: Re: Lowest consumption issue
Post by: philgeek on Sep 13, 2017, 05:35 pm
Sorry, but I'm coming again a last time in order to provide a fruitful issue .

I've tried "to remove  the pin initialization in wiring.c", as suggested in other forums :

https://github.com/arduino/ArduinoCore-samd/blob/master/cores/arduino/wiring.c#L85

And now my consumtion in standby is about 50uA, difficult to be more precise with my multimeter ...

I've not seen negative side effects, anyway.

I can close the topic as SOLVED, and maybe my trials will help others ...
Title: Re: Lowest consumption issue
Post by: nimasa on Mar 14, 2018, 08:25 pm
@philgeek, Wiring.C file in Arduino installation folder on my computer is completely different than this one and there is no pin initialization in it. Do I have to substitute it with the one on Github?
Title: Re: Lowest consumption issue
Post by: philgeek on Mar 18, 2018, 10:02 pm
Here is the updated file with comments & installation path added in the header. I hope this will help to get the low consumption figure on mkrfox1200.

Please take also into account the great benefits of a setup boost 3.3V circuit, which makes batttery life about 10 times longer. My reference is the NCP1402, and its implementation by Sparkfun.

/*
  Copyright (c) 2015 Arduino LLC.  All right reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the GNU Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Philgeek on www.philoc.fr
// Edited on 2018/03/17 thanks to question / my post on Arduino forum mkrfox1200/lowest consumption issue
// I just hope it can help but I cannot commit ;-)

// This file has been updated as I looked for the lowest consumption on mkrfox1200
// The modification below is tagged with "phg" embedded in the comment
// Only one line had to be placed as comment ...
// Notes :
// The path on my configuration is .arduino15/packages/arduino/hardware/samd/1..6.16/cores/arduino/wiring.c
// Notes / Prerequisites
// All unused components, and especially sigfox and usb must have been reset by your application before entering deep sleep
// And Arduino Low Power library must be in its 1.2.0 version, at least in my configuration
// Lastly check any pin configuration, be careful with pullups and leds ... but you did that already
// And at he end of the day, you should get around 50 mA, as I've got by myself ... because the data sheet figures & the mkrfox1200 schematics are done that way.
*/--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//
#include "Arduino.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
 * System Core Clock is at 1MHz (8MHz/8) at Reset.
 * It is switched to 48MHz in the Reset Handler (startup.c)
 */
uint32_t SystemCoreClock=1000000ul ;

/*
void calibrateADC()
{
  volatile uint32_t valeur = 0;

  for(int i = 0; i < 5; ++i)
  {
    ADC->SWTRIG.bit.START = 1;
    while( ADC->INTFLAG.bit.RESRDY == 0 || ADC->STATUS.bit.SYNCBUSY == 1 )
    {
      // Waiting for a complete conversion and complete synchronization
    }

    valeur += ADC->RESULT.bit.RESULT;
  }

  valeur = valeur/5;
}*/

/*
 * Arduino Zero board initialization
 *
 * Good to know:
 *   - At reset, ResetHandler did the system clock configuration. Core is running at 48MHz.
 *   - Watchdog is disabled by default, unless someone plays with NVM User page
 *   - During reset, all PORT lines are configured as inputs with input buffers, output buffers and pull disabled.
 */
void init( void )
{
  // Set Systick to 1ms interval, common to all Cortex-M variants
  if ( SysTick_Config( SystemCoreClock / 1000 ) )
  {
    // Capture error
    while ( 1 ) ;
  }
  NVIC_SetPriority (SysTick_IRQn,  (1 << __NVIC_PRIO_BITS) - 2);  /* set Priority for Systick Interrupt (2nd lowest) */

  // Clock PORT for Digital I/O
//  PM->APBBMASK.reg |= PM_APBBMASK_PORT ;
//
//  // Clock EIC for I/O interrupts
//  PM->APBAMASK.reg |= PM_APBAMASK_EIC ;

  // Clock SERCOM for Serial
  PM->APBCMASK.reg |= PM_APBCMASK_SERCOM0 | PM_APBCMASK_SERCOM1 | PM_APBCMASK_SERCOM2 | PM_APBCMASK_SERCOM3 | PM_APBCMASK_SERCOM4 | PM_APBCMASK_SERCOM5 ;

  // Clock TC/TCC for Pulse and Analog
  PM->APBCMASK.reg |= PM_APBCMASK_TCC0 | PM_APBCMASK_TCC1 | PM_APBCMASK_TCC2 | PM_APBCMASK_TC3 | PM_APBCMASK_TC4 | PM_APBCMASK_TC5 ;

  // Clock ADC/DAC for Analog
  PM->APBCMASK.reg |= PM_APBCMASK_ADC | PM_APBCMASK_DAC ;


  // Setup all pins (digital and analog) in INPUT mode (default is nothing)
  for (uint32_t ul = 0 ; ul < NUM_DIGITAL_PINS ; ul++ )
  {
 // modification - PHG - 2017-09-13 : line below suppressed in order to get lower consumption in standby /deep sleep mode '<50uA)
//    pinMode( ul, INPUT ) ;
  }

  // Initialize Analog Controller
  // Setting clock
  while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_ADC ) | // Generic Clock ADC
                      GCLK_CLKCTRL_GEN_GCLK0     | // Generic Clock Generator 0 is source
                      GCLK_CLKCTRL_CLKEN ;

  while( ADC->STATUS.bit.SYNCBUSY == 1 );          // Wait for synchronization of registers between the clock domains

  ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV512 |    // Divide Clock by 512.
                   ADC_CTRLB_RESSEL_10BIT;         // 10 bits resolution as default

  ADC->SAMPCTRL.reg = 0x3f;                        // Set max Sampling Time Length

  while( ADC->STATUS.bit.SYNCBUSY == 1 );          // Wait for synchronization of registers between the clock domains

  ADC->INPUTCTRL.reg = ADC_INPUTCTRL_MUXNEG_GND;   // No Negative input (Internal Ground)

  // Averaging (see datasheet table in AVGCTRL register description)
  ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_1 |    // 1 sample only (no oversampling nor averaging)
                     ADC_AVGCTRL_ADJRES(0x0ul);   // Adjusting result by 0

  analogReference( AR_DEFAULT ) ; // Analog Reference is AREF pin (3.3v)

  // Initialize DAC
  // Setting clock
  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY );
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_DAC ) | // Generic Clock ADC
                      GCLK_CLKCTRL_GEN_GCLK0     | // Generic Clock Generator 0 is source
                      GCLK_CLKCTRL_CLKEN ;

  while ( DAC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains
  DAC->CTRLB.reg = DAC_CTRLB_REFSEL_AVCC | // Using the 3.3V reference
                   DAC_CTRLB_EOEN ;        // External Output Enable (Vout)
}

#ifdef __cplusplus
}
#endif
Title: Re: Lowest consumption issue
Post by: Gormd on Jul 31, 2018, 11:10 am
Hi there philgeek

I have also tried the Mkrfox1200 in Lowpower deepspleep. (The board has its own way of behaving).

I need a board for long life. As a test I have put the board in deep sleep for intervals with a tmp36 temp measure sensor. I have measured the voltage  between vcc / ground and the current used by the sensor. When the board changed to sleeping mode the values did not change.

I think thats not good for a long battery life - did you find a way to make the board "total sleep" .
Title: Re: Lowest consumption issue
Post by: jmsalomr on Aug 01, 2018, 11:33 pm
Hi philgeek and Gormd,

I'm in a similar project and need a low power board.

Just beginning tests, so I will take advantage of your work and keep you also updated about my progresses.

I cant't find wiring.c in my installation. Where should I find it in a MAC OS X installation?

And, what do you mean philgeek with setup boost 3.3V circuit? It's an additional circuit I should put in front of the board? Could you give more information?

By the moment I'm feeding the board using 2xAA cells.

Best regards.
Title: Re: Lowest consumption issue
Post by: jmsalomr on Aug 02, 2018, 12:40 am
Hi,

I finally found wiring.c and it looks like the one indicated by philgeek.

Regarding the functions to get the board into sleep mode, I have seen that using LowPower.sleep() function the board awakes without problem, but using LowPower.deepsleep() freezes the board and doesn'n wake up. Have you experienced the same problem?

I've seen one post talking about the same problem, but there is no answers.

I have still not made any mesure about the power consumption.

I'll try tomorrow, maybe.

Keep you updated.

Title: Re: Lowest consumption issue
Post by: jmsalomr on Aug 02, 2018, 01:16 am
Update.

Neither the sleep() nor the deepSleep() functions work. And I'm pretty sure they were working in the first tests. I have never changed any core library. Any suggestion?

It's really weird...

Maybe a kind of hard reset? ...
Title: Re: Lowest consumption issue
Post by: Gormd on Aug 03, 2018, 04:16 pm
Hi jmsalomr

A lot of time can be "spild" on this - sometimes its working - sometimes not.

When you use sleep(yourtime to wakeup) you have to add the:
LowPower.attachInterruptWakeup(RTC_ALARM_WAKEUP, alarmEvent0, CHANGE); -in your void setup().. that worked for me.

Have not tried to use the deepsleep - I will try it now....

What will you use your Mkrfox1200 for?

(be aware, that if you have your deve going in sleep mode you have a hard time to connect it to your usb!!)
Title: Re: Lowest consumption issue
Post by: Gormd on Aug 03, 2018, 04:34 pm
Hi there

Deepsleep is also ok with attachInterruptWakeup as mentioned.


Title: Re: Lowest consumption issue
Post by: jmsalomr on Aug 07, 2018, 12:40 am
Hi Gormd,

It was a little bit weird, but it works for me now. I have just to disconnect the board and connect it again. If I left it connected through the USB, even if I push the reset button, it doesn't work - no wake up. But if I disconnect the board and I connect it again, it works. Both with sleep() and deepSleep(). It seems I need just a switch off.

I've been measuring with both sleep() and deepSleep(), without SigFox initialization, and I measure 350 uA in sleep() and deepSleep() modes. No differences between them.

I'm using MKRFOX1200 for an agriculture application. I've been testing Pycom SiPy + PySense with quite good results, but I would like also to test this board.

I'm going to test removing the pin initialization from wiring.c.
Title: Re: Lowest consumption issue
Post by: jmsalomr on Aug 07, 2018, 09:01 am
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.
Title: Re: Lowest consumption issue
Post by: Gormd on Aug 08, 2018, 03:51 pm
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
Title: Re: Lowest consumption issue
Post by: sslupsky on Sep 14, 2018, 06:13 pm
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,
Title: Re: Lowest consumption issue
Post by: sslupsky on Sep 14, 2018, 06:42 pm
Hi jmsalomr,

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

Thank you,
Title: Re: Lowest consumption issue
Post by: sslupsky on Sep 17, 2018, 10:29 pm
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.
Title: Re: Lowest consumption issue
Post by: pierrot10 on Dec 11, 2018, 10:37 pm
Dear all
Thank for this convrsation. I have a similar problem but I am still testing Arduino Low Power, but apparently this
Code: [Select]
sw.digitalWrite(wakeup_led,LOW);
LowPower.sleep(5000);
sw.digitalWrite(wakeup_led,HIGH);

goes to sleep because the led turn for 5 second.

But after free day, I see no difference. The battery goes from 4.2V to 3.7V in less than 3 days.
Without the lowpower, it goes down in 3 days as well . Not good.

I was expected to see a better difference.

My circuit is a bt different than yours. I am using Adafruit Feather MO adalogger with a AMD21 (ARM). I am not ueing sigfox but LoRa

Does some one has an experience with Adafruit Feather MO adalaoger and a RFM95 LoRa module radio in sleep mode, eight with AdruinoLowPower, or may be Sleepdog library from Adafruit?

I am going to investigate a bit more about  wiring.c, but someone can tell exactely what does it and for what it's usefull? What impact if I remove it as well?

Many thanks for any support and help.
Title: Re: Lowest consumption issue
Post by: iverona on Feb 24, 2019, 03:51 pm
Hello @philgeek et al.,

this thread was really useful to get as low consumption as possible! I have a simple alarm created with the mkrfox1200, battery powered and using a reed switch.

Following the tips here now I'm able to get 128.7uA while on deepSleep mode. While transmitting, it's around 380-400uA for 5 seconds. For some reason it's a bit higher than what you got, but I think it's more than enough. The only modification I made to the vanilla Arduino framework has been, as said above, the changes on wiring.c

I'll monitor how long the battery lasts. For anyone interested, code of my app is here:
https://github.com/iverona/StorageRoomAlarm/blob/master/src/main.cpp