Wakeup STM32L432KC from Shutdown Mode with extern RTC

Hello everyone,

I'm currently working with an STM32 Nucleo L432KC board, and I'm trying to implement a low-power application where the board enters shutdown mode and wakes up through an external RTC (RV-3028 C7), to measure the temperature once and go to shutdown mode again.

I want the behavior to be as follows:

  1. The microcontroller should enter shutdown mode to save power.
  2. When the RTC triggers an interrupt, the microcontroller should wake up
  3. After waking up, it should measure the temperature using a BME280 sensor and then return to shutdown mode.

I’ve tried implementing this with the following code snippet: Everythings works well if i remove the shutdown mode. the Interrupt with the RTC works also every 30 seconds and measures the temperature. but i have a problem with the shutdown mode. Can someone maybe help me ? Thank you!

#include "RV-3028-C7.h"
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <STM32LowPower.h>

RV3028 rtc;
Adafruit_BME280 bme; // BME280-Sensor
STM32LowPower lowPower; // 

void setup() {
  Serial.begin(115200);
  while (!Serial); // Warte, bis die serielle Verbindung hergestellt ist
  Serial.println("Setup gestartet...");

  // I2C initialisieren
  Wire.begin();
  Wire.setClock(50000); // Frequenz auf 50 kHz setzen

  // RTC initialisieren
  if (!rtc.begin()) {
    Serial.println("RTC nicht gefunden!");
    while (1); // Halte an, falls RTC nicht gefunden
  }

  // RTC-Timer konfigurieren (z.B. nach 30 Sekunden)
  rtc.setTimer(true, 1, 30, true, true, false); // Timer für 30 Sekunden setzen

  // BME280 initialisieren
  if (!bme.begin(0x76)) {  // 0x76 ist die I2C-Adresse des BME280
    Serial.println("BME280 nicht gefunden!");
    while (1); // Halte an, falls BME280 nicht gefunden
  }

  rtc.setBackupSwitchoverMode(0); // Switchover disabled
  rtc.disableTrickleCharge(); // Trickle Charge deaktivieren
  rtc.disableClockOut(); // CLKOUT deaktivieren

  // Externen Interrupt an PA0 setzen
  pinMode(PA0, INPUT_PULLUP); // PA0 als Eingang mit Pull-Up-Widerstand
  attachInterrupt(digitalPinToInterrupt(PA0), rtcInterrupt, FALLING); // Interrupt bei fallendem Signal

  Serial.println("Setup abgeschlossen, warte auf RTC-Interrupt.");
}

void loop() {
  Serial.println("Gehe in den Shutdown-Modus...");
  lowPower.shutdown(0); // Gehe in den Shutdown-Modus, bis ein Interrupt den Mikrocontroller weckt
}

// Interrupt-Service-Routine (ISR)
void rtcInterrupt() {
  Serial.println("RTC-Interrupt ausgelöst, wecke Mikrocontroller...");

  // I2C wieder aktivieren
  Wire.begin(); // I2C reaktivieren

  if (rtc.readTimerInterruptFlag()) { // Prüfen, ob der Timer-Interrupt ausgelöst wurde
    rtc.clearTimerInterruptFlag(); // Interrupt-Flag sofort zurücksetzen

    // Sensor aus dem Sleep-Modus aufwecken und Temperatur messen
    bme.takeForcedMeasurement(); // Einmalige Messung im Forced-Mode
    float temperature = bme.readTemperature(); // Lese die Temperatur vom BME280-Sensor

    // Ausgabe der gemessenen Temperatur über die serielle Verbindung
    Serial.print("Gemessene Temperatur: ");
    Serial.print(temperature);
    Serial.println(" °C");
  }

  Wire.end(); // I2C wieder deaktivieren
}

Please do not post in "Uncategorized"; see the sticky topics in Uncategorized - Arduino Forum.

I moved your topic to an appropriate forum category.

In the future, please take some time to pick the forum category that best suits the subject of your topic. There is an "About the _____ category" topic at the top of each category that explains its purpose.
This is an important part of responsible forum usage, as explained in the "How to get the best out of this forum" guide. The guide contains a lot of other useful information. Please read it.
Thanks in advance for your cooperation.

