Repository navigation
Conversation
…eshcore-dev#1411) Add hardware button power management for RAK4631 and Muziworks R1 builds, and resolve immediate wakeup from SYSTEMOFF sleep (supersedes meshcore-dev#2701). Key Changes: - Button Power-Down: Monitor BOARD_BUTTON_PIN (WB_A1 / PIN_USER_BTN_ANA) in RAK4631Board::loop(). A 3-second long press illuminates the green LED (PIN_LED1) as power-down confirmation (leaving the blue LED for BLE status) and initiates deep sleep upon button release. - Debounce & Release Settle: Wait for stable button release before power down, and enforce a 50ms settle window before arming SENSE LOW. - Radio Isolation: Detach RadioLib interrupts (DIO1, BUSY) and reset SX1262 pins to default prior to disabling SX126X_POWER_EN. This prevents the collapsing power rail from triggering a false GPIO DETECT interrupt. - BLE Graceful Disconnect: Disconnect active BLE connections and stop advertising before entering sleep so companion apps disconnect cleanly. - LATCH Clearing: Disable SENSE on non-button pins and clear NRF_P0/P1 LATCH registers right before entering SYSTEMOFF, preventing immediate auto-wake. Hardware Testing: - Verified on a physical Muziworks R1 unit (RAK4631 + WisBlock base with hardware button on WB_A1 / Pin 31). - Confirmed normal BLE operation, 3-second long-press detection with green LED indicator, graceful mobile app disconnect, and sustained SYSTEMOFF deep sleep with all LEDs off (no spurious or immediate wakeups). - Confirmed wake from sleep via reset button back to full operational state. Fixes meshcore-dev#1411 Supersedes meshcore-dev#2701
|
Tested this PR on a RAK19007 base + RAK4631 core with an SSD1306 OLED, built from Issue on boards with a display: the 3-second long-press and the CLI/app Hibernate didn't have this problem because Fix I tested: send the SSD1306 display-off and charge-pump-off commands in @@ -96,6 +96,22 @@ void RAK4631Board::initiateShutdown(uint8_t reason) {
}
#endif
+#if defined(DISPLAY_CLASS)
+ // The OLED stays powered from 3V3 in SYSTEMOFF and keeps showing its last frame,
+ // which makes a successful power-off look like a freeze. Paths such as the
+ // long-press and the CLI "poweroff" command bypass UITask::shutdown(), so blank
+ // the panel here: display off (0xAE) and charge pump off (0x8D, 0x10).
+ #ifndef DISPLAY_ADDRESS
+ #define DISPLAY_ADDRESS 0x3C
+ #endif
+ Wire.beginTransmission(DISPLAY_ADDRESS);
+ Wire.write(0x00); // control byte: command stream
+ Wire.write(0xAE);
+ Wire.write(0x8D);
+ Wire.write(0x10);
+ Wire.endTransmission();
+#endif
+
// Disconnect LoRa pins and detach RadioLib interrupts before powering downWith this change, the long-press, A cleaner long-term option might be to route the long-press and Note: the diagnosis and patch were AI-assisted (Claude). I built, flashed and tested the result on my own hardware. |
When entering SYSTEMOFF deep sleep from a button long-press or CLI poweroff, the 3V3 rail keeps the SSD1306 OLED powered with its last frame displayed, making the shutdown appear like a system freeze. Send display-off (0xAE) and charge-pump-off (0x8D, 0x10) commands over I2C in RAK4631Board::initiateShutdown() before entering SYSTEMOFF. Co-authored-by: StarWhiz <StarWhiz@users.noreply.github.com>
|
@StarWhiz I've added your patch and made a commit. It does not affect my non-display device. Would you double check your device and report back? I'm hopeful the powers that be will accept this. :) |
|
@komacke Thanks for adding the OLED patch. I worked with Claude again and re-tested. I found that I was wrong in my earlier comment: on my board the device never actually reached SYSTEMOFF. It hung in Hardware: RAK19007 + RAK4631 + SSD1306, Cause: Evidence (serial log from a temporary diagnostic build, button released): Without step 4b, the log stayed at Fix: release the SAADC channel inputs before the button pin is used digitally. This applies only when the button is analog: @@ -132,4 +132,14 @@ void RAK4631Board::initiateShutdown(uint8_t reason) {
#if defined(BOARD_BUTTON_PIN)
+#if defined(PIN_USER_BTN_ANA) && (PIN_USER_BTN_ANA >= 0)
+ // analogRead() disables the SAADC afterwards but leaves its channel inputs
+ // selecting the button's AIN pin. While selected, the pin's digital input reads 0,
+ // so the settle loop below never exits and SENSE could never see a press.
+ // Release every channel so the button pin works as a digital input again.
+ for (int i = 0; i < 8; i++) {
+ NRF_SAADC->CH[i].PSELP = SAADC_CH_PSELP_PSELP_NC;
+ NRF_SAADC->CH[i].PSELN = SAADC_CH_PSELN_PSELN_NC;
+ }
+#endif
// Ensure pullup is engaged and line is stably HIGH before arming SENSE
pinMode(BOARD_BUTTON_PIN, INPUT_PULLUP);Tested on top of Possibly worth considering: a timeout on the settle loop and on the final AI-assisted (Claude): diagnosis, diagnostic build and patch. I built, flashed and tested everything on my own hardware. |
analogRead() on the user button pin (PIN_USER_BTN_ANA / AIN7) leaves the SAADC channel multiplexer mapped to the pin, causing its digital input buffer to read LOW even when pulled up to 3.3V. This prevented the shutdown settle loop from exiting and kept SENSE_LOW from detecting wake presses. Disconnect all SAADC channels (PSELP/PSELN = NC) before enabling digital pullup in initiateShutdown(). Additionally, add 3-second safety timeouts to both the settle and release loops as a fail-safe against stuck inputs. Tested and confirmed on hardware: verified that the USB serial mapping was not dropping before this update (confirming the hang in initiateShutdown), and now cleanly drops upon entering SYSTEMOFF, and the device wakes up properly on button press. Thanks to @StarWhiz for the diagnosis and patch. Co-authored-by: StarWhiz <StarWhiz@users.noreply.github.com>
|
@StarWhiz Thanks for being thorough! I had not noticed that the USB mapping did not go away. I was in the process of doing a long power-off test and forgot about it. it is draining slowly but clearly it's going to drain more slowing now. :) Your patch and suggested settle loop timeout also added. |
Summary
This PR implements hardware button power management for RAK4631 / Muziworks R1 hardware, enabling deep sleep power-down via long-press, and fixes the immediate wakeup from
SYSTEMOFF(superseding #2701).Background & Root Cause
WB_A1/ Pin 31) had no hardware button power-off monitoring inrak4631.SYSTEMOFFpreviously triggered an immediate reboot (RESETREAS=0x00010000, GPIO DETECT) because:DIO1andBUSYfired as the SX1262 power rail collapsed.LATCHregisters.Key Changes
BOARD_BUTTON_PIN(WB_A1/PIN_USER_BTN_ANA) inRAK4631Board::loop(). A 3-second long press illuminates the green LED (PIN_LED1) as confirmation (leaving the blue LED for BLE status) and initiates deep sleep upon button release.NRF_GPIO_PIN_SENSE_LOW.detachInterrupt()and reset SX1262 pins to default prior to pullingSX126X_POWER_ENlow. Disable SENSE on all non-button pins.Bluefruit.disconnect()) and stop advertising before entering sleep.0xFFFFFFFFtoNRF_P0->LATCHandNRF_P1->LATCHright before enteringSYSTEMOFF.variants/rak4631/. Other variants and newer Muziworks hardware (muzi_base,muziworks_r1_neo) remain untouched. All RAK4631 build targets (BLE, USB, Repeater, Room Server, Terminal Chat) compile cleanly.Hardware Testing
Closes #1411
Supersedes #2701