2024-10-05 08:47 AM
Hi everyone,
I'm working on a project with the STM32 Nucleo L432KC, where I need the microcontroller to enter shutdown mode to save power. The board is connected to an external RTC that triggers an interrupt every 30 seconds to wake the microcontroller. Upon waking, I want it to measure the temperature once using a BME280 sensor.
I've successfully implemented the RTC interrupt, and it works fine. However, when I attempt to put the microcontroller into shutdown mode, nothing happens—it's not waking up as expected.
I'm programming everything using the Arduino IDE and would really appreciate some guidance on how to correctly implement shutdown mode. Has anyone experienced a similar issue or knows how to solve this?
Thanks in advance!
This is the current code without shutdown which works:
#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; // Instanz von STM32LowPower
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 Deep Sleep-Modus...");
//lowPower.deepSleep(0); // Doesnt work
}
// 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");
Serial.println("Gehe in den Deep Sleep-Modus...");
//lowPower.deepSleep(0); // Gehe in den Deep Sleep-Modus, bis ein Interrupt den Mikrocontroller weckt
}
Wire.end(); // I2C wieder deaktivieren
}
This is the function:
void STM32LowPower::shutdown(uint32_t ms)
{
if ((ms != 0) || _rtc_wakeup) {
programRtcWakeUp(ms, SHUTDOWN_MODE);
}
/* Get the rtc object to know if it is configured */
STM32RTC &rtc = STM32RTC::getInstance();
LowPower_shutdown(rtc.isConfigured());
}
/**
* @brief Enable GPIO pin in interrupt mode. If the pin is a wakeup pin, it is
* configured as wakeup source.
* @PAram pin: pin number
* @PAram callback: pointer to callback function.
* @PAram mode: pin interrupt mode (HIGH, LOW, RISING, FALLING or CHANGE)
* @PAram LowPowerMode: Low power mode which will be used
* (IDLE_MODE, SLEEP_MODE, DEEP_SLEEP_MODE, SHUTDOWN_MODE)
* In case of SHUTDOWN_MODE only, Wakeup pin capability is activated
* @retval None
*/
void LowPower_shutdown(bool isRTC)
{
__disable_irq();
/* Clear wakeup flags */
#if defined(PWR_FLAG_WU)
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
#elif defined(PWR_CPUCR_CSSF)
__HAL_PWR_CLEAR_FLAG(PWR_CPUCR_CSSF);
#elif defined(PWR_MPUCR_CSSF)
__HAL_PWR_CLEAR_FLAG(PWR_MPUCR_CSSF);
#endif
#if defined(STM32WBxx)
/* Set low-power mode of CPU2 */
/* Note: Typically, action performed by CPU2 on a dual core application.
Since this example is single core, perform it by CPU1. */
/* Note: On STM32WB, both CPU1 and CPU2 must be in low-power mode
to set the entire System in low-power mode, corresponding to
the deepest low-power mode possible.
For example, CPU1 in Stop2 mode and CPU2 in Shutdown mode
will make system enter in Stop2 mode. */
LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
#endif
#if defined(LL_PWR_SHUTDOWN_MODE) || defined(LL_PWR_MODE_SHUTDOWN)
/* LSE must be on to use shutdown mode within RTC else fallback to standby */
if ((!isRTC) || (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == SET)) {
#if defined(STM32U0xx)
HAL_PWR_EnterSHUTDOWNMode();
#else
HAL_PWREx_EnterSHUTDOWNMode();
#endif
} else
#else
UNUSED(isRTC);
#endif
{
LowPower_standby();
}
}
2024-10-05 12:44 PM
Since this is Arduino drivers, you should be asking for help in the Arduino forum.
In ST forums, you can ask for help on HAL and LL drivers.