#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include "pico/sleep.h"
#include "hardware/gpio.h"
#define WAKE_PIN 22 // GP22 for button wake-up
void led_blink(int count, int on_ms, int off_ms) {
for (int i = 0; i < count; i++) {
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);
sleep_ms(on_ms);
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0);
sleep_ms(off_ms);
}
}
void lposc_dormant_mode() {
// Initialize WiFi
if (cyw43_arch_init()) {
while(1) tight_loop_contents();
}
// PHASE 1: Baseline measurement (33mA expected)
led_blink(3, 100, 100); // 3 blinks = starting
sleep_ms(3000); // Measure baseline current
// PHASE 2: Configure for dormant mode PROPERLY
led_blink(5, 200, 200); // 5 slow blinks = preparing for dormant
// Configure wake button
gpio_init(WAKE_PIN);
gpio_set_dir(WAKE_PIN, GPIO_IN);
gpio_pull_up(WAKE_PIN);
// CRITICAL: Configure clock source for dormant mode
// This was missing in previous test!
sleep_run_from_lposc(); // Required for dormant mode
// Turn off LED and WiFi
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0);
cyw43_arch_deinit();
// NOW go dormant - should reach ~1mA
sleep_goto_dormant_until_pin(WAKE_PIN, true, false); // Edge trigger, falling edge
// === WAKE UP CODE ===
// Restore clocks after dormant wake
sleep_power_up();
// Re-initialize WiFi
if (cyw43_arch_init()) {
while(1) tight_loop_contents();
}
// SUCCESS: 10 very fast blinks
led_blink(10, 50, 50);
// Continue with heartbeat pattern
while(1) {
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);
sleep_ms(100);
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0);
sleep_ms(2900);
}
}
void test_fixed_dormant_mode() {
// Initialize WiFi
if (cyw43_arch_init()) {
while(1) tight_loop_contents();
}
// PHASE 1: Baseline measurement (33mA expected)
led_blink(3, 100, 100); // 3 blinks = starting
sleep_ms(3000); // Measure baseline current
// PHASE 2: Configure for dormant mode PROPERLY
led_blink(5, 200, 200); // 5 slow blinks = preparing for dormant
// Configure wake button
gpio_init(WAKE_PIN);
gpio_set_dir(WAKE_PIN, GPIO_IN);
gpio_pull_up(WAKE_PIN);
// CRITICAL: Configure clock source for dormant mode
// This was missing in previous test!
sleep_run_from_xosc(); // Required for dormant mode
// Turn off LED and WiFi
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0);
cyw43_arch_deinit();
// NOW go dormant - should reach ~1mA
sleep_goto_dormant_until_pin(WAKE_PIN, true, false); // Edge trigger, falling edge
// === WAKE UP CODE ===
// Restore clocks after dormant wake
sleep_power_up();
// Re-initialize WiFi
if (cyw43_arch_init()) {
while(1) tight_loop_contents();
}
// SUCCESS: 10 very fast blinks
led_blink(10, 50, 50);
// Continue with heartbeat pattern
while(1) {
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);
sleep_ms(100);
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0);
sleep_ms(2900);
}
}
int main() {
lposc_dormant_mode();
return 0;
}
I have found out that the xosc sleep mode drops the current draw immediately to 3.8 mA, and it can wake up with the interrupt immediately. However, the lposc sleep seems to have two phases; first it drops to 16 mA for around 40 seconds during which the interrupt does not wake the system up. After that stage, the current draw drops to 1.5 mA, and the system can be awaken with the gp pin interrupt:
This is not a bug report or anything, just an excerpt of knowledge for people who are working on sleep stuff for two weeks with no avail :P
When I test the two different sleep modes with the below code:
I have found out that the xosc sleep mode drops the current draw immediately to 3.8 mA, and it can wake up with the interrupt immediately. However, the lposc sleep seems to have two phases; first it drops to 16 mA for around 40 seconds during which the interrupt does not wake the system up. After that stage, the current draw drops to 1.5 mA, and the system can be awaken with the gp pin interrupt:
Detailed Behavior
XOSC (Crystal Oscillator)
LPOSC (Low Power Oscillator)
This is not a bug report or anything, just an excerpt of knowledge for people who are working on sleep stuff for two weeks with no avail :P
The setup is: