Go Down

Topic: LowPower library for ItsyBitsy M0 Express not working (Read 182 times) previous topic - next topic

mbobinger

Dear Arduino-Team,

I would like to use the ItsyBitsy M0 Express board:
https://www.adafruit.com/product/3727

with the latest LowPower library from rocketscream:
https://github.com/rocketscream/Low-Power

When calling a standard function of the library:
Code: [Select]
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);

I get an error that LowPower has no class powerDown:
Code: [Select]
exit status 1
'class LowPowerClass' has no member named 'powerDown'

The problem seems to be that ATSAMD21 and this quite known library are not compatible. Do you have any solution to this? Maybe another library?

Best and thank you,
Marco

gfvalvo

The README at GitHub says it works with ATSAMD2. It could be that the problem is with the code you haven't bothered to post.
No technical questions via PM. They will be ignored. Post your questions in the forum so that all may learn.

noweare


gfvalvo

Have you looked at the library's source code? Excerpt from LowPower.h:

Code: [Select]
#elif defined (__arm__)

 #if defined (__SAMD21G18A__)
      void idle(idle_t idleMode);
      void standby();
 #else
 #error "Please ensure chosen MCU is ATSAMD21G18A."
 #endif

 #else


Also, there's an example specifically for SAMD21: "standbyExternalInterruptSAMD21.ino"

Doesn't seem like you've put much effort into this.
No technical questions via PM. They will be ignored. Post your questions in the forum so that all may learn.

mbobinger

Hi Guys,

The README at GitHub says it works with ATSAMD2. It could be that the problem is with the code you haven't bothered to post.
Thank you a lot for your replies. My application is to input an external interrupt using a DS3231 Real Time Clock to Pin11 of the Adafruit Itsybitsy M0, which is equipped with an Atmel ATSAMD21 ARM processor. The interrupt calls an Interrupt Service routine, which records some sensor values. I have replaced the long code with the sensor values to print a string.

The code without the power saving function works fine, the DS3231 sends an interrupt each minute and I can also manually interrupt the MCU by connecting pin11 to ground.

However, if I start adding a low.power function (like the one that comes with the rocket scream library or the rtc.lib one), the MCU never comes back from sleep.

Best,
Marco

Code: [Select]

#include <Wire.h>
#include <LowPower.h>
#include <RtcDS3231.h>
volatile boolean alarm = 1;
RtcDS3231<TwoWire> Rtc2(Wire);

//pin definition
const byte interruptPin=11;


void setup()
{
  delay(5000); //delay to get the chip programmed
  Serial.begin(115200);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING);


Rtc2.Begin();
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
Rtc2.SetDateTime(compiled);
RtcDateTime now = Rtc2.GetDateTime();
Rtc2.Enable32kHzPin(false);
Rtc2.SetSquareWavePin(DS3231SquareWavePin_ModeAlarmBoth);
     
    DS3231AlarmTwo alarm2(
            0,
            0,
            0,
            DS3231AlarmTwoControl_OncePerMinute);
    Rtc2.SetAlarmTwo(alarm2);
    Rtc2.LatchAlarmsTriggeredFlags(); 
 sensors.begin(); 
}

void loop() {
  if (alarm == true) {
    handleAlarm();
  }
  LowPower.standby();
}

void handleAlarm() {
alarm = false;
Serial.print("We handle everything here");
Rtc2.LatchAlarmsTriggeredFlags();
}

void handleInterrupt() {
  alarm = true;
}
 

mbobinger

Have you looked at the library's source code? Excerpt from LowPower.h:

Code: [Select]
#elif defined (__arm__)

 #if defined (__SAMD21G18A__)
      void idle(idle_t idleMode);
      void standby();
 #else
 #error "Please ensure chosen MCU is ATSAMD21G18A."
 #endif

 #else


Also, there's an example specifically for SAMD21: "standbyExternalInterruptSAMD21.ino"

Doesn't seem like you've put much effort into this.

Dear gfvalvo,

Could you maybe have a look :)? I am already quite desperate since I have been trying to get the ItsyBitsy work with a low power library and an external interrupt that is provided by a DS3231 Real Time Clock. The code and the interrupt (each minute) works fine if i do not put any low power mode in the code. When I call the low power mode from either of one of these libraries:
1. rocketscream:
https://github.com/rocketscream/Low-Power
2. Arduino Low Power:
https://www.arduino.cc/en/Reference/ArduinoLowPower
3. https://www.arduinolibraries.info/libraries/rtc-zero