I would not deal with the temperature reading and everything else in the ISR.

Just let the ISR wake up the arduino and have the main code just perform the reading and go to sleep again. Trying to perform complex or long stuff within the ISR context is risky business. (on some arduino Interrupts would be disabled for example, meaning I2C would not work)

Hi thanks for your answer! I already tried everything, but i think there is a problem with entering the shutdown or sleep mode. I once just tried to enter the deepsleep oder shutdown mode, but even that didnt work well. If i do the measurements and interrupt without it, it works very well. I cant seem to find the solution for that.

I don't have that board. Does the wake up from sleep continues right after your slept (once the ISR code is executed) or is it a reboot ?

can you check this ?

#include "RV-3028-C7.h"
#include <STM32LowPower.h>

volatile bool wakeFromSleep = false;

RV3028 rtc;
STM32LowPower lowPower;

void rtcInterrupt() {
  wakeFromSleep = true;
}

void setup() {
  Serial.begin(115200);
  while (!Serial); // Warte, bis die serielle Verbindung hergestellt ist
  Serial.println("Setup gestartet...");

  if (wakeFromSleep) Serial.println("Aufwachen aus dem Schlaf, ISR wurde ausgeführt.");
  else Serial.println("Kein Aufwachen aus dem Schlaf, ISR wurde NICHT ausgeführt.");

  // I2C initialisieren
  Wire.begin();
  Wire.setClock(50000); // Frequenz auf 50 kHz setzen

  // RTC initialisieren
  if (!rtc.begin()) {
    Serial.println("RTC nicht gefunden!");
    while (1); // Halte an, falls RTC nicht gefunden
  }

  // RTC-Timer konfigurieren (z.B. nach 30 Sekunden)
  rtc.setTimer(true, 1, 10, true, true, false); // Timer für 10 Sekunden setzen

  rtc.setBackupSwitchoverMode(0); // Switchover disabled
  rtc.disableTrickleCharge(); // Trickle Charge deaktivieren
  rtc.disableClockOut(); // CLKOUT deaktivieren

  // Externen Interrupt an PA0 setzen
  pinMode(PA0, INPUT_PULLUP); // PA0 als Eingang mit Pull-Up-Widerstand
  attachInterrupt(digitalPinToInterrupt(PA0), rtcInterrupt, FALLING); // Interrupt bei fallendem Signal

  Serial.println("Setup abgeschlossen, warte auf RTC-Interrupt.");
  Serial.flush();
  Serial.println("3"); Serial.flush(); delay(1000);
  Serial.println("2"); Serial.flush(); delay(1000);
  Serial.println("1"); Serial.flush(); delay(1000);
  lowPower.shutdown(0); // Gehe in den Shutdown-Modus, bis ein Interrupt den Mikrocontroller weckt

  // Überprüfe, wo wir wirklich aufwachen.
  Serial.println("Wake folgt tatsächlich dem Befehl sleep.");

}

void loop() {}

what do you see in the serial monitor after one minute (should wake up every 10s)

PS: typed here from your code, so may be there are bugs

This is what I see:
1
Setup gestartet...
Kein Aufwachen aus dem Schlaf, ISR wurde NICHT ausgeführt.
Setup abgeschlossen, warte auf RTC-Interrupt.
3
2
1
Setup gestartet...
Kein Aufwachen aus dem Schlaf, ISR wurde NICHT ausgeführt.
Setup abgeschlossen, warte auf RTC-Interrupt.
3
2
1
Setup gestartet...
Kein Aufwachen aus dem Schlaf, ISR wurde NICHT ausgeführt.

OK so it shows the wake from sleep is a full reboot and not continuing where it stopped since the setup is called again.

It is weird though because when you wake up from sleep you should get the ISR triggered and it seems it does not happen since wakeFromSleep is never set to true.

can you add a led with a current limiting resistor and set it as an output in the setup. Then inside the rtcInterrupt() function make the pin an OUTPUT (just to be sure it was not reset during sleep), turn that led ON and turn it off just before going to sleep just to see if the RTC is actually called.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.