Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a4d59d4
To support powersaving mode with lightsleep at 9mA
IoTThinks Nov 16, 2025
2d9077b
To support lightsleep
IoTThinks Nov 16, 2025
6988834
To support powersaving mode with lightsleep at 9mA
IoTThinks Nov 16, 2025
9e9b280
To support powersaving mode with lightsleep at 9mA
IoTThinks Nov 16, 2025
c16102b
To support powersaving mode with lightsleep at 9mA
IoTThinks Nov 16, 2025
d0c342f
To support powersaving mode with lightsleep at 9mA
IoTThinks Nov 16, 2025
1f9806c
To support powersaving mode with lightsleep at 9mA
IoTThinks Nov 16, 2025
b54028e
To awake for 2 minutes in first boot / restart to support Repeater se…
IoTThinks Nov 19, 2025
0e77f9e
Modify sleep duration and wake-up behavior
IoTThinks Nov 22, 2025
56df774
Modify sleep method to accept seconds parameter
IoTThinks Nov 22, 2025
3599a26
Modify sleep function to take seconds as parameter
IoTThinks Nov 22, 2025
c33cd2b
Modify sleep function to accept duration parameter
IoTThinks Nov 22, 2025
d86f596
Modify sleep function to accept duration parameter
IoTThinks Nov 22, 2025
d8954fa
Refactor HeltecV3Board: Remove light sleep methods
IoTThinks Nov 24, 2025
adae43b
Remove light sleep functions
IoTThinks Nov 24, 2025
745566e
Refactor HeltecV4Board by removing light sleep methods
IoTThinks Nov 24, 2025
e636996
Implement light sleep and sleep methods
IoTThinks Nov 24, 2025
f94412b
Enable power saving mode in platformio.ini
IoTThinks Nov 24, 2025
97d7eeb
To support ESP32S3 and validate RTC GPIO
IoTThinks Nov 30, 2025
822c249
Disable powersaving mode in platformio.ini
IoTThinks Nov 30, 2025
20ab10f
To get the current pending outbound packets at Dispatcher
IoTThinks Dec 5, 2025
acee014
To get the current pending outbound packets at Dispatcher
IoTThinks Dec 5, 2025
b97fb20
To postpone sleep to further 5s if there is pending outbound
IoTThinks Dec 5, 2025
dd18ae7
Renamed getOutboundCount in MyMesh to hasPendingWork()
IoTThinks Dec 22, 2025
4bc4d5a
Merge branch 'dev' into dev
IoTThinks Dec 22, 2025
79be9ca
Update src/helpers/ESP32Board.h
IoTThinks Dec 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions examples/simple_repeater/MyMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1115,3 +1115,8 @@ void MyMesh::loop() {
uptime_millis += now - last_millis;
last_millis = now;
}

