Add software LiPo UV protection with energy-save boot.

Detect under-voltage on GPIO1/11, persist UV state in NVS, enter a minimal
power mode without ESP-NOW, and recover after charge; expose LED mode 6
battery-low for host testing via goTool.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-23 18:22:52 +02:00
co-authored by Cursor
parent be18b758ed
commit f006f8b912
26 changed files with 418 additions and 37 deletions
+31 -7
View File
@@ -2,6 +2,9 @@
#include "powerpod.h"
#include "client_registry.h"
#include "driver/gpio.h"
#if POWERPOD_BATTERY_UV_ENABLE
#include "battery_uv.h"
#endif
#include "esp_adc/adc_oneshot.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
@@ -114,6 +117,10 @@ static void lipo_monitor_task(void *param) {
reading.lipo2_valid ? "ok" : "n/a",
(unsigned long)reading.lipo2_mv);
#if POWERPOD_BATTERY_UV_ENABLE
battery_uv_poll(&reading);
#endif
vTaskDelay(pdMS_TO_TICKS(LIPO_SAMPLE_INTERVAL_MS));
}
}
@@ -184,7 +191,7 @@ static esp_err_t init_button(void) {
return ESP_OK;
}
static esp_err_t init_lipo_adc(void) {
static esp_err_t init_lipo_adc_hw(void) {
memset(&s_lipo1, 0, sizeof(s_lipo1));
memset(&s_lipo2, 0, sizeof(s_lipo2));
@@ -201,6 +208,16 @@ static esp_err_t init_lipo_adc(void) {
return ESP_FAIL;
}
return ESP_OK;
}
esp_err_t board_input_init_adc_only(void) { return init_lipo_adc_hw(); }
esp_err_t board_input_start_lipo_monitor(void) {
if (!s_lipo1.ok && !s_lipo2.ok) {
return ESP_FAIL;
}
if (xTaskCreate(lipo_monitor_task, "lipo_mon", 3072, NULL, 1, NULL) != pdPASS) {
return ESP_ERR_NO_MEM;
}
@@ -208,16 +225,23 @@ static esp_err_t init_lipo_adc(void) {
return ESP_OK;
}
esp_err_t board_input_init_button(void) { return init_button(); }
esp_err_t board_input_init(void) {
esp_err_t err = init_button();
esp_err_t err = board_input_init_adc_only();
if (err != ESP_OK) {
ESP_LOGW(TAG_LIPO, "ADC init failed: %s", esp_err_to_name(err));
} else {
err = board_input_start_lipo_monitor();
if (err != ESP_OK) {
ESP_LOGW(TAG_LIPO, "monitor task failed: %s", esp_err_to_name(err));
}
}
err = board_input_init_button();
if (err != ESP_OK) {
ESP_LOGW(TAG_BTN, "init failed: %s", esp_err_to_name(err));
}
err = init_lipo_adc();
if (err != ESP_OK) {
ESP_LOGW(TAG_LIPO, "init failed: %s", esp_err_to_name(err));
}
return ESP_OK;
}