STM32 wake up from standby mode every 10 seconds

3k Views Asked by At

I used to have a project on arduino using the atmega328p chip with this code:

// used for deep sleep
#include <avr/wdt.h>

static void go_to_sleep_and_power_down_and_wake_up_again_in_2_seconds()
{
    // wake up again in 4 seconds
    wdt_enable(WDTO_4S);

    // go to deep sleep    
    {
        // BIG difference when in sleep
        // Diable ADC (analog to digital converter)
        ADCSRA &= ~(1 << 7);

        SMCR |= (1 << 2); // power down mode
        SMCR |= 1;        // enable sleep;

        // BOD DISABLE (big difference when in sleep only)
        MCUCR |= (3 << 5);                      // set both BODS and BODSE at the same time
        MCUCR = (MCUCR & ~(1 << 5)) | (1 << 6); // then set the BODS bit and clear the BOSE bit at the same time

        __asm__ __volatile__("sleep");
    }

    // this line should not execute
}

void setup()
{
    // init code...

    // read sensor value
    // pseudo code:
    if(valueReadFromSensor == 0)
    {
        turnOnAlarm();
        return;
    }

    go_to_sleep_and_power_down_and_wake_up_again_in_2_seconds()
}

void loop(){
   // not used
}

The code is very simple, once it wakes up it reads data from a sensor and goes back to sleep. After 2 seconds it wakes up again and repeats the same process.

How can I do the same thing on stm32 on the bluepill for example? I have managed to go to standby mode using this function HAL_PWR_EnterSTANDBYMode();. But how can I enable waking up again in 2 seconds for example?

Edit

I have tried this sources:

uses an old version of stm32 cube ide and different board. I tried the video doing the same steps and some defines make the code unable to compile. https://www.youtube.com/watch?v=zQ1sT9fjd3E

does not have code https://www.stm32duino.com/viewtopic.php?t=922

does not have code STM32 wake up from standby by RTC

I am not using freeRtos https://electronics.stackexchange.com/a/562120/56969

1

There are 1 best solutions below

0
Tono Nam On

Finally found a solution using IWDG. This code works for PlatformIO using the arduino framework

#include <Arduino.h>
#include <IWatchdog.h> // <----------- needed

void setup(void)
{
    // start serial
    Serial.begin(115200);

    // set pins
    pinMode(LED_BUILTIN, OUTPUT);
    pinMode(A0, INPUT_PULLUP); // connect button to this pin to simulate a sensor for purposes of this example.

    // flash led to indicate board is starting
    Serial.println("starting...");
    digitalWrite(LED_BUILTIN, HIGH);
    delay(250);
    digitalWrite(LED_BUILTIN, LOW);

    // read value from sensor. In this case just tell if button is presses
    // connect one side of button to pin A0 and the other to ground
    int sensorValue = digitalRead(A0);

    // if button is not pressed
    if (sensorValue == 1)
    {
        // go to sleep and try again in 4 seconds
        Serial.println("going to sleep and trying again in 4 seconds...");

        // Initialize the IWDG with 4 seconds timeout.
        // This would cause a CPU reset if the IWDG timer
        // is not reloaded in approximately 4 seconds.
        IWatchdog.begin(4000000);

        // go to sleep
        HAL_PWR_EnterSTANDBYMode();

        Serial.println("This line should NOT print!!!!!");
    }


    // at this point it means the button is was pressed
    Serial.println("staying awake!");
    // stay awake flashing led
    while (true)
    {
        digitalWrite(LED_BUILTIN, HIGH);
        delay(50);
        digitalWrite(LED_BUILTIN, LOW);
        delay(50);
    }
}

void loop()
{
}

This video explains how to have the same using stm32CubeIDE: https://www.youtube.com/watch?v=AelNsnpfbcM&t=472s