Reduce sender power draw (RX windows + CPU/WiFi/ADC/pins)
- Add LoRa idle/sleep/receive-window helpers and use short RX windows for ACK/time sync - Schedule sender time-sync windows (fast/slow) and track RX vs sleep time in debug - Lower sender power (80 MHz CPU, WiFi/BT off, reduced ADC sampling, unused pins pulldown) - Make SERIAL_DEBUG_MODE a build flag, add prod envs with debug off, and document changes
This commit is contained in:
11
README.md
11
README.md
@@ -256,6 +256,7 @@ inline constexpr uint16_t EXPECTED_SENDER_IDS[NUM_SENDERS] = { 0xF19C };
|
|||||||
- 3.0 V = 0%
|
- 3.0 V = 0%
|
||||||
- 4.2 V = 100%
|
- 4.2 V = 100%
|
||||||
- Uses deep sleep between cycles (`SENDER_WAKE_INTERVAL_SEC`).
|
- Uses deep sleep between cycles (`SENDER_WAKE_INTERVAL_SEC`).
|
||||||
|
- Sender CPU is throttled to 80 MHz and LoRa RX is only enabled in short windows (ACK wait or time-sync).
|
||||||
|
|
||||||
## Web UI
|
## Web UI
|
||||||
- AP SSID: `DD3-Bridge-<short_id>` (prefix configurable)
|
- AP SSID: `DD3-Bridge-<short_id>` (prefix configurable)
|
||||||
@@ -296,12 +297,14 @@ inline constexpr uint16_t EXPECTED_SENDER_IDS[NUM_SENDERS] = { 0xF19C };
|
|||||||
- When no RTC is present or enabled, the receiver keeps sending time sync every 60 seconds.
|
- When no RTC is present or enabled, the receiver keeps sending time sync every 60 seconds.
|
||||||
|
|
||||||
## Build Environments
|
## Build Environments
|
||||||
- `lilygo-t3-v1-6-1`: production build
|
- `lilygo-t3-v1-6-1`: production build (debug on)
|
||||||
- `lilygo-t3-v1-6-1-test`: test build with `ENABLE_TEST_MODE`
|
- `lilygo-t3-v1-6-1-test`: test build with `ENABLE_TEST_MODE`
|
||||||
- `lilygo-t3-v1-6-1-868`: production build for 868 MHz modules
|
- `lilygo-t3-v1-6-1-868`: production build for 868 MHz modules (debug on)
|
||||||
- `lilygo-t3-v1-6-1-868-test`: test build for 868 MHz modules
|
- `lilygo-t3-v1-6-1-868-test`: test build for 868 MHz modules
|
||||||
- `lilygo-t3-v1-6-1-payload-test`: build with `PAYLOAD_CODEC_TEST`
|
- `lilygo-t3-v1-6-1-payload-test`: build with `PAYLOAD_CODEC_TEST`
|
||||||
- `lilygo-t3-v1-6-1-868-payload-test`: 868 MHz build with `PAYLOAD_CODEC_TEST`
|
- `lilygo-t3-v1-6-1-868-payload-test`: 868 MHz build with `PAYLOAD_CODEC_TEST`
|
||||||
|
- `lilygo-t3-v1-6-1-prod`: production build with serial debug off
|
||||||
|
- `lilygo-t3-v1-6-1-868-prod`: 868 MHz production build with serial debug off
|
||||||
|
|
||||||
## Config Knobs
|
## Config Knobs
|
||||||
Key timing settings in `include/config.h`:
|
Key timing settings in `include/config.h`:
|
||||||
@@ -311,9 +314,11 @@ Key timing settings in `include/config.h`:
|
|||||||
- `BATCH_MAX_RETRIES`
|
- `BATCH_MAX_RETRIES`
|
||||||
- `BATCH_QUEUE_DEPTH`
|
- `BATCH_QUEUE_DEPTH`
|
||||||
- `BATCH_RETRY_POLICY` (keep or drop on retry exhaustion)
|
- `BATCH_RETRY_POLICY` (keep or drop on retry exhaustion)
|
||||||
- `SERIAL_DEBUG_MODE` / `SERIAL_DEBUG_DUMP_JSON`
|
- `SERIAL_DEBUG_MODE_FLAG` (build flag) / `SERIAL_DEBUG_DUMP_JSON`
|
||||||
- `LORA_SEND_BYPASS` (debug only)
|
- `LORA_SEND_BYPASS` (debug only)
|
||||||
- `ENABLE_SD_LOGGING` / `PIN_SD_CS`
|
- `ENABLE_SD_LOGGING` / `PIN_SD_CS`
|
||||||
|
- `SENDER_TIMESYNC_WINDOW_MS`
|
||||||
|
- `SENDER_TIMESYNC_CHECK_SEC_FAST` / `SENDER_TIMESYNC_CHECK_SEC_SLOW`
|
||||||
- `SD_HISTORY_MAX_DAYS` / `SD_HISTORY_MIN_RES_MIN`
|
- `SD_HISTORY_MAX_DAYS` / `SD_HISTORY_MIN_RES_MIN`
|
||||||
- `SD_HISTORY_MAX_BINS` / `SD_HISTORY_TIME_BUDGET_MS`
|
- `SD_HISTORY_MAX_BINS` / `SD_HISTORY_TIME_BUDGET_MS`
|
||||||
- `WEB_AUTH_REQUIRE_STA` / `WEB_AUTH_REQUIRE_AP` / `WEB_AUTH_DEFAULT_USER` / `WEB_AUTH_DEFAULT_PASS`
|
- `WEB_AUTH_REQUIRE_STA` / `WEB_AUTH_REQUIRE_AP` / `WEB_AUTH_DEFAULT_USER` / `WEB_AUTH_DEFAULT_PASS`
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ constexpr uint32_t SENDER_WAKE_INTERVAL_SEC = 30;
|
|||||||
constexpr uint32_t TIME_SYNC_INTERVAL_SEC = 60;
|
constexpr uint32_t TIME_SYNC_INTERVAL_SEC = 60;
|
||||||
constexpr uint32_t TIME_SYNC_SLOW_INTERVAL_SEC = 3600;
|
constexpr uint32_t TIME_SYNC_SLOW_INTERVAL_SEC = 3600;
|
||||||
constexpr uint32_t TIME_SYNC_FAST_WINDOW_MS = 10UL * 60UL * 1000UL;
|
constexpr uint32_t TIME_SYNC_FAST_WINDOW_MS = 10UL * 60UL * 1000UL;
|
||||||
|
constexpr uint32_t SENDER_TIMESYNC_WINDOW_MS = 300;
|
||||||
|
constexpr uint32_t SENDER_TIMESYNC_CHECK_SEC_FAST = 60;
|
||||||
|
constexpr uint32_t SENDER_TIMESYNC_CHECK_SEC_SLOW = 3600;
|
||||||
constexpr bool ENABLE_DS3231 = true;
|
constexpr bool ENABLE_DS3231 = true;
|
||||||
constexpr uint32_t OLED_PAGE_INTERVAL_MS = 4000;
|
constexpr uint32_t OLED_PAGE_INTERVAL_MS = 4000;
|
||||||
constexpr uint32_t OLED_AUTO_OFF_MS = 10UL * 60UL * 1000UL;
|
constexpr uint32_t OLED_AUTO_OFF_MS = 10UL * 60UL * 1000UL;
|
||||||
@@ -73,7 +76,10 @@ constexpr uint8_t BATCH_QUEUE_DEPTH = 10;
|
|||||||
constexpr BatchRetryPolicy BATCH_RETRY_POLICY = BatchRetryPolicy::Keep;
|
constexpr BatchRetryPolicy BATCH_RETRY_POLICY = BatchRetryPolicy::Keep;
|
||||||
constexpr uint32_t WATCHDOG_TIMEOUT_SEC = 120;
|
constexpr uint32_t WATCHDOG_TIMEOUT_SEC = 120;
|
||||||
constexpr bool ENABLE_HA_DISCOVERY = true;
|
constexpr bool ENABLE_HA_DISCOVERY = true;
|
||||||
constexpr bool SERIAL_DEBUG_MODE = true;
|
#ifndef SERIAL_DEBUG_MODE_FLAG
|
||||||
|
#define SERIAL_DEBUG_MODE_FLAG 0
|
||||||
|
#endif
|
||||||
|
constexpr bool SERIAL_DEBUG_MODE = SERIAL_DEBUG_MODE_FLAG != 0;
|
||||||
constexpr bool SERIAL_DEBUG_DUMP_JSON = false;
|
constexpr bool SERIAL_DEBUG_DUMP_JSON = false;
|
||||||
constexpr bool LORA_SEND_BYPASS = false;
|
constexpr bool LORA_SEND_BYPASS = false;
|
||||||
constexpr bool ENABLE_SD_LOGGING = true;
|
constexpr bool ENABLE_SD_LOGGING = true;
|
||||||
|
|||||||
@@ -19,5 +19,7 @@ struct LoraPacket {
|
|||||||
void lora_init();
|
void lora_init();
|
||||||
bool lora_send(const LoraPacket &pkt);
|
bool lora_send(const LoraPacket &pkt);
|
||||||
bool lora_receive(LoraPacket &pkt, uint32_t timeout_ms);
|
bool lora_receive(LoraPacket &pkt, uint32_t timeout_ms);
|
||||||
|
void lora_idle();
|
||||||
void lora_sleep();
|
void lora_sleep();
|
||||||
|
bool lora_receive_window(LoraPacket &pkt, uint32_t timeout_ms);
|
||||||
uint32_t lora_airtime_ms(size_t packet_len);
|
uint32_t lora_airtime_ms(size_t packet_len);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
void power_sender_init();
|
void power_sender_init();
|
||||||
void power_receiver_init();
|
void power_receiver_init();
|
||||||
|
void power_configure_unused_pins_sender();
|
||||||
void read_battery(MeterData &data);
|
void read_battery(MeterData &data);
|
||||||
uint8_t battery_percent_from_voltage(float voltage_v);
|
uint8_t battery_percent_from_voltage(float voltage_v);
|
||||||
void light_sleep_ms(uint32_t ms);
|
void light_sleep_ms(uint32_t ms);
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ lib_deps =
|
|||||||
adafruit/Adafruit SSD1306@^2.5.9
|
adafruit/Adafruit SSD1306@^2.5.9
|
||||||
adafruit/Adafruit GFX Library@^1.11.9
|
adafruit/Adafruit GFX Library@^1.11.9
|
||||||
knolleary/PubSubClient@^2.8
|
knolleary/PubSubClient@^2.8
|
||||||
|
build_flags =
|
||||||
|
-DSERIAL_DEBUG_MODE_FLAG=1
|
||||||
|
|
||||||
[env:lilygo-t3-v1-6-1-test]
|
[env:lilygo-t3-v1-6-1-test]
|
||||||
platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.07/platform-espressif32.zip
|
platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.07/platform-espressif32.zip
|
||||||
@@ -30,6 +32,7 @@ lib_deps =
|
|||||||
adafruit/Adafruit GFX Library@^1.11.9
|
adafruit/Adafruit GFX Library@^1.11.9
|
||||||
knolleary/PubSubClient@^2.8
|
knolleary/PubSubClient@^2.8
|
||||||
build_flags =
|
build_flags =
|
||||||
|
-DSERIAL_DEBUG_MODE_FLAG=1
|
||||||
-DENABLE_TEST_MODE
|
-DENABLE_TEST_MODE
|
||||||
|
|
||||||
[env:lilygo-t3-v1-6-1-868]
|
[env:lilygo-t3-v1-6-1-868]
|
||||||
@@ -43,6 +46,7 @@ lib_deps =
|
|||||||
adafruit/Adafruit GFX Library@^1.11.9
|
adafruit/Adafruit GFX Library@^1.11.9
|
||||||
knolleary/PubSubClient@^2.8
|
knolleary/PubSubClient@^2.8
|
||||||
build_flags =
|
build_flags =
|
||||||
|
-DSERIAL_DEBUG_MODE_FLAG=1
|
||||||
-DLORA_FREQUENCY_HZ=868E6
|
-DLORA_FREQUENCY_HZ=868E6
|
||||||
|
|
||||||
[env:lilygo-t3-v1-6-1-868-test]
|
[env:lilygo-t3-v1-6-1-868-test]
|
||||||
@@ -56,6 +60,7 @@ lib_deps =
|
|||||||
adafruit/Adafruit GFX Library@^1.11.9
|
adafruit/Adafruit GFX Library@^1.11.9
|
||||||
knolleary/PubSubClient@^2.8
|
knolleary/PubSubClient@^2.8
|
||||||
build_flags =
|
build_flags =
|
||||||
|
-DSERIAL_DEBUG_MODE_FLAG=1
|
||||||
-DENABLE_TEST_MODE
|
-DENABLE_TEST_MODE
|
||||||
-DLORA_FREQUENCY_HZ=868E6
|
-DLORA_FREQUENCY_HZ=868E6
|
||||||
|
|
||||||
@@ -70,6 +75,7 @@ lib_deps =
|
|||||||
adafruit/Adafruit GFX Library@^1.11.9
|
adafruit/Adafruit GFX Library@^1.11.9
|
||||||
knolleary/PubSubClient@^2.8
|
knolleary/PubSubClient@^2.8
|
||||||
build_flags =
|
build_flags =
|
||||||
|
-DSERIAL_DEBUG_MODE_FLAG=1
|
||||||
-DPAYLOAD_CODEC_TEST
|
-DPAYLOAD_CODEC_TEST
|
||||||
|
|
||||||
[env:lilygo-t3-v1-6-1-868-payload-test]
|
[env:lilygo-t3-v1-6-1-868-payload-test]
|
||||||
@@ -83,5 +89,33 @@ lib_deps =
|
|||||||
adafruit/Adafruit GFX Library@^1.11.9
|
adafruit/Adafruit GFX Library@^1.11.9
|
||||||
knolleary/PubSubClient@^2.8
|
knolleary/PubSubClient@^2.8
|
||||||
build_flags =
|
build_flags =
|
||||||
|
-DSERIAL_DEBUG_MODE_FLAG=1
|
||||||
-DPAYLOAD_CODEC_TEST
|
-DPAYLOAD_CODEC_TEST
|
||||||
-DLORA_FREQUENCY_HZ=868E6
|
-DLORA_FREQUENCY_HZ=868E6
|
||||||
|
|
||||||
|
[env:lilygo-t3-v1-6-1-prod]
|
||||||
|
platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.07/platform-espressif32.zip
|
||||||
|
board = ttgo-lora32-v1
|
||||||
|
framework = arduino
|
||||||
|
lib_deps =
|
||||||
|
sandeepmistry/LoRa@^0.8.0
|
||||||
|
bblanchon/ArduinoJson@^6.21.5
|
||||||
|
adafruit/Adafruit SSD1306@^2.5.9
|
||||||
|
adafruit/Adafruit GFX Library@^1.11.9
|
||||||
|
knolleary/PubSubClient@^2.8
|
||||||
|
build_flags =
|
||||||
|
-DSERIAL_DEBUG_MODE_FLAG=0
|
||||||
|
|
||||||
|
[env:lilygo-t3-v1-6-1-868-prod]
|
||||||
|
platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.07/platform-espressif32.zip
|
||||||
|
board = ttgo-lora32-v1
|
||||||
|
framework = arduino
|
||||||
|
lib_deps =
|
||||||
|
sandeepmistry/LoRa@^0.8.0
|
||||||
|
bblanchon/ArduinoJson@^6.21.5
|
||||||
|
adafruit/Adafruit SSD1306@^2.5.9
|
||||||
|
adafruit/Adafruit GFX Library@^1.11.9
|
||||||
|
knolleary/PubSubClient@^2.8
|
||||||
|
build_flags =
|
||||||
|
-DSERIAL_DEBUG_MODE_FLAG=0
|
||||||
|
-DLORA_FREQUENCY_HZ=868E6
|
||||||
|
|||||||
@@ -110,10 +110,24 @@ bool lora_receive(LoraPacket &pkt, uint32_t timeout_ms) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lora_idle() {
|
||||||
|
LoRa.idle();
|
||||||
|
}
|
||||||
|
|
||||||
void lora_sleep() {
|
void lora_sleep() {
|
||||||
LoRa.sleep();
|
LoRa.sleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool lora_receive_window(LoraPacket &pkt, uint32_t timeout_ms) {
|
||||||
|
if (timeout_ms == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LoRa.receive();
|
||||||
|
bool got = lora_receive(pkt, timeout_ms);
|
||||||
|
LoRa.sleep();
|
||||||
|
return got;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t lora_airtime_ms(size_t packet_len) {
|
uint32_t lora_airtime_ms(size_t packet_len) {
|
||||||
if (packet_len == 0) {
|
if (packet_len == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
88
src/main.cpp
88
src/main.cpp
@@ -88,6 +88,10 @@ static uint8_t g_inflight_count = 0;
|
|||||||
static uint16_t g_inflight_batch_id = 0;
|
static uint16_t g_inflight_batch_id = 0;
|
||||||
static bool g_inflight_active = false;
|
static bool g_inflight_active = false;
|
||||||
static uint32_t g_last_debug_log_ms = 0;
|
static uint32_t g_last_debug_log_ms = 0;
|
||||||
|
static uint32_t g_sender_last_timesync_check_ms = 0;
|
||||||
|
static uint32_t g_sender_rx_window_ms = 0;
|
||||||
|
static uint32_t g_sender_sleep_ms = 0;
|
||||||
|
static uint32_t g_sender_power_log_ms = 0;
|
||||||
|
|
||||||
static void watchdog_kick();
|
static void watchdog_kick();
|
||||||
|
|
||||||
@@ -144,6 +148,22 @@ static void update_battery_cache() {
|
|||||||
g_last_battery_ms = millis();
|
g_last_battery_ms = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool sender_timesync_window_due() {
|
||||||
|
uint32_t interval_sec = SENDER_TIMESYNC_CHECK_SEC_FAST;
|
||||||
|
if (time_is_synced() && time_rtc_present()) {
|
||||||
|
interval_sec = SENDER_TIMESYNC_CHECK_SEC_SLOW;
|
||||||
|
}
|
||||||
|
if (g_sender_last_timesync_check_ms == 0) {
|
||||||
|
g_sender_last_timesync_check_ms = millis() - interval_sec * 1000UL;
|
||||||
|
}
|
||||||
|
uint32_t now_ms = millis();
|
||||||
|
if (now_ms - g_sender_last_timesync_check_ms >= interval_sec * 1000UL) {
|
||||||
|
g_sender_last_timesync_check_ms = now_ms;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool batch_queue_drop_oldest() {
|
static bool batch_queue_drop_oldest() {
|
||||||
if (g_batch_count == 0) {
|
if (g_batch_count == 0) {
|
||||||
return false;
|
return false;
|
||||||
@@ -620,6 +640,7 @@ void setup() {
|
|||||||
|
|
||||||
if (g_role == DeviceRole::Sender) {
|
if (g_role == DeviceRole::Sender) {
|
||||||
power_sender_init();
|
power_sender_init();
|
||||||
|
power_configure_unused_pins_sender();
|
||||||
meter_init();
|
meter_init();
|
||||||
g_last_sample_ms = millis() - METER_SAMPLE_INTERVAL_MS;
|
g_last_sample_ms = millis() - METER_SAMPLE_INTERVAL_MS;
|
||||||
g_last_send_ms = millis();
|
g_last_send_ms = millis();
|
||||||
@@ -712,37 +733,18 @@ static void sender_loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (g_batch_ack_pending) {
|
if (g_batch_ack_pending) {
|
||||||
uint32_t end_ms = millis() + 400;
|
LoraPacket ack_pkt = {};
|
||||||
while (millis() < end_ms) {
|
uint32_t rx_start = millis();
|
||||||
LoraPacket ack_pkt = {};
|
bool got_ack = lora_receive_window(ack_pkt, 400);
|
||||||
if (!lora_receive(ack_pkt, 0) || ack_pkt.protocol_version != PROTOCOL_VERSION) {
|
uint32_t rx_elapsed = millis() - rx_start;
|
||||||
delay(5);
|
if (SERIAL_DEBUG_MODE) {
|
||||||
continue;
|
g_sender_rx_window_ms += rx_elapsed;
|
||||||
}
|
|
||||||
if (ack_pkt.payload_type == PayloadType::Ack && ack_pkt.payload_len >= 6 && ack_pkt.role == DeviceRole::Receiver) {
|
|
||||||
uint16_t ack_id = read_u16_le(ack_pkt.payload);
|
|
||||||
uint16_t ack_sender = read_u16_le(&ack_pkt.payload[2]);
|
|
||||||
uint16_t ack_receiver = read_u16_le(&ack_pkt.payload[4]);
|
|
||||||
if (ack_sender == g_short_id && ack_receiver == ack_pkt.device_id_short &&
|
|
||||||
g_batch_ack_pending && ack_id == g_last_sent_batch_id) {
|
|
||||||
g_last_acked_batch_id = ack_id;
|
|
||||||
serial_debug_printf("ack: ok batch_id=%u", ack_id);
|
|
||||||
finish_inflight_batch();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
if (got_ack && ack_pkt.payload_type == PayloadType::Ack && ack_pkt.payload_len >= 6 && ack_pkt.role == DeviceRole::Receiver) {
|
||||||
|
uint16_t ack_id = read_u16_le(ack_pkt.payload);
|
||||||
LoraPacket rx = {};
|
uint16_t ack_sender = read_u16_le(&ack_pkt.payload[2]);
|
||||||
if (lora_receive(rx, 0) && rx.protocol_version == PROTOCOL_VERSION) {
|
uint16_t ack_receiver = read_u16_le(&ack_pkt.payload[4]);
|
||||||
if (rx.payload_type == PayloadType::TimeSync) {
|
if (ack_sender == g_short_id && ack_receiver == ack_pkt.device_id_short &&
|
||||||
time_handle_timesync_payload(rx.payload, rx.payload_len);
|
|
||||||
} else if (rx.payload_type == PayloadType::Ack && rx.payload_len >= 6 && rx.role == DeviceRole::Receiver) {
|
|
||||||
uint16_t ack_id = read_u16_le(rx.payload);
|
|
||||||
uint16_t ack_sender = read_u16_le(&rx.payload[2]);
|
|
||||||
uint16_t ack_receiver = read_u16_le(&rx.payload[4]);
|
|
||||||
if (ack_sender == g_short_id && ack_receiver == rx.device_id_short &&
|
|
||||||
g_batch_ack_pending && ack_id == g_last_sent_batch_id) {
|
g_batch_ack_pending && ack_id == g_last_sent_batch_id) {
|
||||||
g_last_acked_batch_id = ack_id;
|
g_last_acked_batch_id = ack_id;
|
||||||
serial_debug_printf("ack: ok batch_id=%u", ack_id);
|
serial_debug_printf("ack: ok batch_id=%u", ack_id);
|
||||||
@@ -751,6 +753,23 @@ static void sender_loop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool timesync_due = (!g_batch_ack_pending && sender_timesync_window_due());
|
||||||
|
if (timesync_due) {
|
||||||
|
LoraPacket rx = {};
|
||||||
|
uint32_t rx_start = millis();
|
||||||
|
bool got = lora_receive_window(rx, SENDER_TIMESYNC_WINDOW_MS);
|
||||||
|
uint32_t rx_elapsed = millis() - rx_start;
|
||||||
|
if (SERIAL_DEBUG_MODE) {
|
||||||
|
g_sender_rx_window_ms += rx_elapsed;
|
||||||
|
}
|
||||||
|
if (got && rx.payload_type == PayloadType::TimeSync) {
|
||||||
|
time_handle_timesync_payload(rx.payload, rx.payload_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!g_batch_ack_pending) {
|
||||||
|
lora_sleep();
|
||||||
|
}
|
||||||
|
|
||||||
if (g_batch_ack_pending && (now_ms - g_last_batch_send_ms >= g_batch_ack_timeout_ms)) {
|
if (g_batch_ack_pending && (now_ms - g_last_batch_send_ms >= g_batch_ack_timeout_ms)) {
|
||||||
if (g_batch_retry_count < BATCH_MAX_RETRIES) {
|
if (g_batch_retry_count < BATCH_MAX_RETRIES) {
|
||||||
g_batch_retry_count++;
|
g_batch_retry_count++;
|
||||||
@@ -780,6 +799,15 @@ static void sender_loop() {
|
|||||||
uint32_t next_due = next_sample_due < next_send_due ? next_sample_due : next_send_due;
|
uint32_t next_due = next_sample_due < next_send_due ? next_sample_due : next_send_due;
|
||||||
if (!g_batch_ack_pending && next_due > now_ms) {
|
if (!g_batch_ack_pending && next_due > now_ms) {
|
||||||
watchdog_kick();
|
watchdog_kick();
|
||||||
|
if (SERIAL_DEBUG_MODE) {
|
||||||
|
g_sender_sleep_ms += (next_due - now_ms);
|
||||||
|
if (now_ms - g_sender_power_log_ms >= 10000) {
|
||||||
|
g_sender_power_log_ms = now_ms;
|
||||||
|
serial_debug_printf("power: rx_ms=%lu sleep_ms=%lu", static_cast<unsigned long>(g_sender_rx_window_ms),
|
||||||
|
static_cast<unsigned long>(g_sender_sleep_ms));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lora_sleep();
|
||||||
light_sleep_ms(next_due - now_ms);
|
light_sleep_ms(next_due - now_ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ static constexpr float BATTERY_CAL = 1.0f;
|
|||||||
static constexpr float ADC_REF_V = 3.3f;
|
static constexpr float ADC_REF_V = 3.3f;
|
||||||
|
|
||||||
void power_sender_init() {
|
void power_sender_init() {
|
||||||
|
setCpuFrequencyMhz(80);
|
||||||
|
WiFi.mode(WIFI_OFF);
|
||||||
esp_wifi_stop();
|
esp_wifi_stop();
|
||||||
|
esp_wifi_deinit();
|
||||||
btStop();
|
btStop();
|
||||||
analogReadResolution(12);
|
analogReadResolution(12);
|
||||||
pinMode(PIN_BAT_ADC, INPUT);
|
pinMode(PIN_BAT_ADC, INPUT);
|
||||||
@@ -22,14 +25,19 @@ void power_receiver_init() {
|
|||||||
pinMode(PIN_BAT_ADC, INPUT);
|
pinMode(PIN_BAT_ADC, INPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_battery(MeterData &data) {
|
void power_configure_unused_pins_sender() {
|
||||||
const int samples = 8;
|
// Board-specific: only touch pins that are known unused and safe on TTGO LoRa32 v1.6.1
|
||||||
uint32_t sum = 0;
|
const uint8_t pins[] = {32, 33};
|
||||||
for (int i = 0; i < samples; ++i) {
|
for (uint8_t pin : pins) {
|
||||||
sum += analogRead(PIN_BAT_ADC);
|
pinMode(pin, INPUT_PULLDOWN);
|
||||||
delay(5);
|
|
||||||
}
|
}
|
||||||
float avg = static_cast<float>(sum) / samples;
|
}
|
||||||
|
|
||||||
|
void read_battery(MeterData &data) {
|
||||||
|
uint32_t sum = 0;
|
||||||
|
sum += analogRead(PIN_BAT_ADC);
|
||||||
|
sum += analogRead(PIN_BAT_ADC);
|
||||||
|
float avg = static_cast<float>(sum) / 2.0f;
|
||||||
float v = (avg / 4095.0f) * ADC_REF_V * BATTERY_DIVIDER * BATTERY_CAL;
|
float v = (avg / 4095.0f) * ADC_REF_V * BATTERY_DIVIDER * BATTERY_CAL;
|
||||||
|
|
||||||
data.battery_voltage_v = v;
|
data.battery_voltage_v = v;
|
||||||
|
|||||||
Reference in New Issue
Block a user