// To get the current pending outbound packets at Dispatcher
int MyMesh::hasPendingWork(uint32_t now) const {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the now parameter. It's not used.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. This PR 1107 is much older than PR 1238.
    In my PowerSaving fork, NRF52 is enjoying 8.5mA power consumption for a while.
    All these stuff will be pushed after this PR is approved.

  2. Last time, I'm thinking to use CLI to enable/disable powersaving mode.
    However, I believe powersaving mode should be the default and built-in feature.
    For IoT world, power saving is actually a must.

Copy link
Author

@IoTThinks IoTThinks Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fschrempf We may just change the comment to become " To get the current pending works"
Or yes, just make it int MyMesh::hasPendingWork() const {

// To get the current pending outbound packets at Dispatcher
int MyMesh::hasPendingWork(uint32_t now) const {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You either have to remove the now parameter, or pass it on to getOutboundCount(). Keeping it without using it doesn't make sense.

return _mgr->getOutboundCount(0xFFFFFFFF);
}
3 changes: 3 additions & 0 deletions examples/simple_repeater/MyMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,4 +225,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
bridge.begin();
}
#endif

// To get the current pending outbound packets at Dispatcher
int hasPendingWork(uint32_t now) const;
};
21 changes: 21 additions & 0 deletions examples/simple_repeater/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,21 @@ void halt() {

static char command[160];

#ifdef POWERSAVING_MODE
unsigned long lastActive = 0; // mark last active time
unsigned long nextSleepinSecs = 120; // next sleep in seconds. First time is 2m to send advert and do repeater setup.
#endif

void setup() {
Serial.begin(115200);
delay(1000);

board.begin();

#ifdef POWERSAVING_MODE
lastActive = millis(); // mark last active time at boot
#endif

#ifdef DISPLAY_CLASS
if (display.begin()) {
display.startFrame();
Expand Down Expand Up @@ -117,4 +126,16 @@ void loop() {
ui_task.loop();
#endif
rtc_clock.tick();

#ifdef POWERSAVING_MODE
if (the_mesh.millisHasNowPassed(lastActive + nextSleepinSecs * 1000)) { // Try to sleep every nextSleepinSecs seconds
if(the_mesh.hasPendingWork(0xFFFFFFFF) == 0) { // Has no pending work. Safe to sleep
board.sleep(1800); // To sleep. Wake up after 30 minutes or when receiving a LoRa packet
lastActive = millis();
nextSleepinSecs = 5; // Default: To work for 5s and sleep again
} else {
nextSleepinSecs += 5; // To give 5 more seconds to send
}
}
#endif
}
3 changes: 2 additions & 1 deletion src/MeshCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class MainBoard {
virtual void onAfterTransmit() { }
virtual void reboot() = 0;
virtual void powerOff() { /* no op */ }
virtual void sleep(uint32_t secs) { /* no op */ }
virtual uint32_t getGpio() { return 0; }
virtual void setGpio(uint32_t values) {}
virtual uint8_t getStartupReason() const = 0;
Expand Down Expand Up @@ -90,4 +91,4 @@ class RTCClock {
}
};

}
}
21 changes: 21 additions & 0 deletions src/helpers/ESP32Board.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <rom/rtc.h>
#include <sys/time.h>
#include <Wire.h>
#include <WiFi.h>
#include "driver/rtc_io.h"

class ESP32Board : public mesh::MainBoard {
protected:
Expand Down Expand Up @@ -42,6 +44,25 @@ class ESP32Board : public mesh::MainBoard {
#endif
}

void enterLightSleep(uint32_t secs) {
#if defined(CONFIG_IDF_TARGET_ESP32S3) // Supported ESP32 variants
if (rtc_gpio_is_valid_gpio((gpio_num_t)P_LORA_DIO_1)) { // Only enter sleep mode if P_LORA_DIO_1 is RTC pin
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
esp_sleep_enable_ext1_wakeup((1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // To wake up when receiving a LoRa packet

if (secs > 0) {
esp_sleep_enable_timer_wakeup(secs * 1000000); // To wake up every hour to do periodically jobs
}

esp_light_sleep_start(); // CPU enters light sleep
}
#endif
}

void sleep(uint32_t secs) override {
if (WiFi.getMode() == WIFI_MODE_NULL) { // WiFi is off ~ No active OTA, safe to go to sleep
enterLightSleep(secs); // To wake up after "secs" seconds or when receiving a LoRa packet
}
// Temperature from ESP32 MCU
float getMCUTemperature() override {
return temperatureRead();
Expand Down
1 change: 1 addition & 0 deletions variants/heltec_v3/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ build_flags =
-D MAX_NEIGHBOURS=50
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
-D POWERSAVING_MODE=1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really like the fact that we are enabling this for specific boards only. I know this can be rolled out to other boards later, but it will likely be confusing for some users if some boards show a different behavior than others (for example CLI accessibility after the initial 2 minute period).

Copy link
Author

@IoTThinks IoTThinks Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we will have power saving to all boards soon by default. All will have the same powersaving behaviors.
However due to large user base of MeshCore, we would like to see the impact of the change to Heltec v3/v4 first.

build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<../examples/simple_repeater>
Expand Down
1 change: 1 addition & 0 deletions variants/heltec_v4/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ build_flags =
-D MAX_NEIGHBOURS=50
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
-D POWERSAVING_MODE=1
build_src_filter = ${Heltec_lora32_v4.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<../examples/simple_repeater>
Expand Down