the MCU never comes back from sleep. Please have a look at my code below. The external interrupt calls an InterruptServiceRoutine that sets an alarm flag to true. The loop function then just sets the alarm flag to false and calls the handlealarm function. I have also tried to use CHANGE and LOW for the attach.Interrupt but the MCU still does not come back from sleep mode.
Where shall I call the sleep mode? I think the problem lies somewhere else besides the position of the sleep mode.

Please see my code below:

Code: [Select]

#include <RTCZero.h> //library for setting the real time clock on the MCU board, can also be used for low power modes
RTCZero rtc; //object definition
#include <Wire.h> //library for I2C connection
#include <OneWire.h> //library for the temperature sensor
#include <LowPower.h> //rocketscream library
//#include <SoftwareWire.h>
#include <RtcDS3231.h> //RTC library clock that sets the RTC alarm and RTC time
#include <DallasTemperature.h> //DS18 digital temperature library
//#include <ArduinoLowPower.h>
#define _BV(b) (1UL << (b)) //required for the Rtc2 wire definition
RtcDS3231<TwoWire> Rtc2(Wire);
volatile boolean alarm = 1;

//setting of the internal MCU clock using the RTCzero library
const byte seconds = 0;
const byte minutes = 20;
const byte hours = 15;
const byte days = 21;
const byte months = 7;
const byte years = 19;
const byte interruptPin = 11;

void setup()
{
 delay(5000); //delay to get the chip programmed
 Serial.begin(115200);
 pinMode(interruptPin, INPUT_PULLUP);
 attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, CHANGE);
 
//Section for RTCzero library that sets the internal time of the MCU and puts the MCU to sleep via standbyMode();
 rtc.begin();
 rtc.setTime(hours, minutes, seconds);
 rtc.setDate(days, months, years);
 //rtc.setAlarmTime(00, 00, 10); //
 //rtc.enableAlarm(rtc.MATCH_HHMMSS);
 //rtc.attachInterrupt(ISR);
//extInterrupt(11); //creates an interrupt source on external pin


Rtc2.Begin();
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
Rtc2.SetDateTime(compiled);
RtcDateTime now = Rtc2.GetDateTime();
Rtc2.Enable32kHzPin(false);
Rtc2.SetSquareWavePin(DS3231SquareWavePin_ModeAlarmBoth);

RtcDateTime alarmTime = now + 88; // into the future
   DS3231AlarmOne alarm1(
           alarmTime.Day(),
           alarmTime.Hour(),
           alarmTime.Minute(),
           alarmTime.Second(),
           DS3231AlarmOneControl_HoursMinutesSecondsMatch);
 Rtc2.SetAlarmOne(alarm1);          
   DS3231AlarmTwo alarm2(
           0,
           0,
           0,
           DS3231AlarmTwoControl_OncePerMinute);
   Rtc2.SetAlarmTwo(alarm2);
   Rtc2.LatchAlarmsTriggeredFlags();  
}

void loop() {
 if (alarm == true) {
   handleAlarm();
 }
// LowPower.standby();
}

void handleAlarm() {
 alarm = false;
 RtcDateTime timestamp = Rtc2.GetDateTime();
 Serial.print("time interrupt at: ");
 char time[10];
 sprintf(time, "%d:%d:%d",
         timestamp.Hour(),
         timestamp.Minute(),
         timestamp.Second()
        );
Serial.println(time);

   Rtc2.LatchAlarmsTriggeredFlags();
}

void handleInterrupt() {
 alarm = true;
}

gfvalvo

It's been long time since I looked in to it, but I recall getting edge-triggered interrupts to work is tricky while the SAMD21 is sleeping. You need to have a clock enabled -- XOSC32K, I think. And then use that as the clock to the interrupt system.

You'll have to Google around. Start here: https://github.com/arduino/ArduinoCore-samd/issues/142

And, of course, the device datasheet.
No technical questions via PM. They will be ignored. Post your questions in the forum so that all may learn.

mbobinger

It's been long time since I looked in to it, but I recall getting edge-triggered interrupts to work is tricky while the SAMD21 is sleeping. You need to have a clock enabled -- XOSC32K, I think. And then use that as the clock to the interrupt system.

You'll have to Google around. Start here: https://github.com/arduino/ArduinoCore-samd/issues/142

And, of course, the device datasheet.
Thank you a lot. I have come across this thread yesterday but I haven't checked it in detail. I will give it a try.

I tested my code with an Arduino UNO /Atmega328P and it worked perfectly using the rocketscream LowPower library. I guess it is as you say, have the XOSC32K clock enabled and use that for the interrupt.

Anyways, looking the datasheet, I am happy with the power consumption in any mode of the Atmega328P also. No need for an ATSAMD21, maybe later.

Best,
Marco

Go Up