STM32 power saving: wake up from RTC alarm and Serial – 6
As usual, our microcontrollers give a wide range of wake-up sources, we already see a timed wake-up, and now we introduce the wake-up via RTC alarm and Serial of our STM32.
Wake up with internal interrupt raise with the RTC alarm
For this test, It’s better if you read this article first “STM32: internal RTC, clock and battery backup (VBAT)” to understand better how to work the internal RTC.
We want to try to set an alarm to wake the device, and to do this the RTC library helps us.
In this case, we use the perfect integration of STM32LowPower and RTC library, and we can modify the sketch of the alarm used in the linked article to wake from a low-power mode.
/**
* A simple sketch that set the time to
* 2022-04-20 at 16:00:00
* and an alarm at
* 16:00:10
* the result is the interrupt after 10 secs
* and wake from deep sleep status.
*
* by Renzo Mischianti <www.mischianti.org>
* en: https://mischianti.org/category/tutorial/stm32-tutorial/
* it: https://mischianti.org/it/category/guide/guida-alla-linea-di-microcontrollori-stm32/
*/
#include "STM32LowPower.h"
#include <STM32RTC.h>
/* Get the rtc object */
STM32RTC& rtc = STM32RTC::getInstance();
/* Change these values to set the current initial time */
const byte seconds = 0;
const byte minutes = 0;
const byte hours = 16;
/* Change these values to set the current initial date */
const byte day = 20;
const byte month = 4;
const byte year = 22;
void alarmMatch(void *data);
void setup()
{
Serial.begin(115200);
// Select RTC clock source: LSI_CLOCK, LSE_CLOCK or HSE_CLOCK.
// By default the LSI is selected as source.
// rtc.setClockSource(STM32RTC::LSI_CLOCK);
rtc.begin(); // initialize RTC 24H format
// we set the time at 2022-04-20 at 16:00:00
rtc.setTime(hours, minutes, seconds);
rtc.setDate(day, month, year);
delay(1000);
String someRandomData = "www.mischianti.org";
// Configure low power
LowPower.begin();
LowPower.enableWakeupFrom(&rtc, alarmMatch, &someRandomData);
// Now we set an alert at 16:00:10
// pratically 10 secs after the start
// (check the initialization of clock)
rtc.setAlarmDay(day);
rtc.setAlarmTime(16, 0, 10, 0);
rtc.enableAlarm(rtc.MATCH_DHHMMSS);
// Print date...
Serial.printf("Now is %02d/%02d/%02d %02d:%02d:%02d.%03d and we set the wake at 16:10! So wait 10secs! \n",
rtc.getDay(), rtc.getMonth(), rtc.getYear(),
rtc.getHours(), rtc.getMinutes(), rtc.getSeconds(), rtc.getSubSeconds());
Serial.println("Deep Sleep!");
delay(1000);
LowPower.deepSleep();
}
void loop()
{
// Print date...
Serial.printf("%02d/%02d/%02d ", rtc.getDay(), rtc.getMonth(), rtc.getYear());
// ...and time
Serial.printf("%02d:%02d:%02d.%03d\n", rtc.getHours(), rtc.getMinutes(), rtc.getSeconds(), rtc.getSubSeconds());
delay(1000);
}
void alarmMatch(void *data)
{
String myData = *(String*)data;
Serial.println("Alarm Match!");
Serial.println(myData);
}
I highlight the dependence code we need to wake up from deep sleep (but work with all low-power modes). After importing the library, we are going to enable LowPower mode and attach the alarm interrupt.
// Configure low power
LowPower.begin();
LowPower.enableWakeupFrom(&rtc, alarmMatch, &someRandomData);
Then, after setting all data to the alarm, we put in deepSleep the device.
LowPower.deepSleep();
You can check the result in the serial output.
Now is 20/04/22 16:00:00.944 and we set the wake at 16:10! So wait 10secs!
Deep Sleep!
Alarm Match!
www.mischianti.org
20/04/22 16:00:10.008
20/04/22 16:00:10.952
20/04/22 16:00:11.900
20/04/22 16:00:12.848
20/04/22 16:00:13.792
20/04/22 16:00:14.740
The sketch is very simple but offers functionality that can be very useful.
Wake up from Serial
Another interesting feature is the wake-up from the Serial device. It’s interesting, especially if you have an autonomous Serial device.
Here the STM32 and ST-Link V2 used in this test STM32F103C8T6 STM32F401 STM32F411 ST-Link v2 ST-Link v2 official
Here the FTDI USB to TTL CH340G - USB to TTL FT232RL
Here my multimeter Aneng SZ18
The USB Serial wake-up is not supported so we are going to enhance the basic wiring schema used for this test by adding also the wiring from STM32 Rx to Tx FTDI pin.
STM32 | FTDI |
---|---|
PA9 | Tx |
PA10 | Rx |
GND | GND |
Here the FTDI USB to TTL CH340G - USB to TTL FT232RL
The sketch is also very simple.
/**
* STM32 wake up from Serial, you must use and external FTDI connected
*
* STM32 FTDI
* PA9 Tx
* PA10 Rx
*
* then with a serial console try to write some text, the STM32 wake-up
* read the Serial buffer and return in sleep.
*
* by Renzo Mischianti <www.mischianti.org>
* en: https://mischianti.org/category/tutorial/stm32-tutorial/
* it: https://mischianti.org/it/category/guide/guida-alla-linea-di-microcontrollori-stm32/
*/
#include "STM32LowPower.h"
// Declare it volatile since it's incremented inside an interrupt
volatile int wakeup_counter = 0;
void serialWakeup();
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("START PROGRAM!");
// Configure low power
LowPower.begin();
// Enable UART in Low Power mode wakeup source
LowPower.enableWakeupFrom(&Serial, serialWakeup);
}
void loop() {
Serial.print("Start Sleep mode in ");
for (int i = 5;i>0;i--) { Serial.print(i); Serial.print(" "); delay(1000); } Serial.println( "OK!" ); delay(1000);
// Go to sleep
LowPower.sleep();
// Waked
Serial.print(wakeup_counter);
Serial.println(" wake up");
// Give time to Serial bus to be ready
delay(10);
// Read all serial buffer
while(Serial.available()) {
char c = Serial.read();
Serial.print(c);
}
Serial.println();
}
void serialWakeup() {
// This function will be called once on device wakeup
// You can do some little operations here (like changing variables
// which will be used in the loop)
// Remember to avoid calling delay() and long running functions
// since this functions executes in interrupt context
wakeup_counter++;
}
The serial output, in my case, is:
START PROGRAM!
Start Sleep mode in 5 4 3 2 1 OK!
>>Send to COM16: "pippo"<<
1 wake up
pippo
Start Sleep mode in 5 4 3 2 1 OK!
>>Send to COM16: "pluto"<<
2 wake up
pluto
Start Sleep mode in 5 4 3 2 1 OK!
>>Send to COM16: "paperino"<<
3 wake up
paperino
Start Sleep mode in 5 4 3 2 1 OK!
Thanks
- STM32F1 Blue-Pill: pinout, specs, and Arduino IDE configuration (STM32duino and STMicroelectronics)
- STM32: program (STM32F1) via USB with STM32duino bootloader
- STM32: programming (STM32F1 STM32F4) via USB with HID boot-loader
- STM32F4 Black-Pill: pinout, specs, and Arduino IDE configuration
- STM32: ethernet w5500 with plain HTTP and SSL (HTTPS)
- STM32: ethernet enc28j60 with plain HTTP and SSL (HTTPS)
- STM32: WiFiNINA with ESP32 WiFi Co-Processor
- How to use SD card with stm32 and SdFat library
- \STM32: SPI flash memory FAT FS
- STM32: internal RTC, clock, and battery backup (VBAT)
- STM32 LoRa
- STM32 Power saving
- STM32F1 Blue-Pill clock and frequency management
- STM32F4 Black-Pill clock and frequency management
- Intro and Arduino vs STM framework
- Library LowPower, wiring, and Idle (STM Sleep) mode
- Sleep, deep sleep, shutdown, and power consumption
- Wake up from RTC alarm and Serial
- Wake up from the external source
- Backup domain intro and variable preservation across reset
- RTC backup register and SRAM preservation
- STM32 send emails with attachments and SSL (like Gmail): w5500, enc28j60, SD, and SPI Fash
- FTP server on STM32 with w5500, enc28j60, SD Card, and SPI Flash
- Connecting the EByte E70 to STM32 (black/blue pill) devices and a simple sketch example