Skip to content

Commit 792f299

Browse files
authored
Merge pull request #1873 from Specter242/codex/sensecap-solar-led-poweroff-parity
sensecap solar: add poweroff/shutdown support and nrf52 PM parity
2 parents 82d1a3d + e08dcbd commit 792f299

7 files changed

Lines changed: 111 additions & 7 deletions

File tree

docs/nrf52_power_management.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Shutdown reason codes (stored in GPREGRET2):
4242
| RAK WisMesh Tag | No | No | No |
4343
| Heltec Mesh Solar | No | No | No |
4444
| LilyGo T-Echo / T-Echo Lite | No | No | No |
45-
| SenseCAP Solar | No | No | No |
45+
| SenseCAP Solar | Yes | Yes | Yes |
4646
| WIO Tracker L1 / L1 E-Ink | No | No | No |
4747
| WIO WM1110 | No | No | No |
4848
| Mesh Pocket | No | No | No |

examples/simple_repeater/main.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ static char command[160];
2323
unsigned long lastActive = 0; // mark last active time
2424
unsigned long nextSleepinSecs = 120; // next sleep in seconds. The first sleep (if enabled) is after 2 minutes from boot
2525

26+
#if defined(PIN_USER_BTN) && defined(_SEEED_SENSECAP_SOLAR_H_)
27+
static unsigned long userBtnDownAt = 0;
28+
#define USER_BTN_HOLD_OFF_MILLIS 1500
29+
#endif
30+
2631
void setup() {
2732
Serial.begin(115200);
2833
delay(1000);
@@ -127,6 +132,21 @@ void loop() {
127132
command[0] = 0; // reset command buffer
128133
}
129134

135+
#if defined(PIN_USER_BTN) && defined(_SEEED_SENSECAP_SOLAR_H_)
136+
// Hold the user button to power off the SenseCAP Solar repeater.
137+
int btnState = digitalRead(PIN_USER_BTN);
138+
if (btnState == LOW) {
139+
if (userBtnDownAt == 0) {
140+
userBtnDownAt = millis();
141+
} else if ((unsigned long)(millis() - userBtnDownAt) >= USER_BTN_HOLD_OFF_MILLIS) {
142+
Serial.println("Powering off...");
143+
board.powerOff(); // does not return
144+
}
145+
} else {
146+
userBtnDownAt = 0;
147+
}
148+
#endif
149+
130150
the_mesh.loop();
131151
sensors.loop();
132152
#ifdef DISPLAY_CLASS

src/helpers/CommonCLI.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,9 @@ uint8_t CommonCLI::buildAdvertData(uint8_t node_type, uint8_t* app_data) {
199199
}
200200

201201
void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, char* reply) {
202-
if (memcmp(command, "reboot", 6) == 0) {
202+
if (memcmp(command, "poweroff", 8) == 0 || memcmp(command, "shutdown", 8) == 0) {
203+
_board->powerOff(); // doesn't return
204+
} else if (memcmp(command, "reboot", 6) == 0) {
203205
_board->reboot(); // doesn't return
204206
} else if (memcmp(command, "clkreboot", 9) == 0) {
205207
// Reset clock

variants/sensecap_solar/SenseCapSolarBoard.cpp

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,67 @@
33

44
#include "SenseCapSolarBoard.h"
55

6+
#ifdef NRF52_POWER_MANAGEMENT
7+
const PowerMgtConfig power_config = {
8+
.lpcomp_ain_channel = PWRMGT_LPCOMP_AIN,
9+
.lpcomp_refsel = PWRMGT_LPCOMP_REFSEL,
10+
.voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK
11+
};
12+
13+
void SenseCapSolarBoard::initiateShutdown(uint8_t reason) {
14+
bool enable_lpcomp = (reason == SHUTDOWN_REASON_LOW_VOLTAGE ||
15+
reason == SHUTDOWN_REASON_BOOT_PROTECT);
16+
17+
pinMode(VBAT_ENABLE, OUTPUT);
18+
digitalWrite(VBAT_ENABLE, enable_lpcomp ? LOW : HIGH);
19+
20+
if (enable_lpcomp) {
21+
configureVoltageWake(power_config.lpcomp_ain_channel, power_config.lpcomp_refsel);
22+
}
23+
24+
enterSystemOff(reason);
25+
}
26+
#endif // NRF52_POWER_MANAGEMENT
27+
628
void SenseCapSolarBoard::begin() {
7-
NRF52Board::begin();
29+
NRF52BoardDCDC::begin();
30+
31+
pinMode(BATTERY_PIN, INPUT);
32+
pinMode(VBAT_ENABLE, OUTPUT);
33+
digitalWrite(VBAT_ENABLE, LOW);
34+
analogReadResolution(12);
35+
analogReference(AR_INTERNAL_3_0);
36+
delay(50);
37+
38+
#ifdef PIN_USER_BTN
39+
pinMode(PIN_USER_BTN, INPUT_PULLUP);
40+
#elif defined(PIN_BUTTON1)
41+
pinMode(PIN_BUTTON1, INPUT_PULLUP);
42+
#endif
843

944
#if defined(PIN_WIRE_SDA) && defined(PIN_WIRE_SCL)
1045
Wire.setPins(PIN_WIRE_SDA, PIN_WIRE_SCL);
1146
#endif
1247

1348
Wire.begin();
1449

50+
#ifdef LED_GREEN
51+
pinMode(LED_GREEN, OUTPUT);
52+
digitalWrite(LED_GREEN, HIGH);
53+
#endif
54+
#ifdef LED_BLUE
55+
pinMode(LED_BLUE, OUTPUT);
56+
digitalWrite(LED_BLUE, LOW);
57+
#endif
58+
1559
#ifdef P_LORA_TX_LED
1660
pinMode(P_LORA_TX_LED, OUTPUT);
1761
digitalWrite(P_LORA_TX_LED, LOW);
1862
#endif
1963

64+
#ifdef NRF52_POWER_MANAGEMENT
65+
checkBootVoltage(&power_config);
66+
#endif
67+
2068
delay(10); // give sx1262 some time to power up
21-
}
69+
}

variants/sensecap_solar/SenseCapSolarBoard.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
#include <helpers/NRF52Board.h>
66

77
class SenseCapSolarBoard : public NRF52BoardDCDC {
8+
protected:
9+
#ifdef NRF52_POWER_MANAGEMENT
10+
void initiateShutdown(uint8_t reason) override;
11+
#endif
12+
813
public:
914
SenseCapSolarBoard() : NRF52Board("SENSECAP_SOLAR_OTA") {}
1015
void begin();
@@ -31,4 +36,25 @@ class SenseCapSolarBoard : public NRF52BoardDCDC {
3136
const char* getManufacturerName() const override {
3237
return "Seeed SenseCap Solar";
3338
}
39+
40+
void powerOff() override {
41+
digitalWrite(LED_GREEN, LOW);
42+
digitalWrite(LED_BLUE, LOW);
43+
44+
#ifdef PIN_USER_BTN
45+
while (digitalRead(PIN_USER_BTN) == LOW);
46+
// Keep pull-up enabled in system-off so the wake line doesn't float low.
47+
nrf_gpio_cfg_sense_input(digitalPinToInterrupt(g_ADigitalPinMap[PIN_USER_BTN]), NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
48+
#elif defined(PIN_BUTTON1)
49+
while (digitalRead(PIN_BUTTON1) == LOW);
50+
// Keep pull-up enabled in system-off so the wake line doesn't float low.
51+
nrf_gpio_cfg_sense_input(digitalPinToInterrupt(g_ADigitalPinMap[PIN_BUTTON1]), NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
52+
#endif
53+
54+
#ifdef NRF52_POWER_MANAGEMENT
55+
initiateShutdown(SHUTDOWN_REASON_USER);
56+
#else
57+
sd_power_system_off();
58+
#endif
59+
}
3460
};

variants/sensecap_solar/platformio.ini

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ build_flags = ${nrf52_base.build_flags}
1010
-I src/helpers/nrf52
1111
-UENV_INCLUDE_GPS
1212
-D NRF52_PLATFORM=1
13+
-D NRF52_POWER_MANAGEMENT
1314
-D RADIO_CLASS=CustomSX1262
1415
-D WRAPPER_CLASS=CustomSX1262Wrapper
15-
-D P_LORA_TX_LED=12
16+
-D P_LORA_TX_LED=11
1617
-D P_LORA_DIO_1=1
1718
-D P_LORA_RESET=2
1819
-D P_LORA_BUSY=3
1920
-D P_LORA_NSS=4
21+
-D PIN_USER_BTN=PIN_BUTTON1
2022
-D LORA_TX_POWER=22
2123
-D SX126X_RXEN=5
2224
-D SX126X_TXEN=RADIOLIB_NC
@@ -96,4 +98,4 @@ build_src_filter = ${SenseCap_Solar.build_src_filter}
9698
+<../examples/companion_radio/*.cpp>
9799
lib_deps =
98100
${SenseCap_Solar.lib_deps}
99-
densaugeo/base64 @ ~1.4.0
101+
densaugeo/base64 @ ~1.4.0

variants/sensecap_solar/variant.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
// Buttons
3333
#define PIN_BUTTON1 (13)
3434
#define PIN_BUTTON2 (20)
35+
#define PIN_USER_BTN PIN_BUTTON1
3536

3637
#define VBAT_ENABLE (19) // Output LOW to enable reading of the BAT voltage.
3738

@@ -41,6 +42,11 @@
4142
#define ADC_MULTIPLIER (3.0F) // 1M, 512k divider bridge
4243
#define ADC_RESOLUTION (12)
4344

45+
// nRF52 power management settings
46+
#define PWRMGT_VOLTAGE_BOOTLOCK (3300) // Won't boot below this voltage (mV)
47+
#define PWRMGT_LPCOMP_AIN (7) // AIN7 = P0.31 = BATTERY_PIN
48+
#define PWRMGT_LPCOMP_REFSEL (2) // 3/8 VDD (~3.38-3.71V)
49+
4450
// Serial interfaces
4551
#define PIN_SERIAL1_RX (7)
4652
#define PIN_SERIAL1_TX (6)
@@ -82,4 +88,4 @@
8288
#define EXTERNAL_FLASH_DEVICES P25Q16H
8389
#define EXTERNAL_FLASH_USE_QSPI
8490

85-
#endif
91+
#endif

0 commit comments

Comments
 (0)