stm32duino / STM32LowPower

Arduino Low Power library for STM32
187 stars 52 forks source link

Using LSE clock source for the RTC does not work with the LowPower shutdown #22

Closed Bambofy closed 4 years ago

Bambofy commented 4 years ago

Hi, I have made a forum post here that contains information about the bug. https://www.stm32duino.com/viewtopic.php?f=62&t=360

Here is the sample code that doesn't work. It shuts down on the first loop and never starts up again.


#include <STM32RTC.h>

#include <STM32LowPower.h>

STM32RTC& rtc = STM32RTC::getInstance();
volatile bool sleeping = false;
void callback(void* data)
{
    sleeping = false;
    Serial.println("Callback!");
    Serial.flush();
}

void setup() {
    // put your setup code here, to run once:
    Serial.begin(9600);
    Serial.println("Started");
    Serial.flush();

    rtc.begin();
    rtc.setClockSource(STM32RTC::LSE_CLOCK);
    LowPower.begin();

    if (!rtc.isTimeSet())
    {
        Serial3.println("Time did not persist.");
        Serial3.flush();
    }
    else
    {
        Serial3.println("Time persisted!");
        Serial3.flush();
    }
    rtc.setHours(5);
    rtc.setMinutes(5);
    rtc.setSeconds(1);
    rtc.setWeekDay(1);
    rtc.setDay(1);
    rtc.setMonth(1);
    rtc.setYear(20);
    LowPower.enableWakeupFrom(&rtc, callback);
}

void loop() {
    Serial.println("Shutting down!");
    Serial.flush();
    LowPower.shutdown(1000);
    Serial.println("Done!");
    Serial.flush();
}

If you remove the line "rtc.setClockSource()" the code operates normally however the time does not persist.

fpistm commented 4 years ago

As answered on the forum, which board? If you do not provide all relevant information, you can't get help...

Bambofy commented 4 years ago

STM32 L452RE, could i be missing some HAL configuration to enable LSE + RTC clock combinations?

Also running the 1.8.0 version of stm32duino, will be updating it to 1.9.0 soon.

fpistm commented 4 years ago

Seems you didn't read the STM32RTC README.md... void setClockSource(Source_Clock source) : this function must be called before begin().

Moreover there are several issue in your sketch:

  1. As you used LowPower.shutdown(1000); you don't need to call LowPower.enableWakeupFrom(&rtc, callback); The shutdown with a delay value will program automatically the RTC to wake up. For L4 the LSE will be used as RTC clock source in any case even if the RTC is already configured to usethe LSI. This explain your issue, you started the RTC using LSI then you told the RTC to use the LSE. So when entering in shutdown mode then it done nothing as it thought it already configured on the LSE while in fact RTC is on the LSI. If you want a specific alarm configuration, then you can use LowPower.enableWakeupFrom(&rtc, callback); and set your own alarm config and then calling LowPower.shutdown(); without any delay
  2. Code after LowPower.shutdown(); will never be called as the system restart.
  3. Code in the callback will never be called as the system restart.

Here a code to show the time persistent (based on https://github.com/stm32duino/STM32Examples/tree/master/examples/NonReg/RTC/RTC_Tests)

#include <STM32RTC.h>

#include <STM32LowPower.h>

static const char* mydate = __DATE__;
static const char* mytime = __TIME__;
static byte seconds = 0;
static byte minutes = 0;
static byte hours = 0;

static byte weekDay = 1;
static byte day = 0;
static byte month = 0;
static byte year = 0;

static STM32RTC::Hour_Format hourFormat = STM32RTC::HOUR_24;
static STM32RTC::AM_PM period = STM32RTC::AM;

STM32RTC& rtc = STM32RTC::getInstance();

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("Started");
  Serial.flush();

  LowPower.begin();

  rtc.setClockSource(STM32RTC::LSE_CLOCK);
  rtc.begin();

  if (!rtc.isTimeSet())
  {
    Serial.println("Time did not persist.");

    initDateTime(mydate, mytime);
    rtc.setTime(hours, minutes, seconds);
    rtc.setDate(weekDay, day, month, year);
    printDateTime(1, 0, false);
  }
  else
  {
    Serial.println("Time persisted!");
    printDateTime(1, 0, false);
  }
}

void loop() {
  Serial.println("Shutting down!");
  Serial.flush();
  LowPower.shutdown(1000);
}

static uint8_t conv2d(const char* p) {
  uint8_t v = 0;
  if ('0' <= *p && *p <= '9')
    v = *p - '0';
  return 10 * v + *++p - '0';
}

void print2digits(int number) {
  if (number < 10) {
    Serial.print("0"); // print a 0 before if the number is < than 10
  }
  Serial.print(number);
}

// sample input: date = "Dec 26 2009", time = "12:34:56"
void initDateTime (const char* date, const char* time) {
  year = conv2d(date + 9);
  // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
  switch (date[0]) {
    case 'J': month = (date[1] == 'a') ? 1 : ((date[2] == 'n') ? 6 : 7); break;
    case 'F': month = 2; break;
    case 'A': month = date[2] == 'r' ? 4 : 8; break;
    case 'M': month = date[2] == 'r' ? 3 : 5; break;
    case 'S': month = 9; break;
    case 'O': month = 10; break;
    case 'N': month = 11; break;
    case 'D': month = 12; break;
  }
  day = conv2d(date + 4);
  hours = conv2d(time);
  if (hourFormat == rtc.HOUR_12) {
    period = hours >= 12 ? rtc.PM : rtc.AM;
    hours = hours >= 13 ? hours - 12 : (hours < 1 ? hours + 12 : hours);
  }
  minutes = conv2d(time + 3);
  seconds = conv2d(time + 6);
}

// t: number of print
// d: delay between each print
// a: display alarm
void printDateTime(uint32_t t, uint32_t d, bool a) {
  for (uint32_t i=0; i<t; i++) {
    // Print date...
    print2digits(rtc.getMonth());
    Serial.print("/");
    print2digits(rtc.getDay());
    Serial.print("/");
    print2digits(rtc.getYear());
    Serial.print("\t");

    // ...and time
    print2digits(rtc.getHours(&period));
    Serial.print(":");
    print2digits(rtc.getMinutes());
    Serial.print(":");
    print2digits(rtc.getSeconds());
    if (hourFormat == rtc.HOUR_12) {
      Serial.print(period == rtc.AM ? " AM":" PM");
    }
    if(a) {
      // Print day...
      Serial.print("\t");
      print2digits(rtc.getAlarmDay());
      Serial.print("\t");

      // ...and time
      print2digits(rtc.getAlarmHours(&period));
      Serial.print(":");
      print2digits(rtc.getAlarmMinutes());
      Serial.print(":");
      print2digits(rtc.getAlarmSeconds());
      if (hourFormat == rtc.HOUR_12) {
        Serial.print(period == rtc.AM ? " AM":" PM");
      }
    }
    Serial.println();
    delay(d);
  }
}

Output

Started
Time did not persist.
05/20/20    15:41:51
Shutting down!
Started
Time persisted!
05/20/20    15:41:52
Shutting down!
Time persisted!
05/20/20    15:41:53
Shutting down!