saving and charge indication working

This commit is contained in:
2026-01-19 22:05:35 -06:00
parent 40bea065a7
commit d427859804
9 changed files with 215 additions and 39 deletions

View File

@@ -1,10 +1,11 @@
{
"C_Cpp.intelliSenseEngine": "default",
"idf.projectName": "soundshot",
"idf.espIdfPathWin": "C:\\Users\\Brent.Perteet\\esp\\v5.4.1\\esp-idf",
"idf.openOcdConfigs": [
"board/esp32-wrover-kit-3.3v.cfg"
],
"idf.portWin": "COM14",
"idf.portWin": "COM3",
"idf.toolsPathWin": "C:\\Users\\Brent.Perteet\\.espressif",
"idf.flashType": "UART",
"files.associations": {
@@ -37,7 +38,8 @@
"lv_slider.h": "c",
"lv_menu.h": "c",
"stdint.h": "c",
"random": "c"
"random": "c",
"string.h": "c"
},
"git.ignoreLimitWarning": true,
"idf.pythonInstallPath": "C:\\Users\\Brent.Perteet\\.espressif\\tools\\idf-python\\3.11.2\\python.exe",

View File

@@ -8,5 +8,6 @@ idf_component_register(SRCS "battery.c" "bt_app.c" "system.c" "bubble.c" "keypad
"esp_lvgl_port"
"esp_timer"
"nvs_flash"
"bt")
"bt"
"esp_adc")

View File

@@ -7,6 +7,7 @@
#include "esp_adc/adc_cali_scheme.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
static const char *TAG = "battery";
@@ -177,9 +178,16 @@ int battery_get_percentage(void)
static void battery_monitoring_task(void *pvParameters)
{
ESP_LOGI(TAG, "Battery monitoring task started");
bool led_toggle = false;
int loop_count = 0;
int voltage_mv = 0;
bool is_charging = false;
while (1) {
int voltage_mv = battery_read_voltage_mv();
while (1)
{
// Read voltage every 20 iterations (5000ms)
if (loop_count % 20 == 0) {
voltage_mv = battery_read_voltage_mv();
int percentage = battery_get_percentage();
if (voltage_mv >= 0 && percentage >= 0) {
@@ -192,8 +200,67 @@ static void battery_monitoring_task(void *pvParameters)
ESP_LOGW(TAG, "Failed to read battery voltage");
}
// Read battery every 30 seconds
vTaskDelay(pdMS_TO_TICKS(30000));
// Read charge status and update system
is_charging = !gpio_get_level(PIN_NUM_CHARGE_STATUS);
system_setChargeStatus(is_charging);
}
// LED control based on charging status and voltage (runs every 250ms)
if (is_charging)
{
// Charging: Red until voltage > 4150mV, then Green
if (voltage_mv > 4150) {
gpio_set_level(PIN_LED_GREEN, 1); // Green ON
gpio_set_level(PIN_LED_RED, 0); // Red OFF
} else {
gpio_set_level(PIN_LED_GREEN, 0); // Green OFF
gpio_set_level(PIN_LED_RED, 1); // Red ON
}
gpio_set_level(PIN_NUM_LED_2, 1);
}
else
{
// Not charging: voltage-based indication
if (voltage_mv > 3900)
{
// Good voltage: Green steady
gpio_set_level(PIN_LED_GREEN, 1); // Green ON
gpio_set_level(PIN_LED_RED, 0); // Red OFF
}
else
if (voltage_mv > 3700)
{
// Warning voltage: Green flashing at 2Hz
gpio_set_level(PIN_LED_GREEN, led_toggle ? 0 : 1);
gpio_set_level(PIN_LED_RED, 0); // Red OFF
led_toggle = !led_toggle;
}
else
if (voltage_mv > 3600)
{
// Low voltage: Red steady
gpio_set_level(PIN_LED_GREEN, 0); // Green OFF
gpio_set_level(PIN_LED_RED, 1); // Red ON
}
else
if (voltage_mv > 3500)
{
// Warning voltage: Red flashing at 2Hz
gpio_set_level(PIN_LED_RED, led_toggle ? 0 : 1);
gpio_set_level(PIN_LED_GREEN, 0); // Green OFF
led_toggle = !led_toggle;
}
else
{
// power off
gpio_set_level(PIN_NUM_nON, 0);
}
gpio_set_level(PIN_NUM_LED_2, 1);
}
loop_count++;
vTaskDelay(pdMS_TO_TICKS(250));
}
}

View File

@@ -7,7 +7,7 @@
// Battery monitoring configuration
#define BATTERY_ADC_CHANNEL ADC_CHANNEL_6 // GPIO34 (ADC1_CH6)
#define BATTERY_ADC_ATTEN ADC_ATTEN_DB_12 // Full range ~3.9V (0-3300mV with attenuation)
#define BATTERY_ADC_WIDTH ADC_WIDTH_BIT_12 // 12-bit resolution (0-4095)
#define BATTERY_ADC_WIDTH ADC_BITWIDTH_12 // 12-bit resolution (0-4095)
// Battery voltage calculation constants
// Adjust these based on your voltage divider circuit

View File

@@ -10,6 +10,10 @@
#define PIN_NUM_nON 26
#define PIN_NUM_CHARGE_STATUS 2
#define PIN_LED_RED PIN_NUM_LED_0
#define PIN_LED_GREEN PIN_NUM_LED_1
// Define GPIO pins
#ifdef DEVKIT

View File

@@ -100,6 +100,7 @@ static lv_obj_t *list;
static lv_obj_t *buttons[MAX_ITEMS];
static int selected_index = 0;
static lv_obj_t *_bubble = NULL;
static lv_obj_t *_voltageLabel = NULL;
static lv_obj_t * _menu = NULL;
static lv_obj_t *_currentPage = NULL;
@@ -242,6 +243,9 @@ static void show_menu(void) {
lv_obj_remove_flag(menu, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(_bubble, LV_OBJ_FLAG_HIDDEN);
if (_voltageLabel != NULL) {
lv_obj_add_flag(_voltageLabel, LV_OBJ_FLAG_HIDDEN);
}
}
static void cleanup_menu(void) {
@@ -269,6 +273,9 @@ static void cleanup_menu(void) {
static void show_bubble(void) {
cleanup_menu(); // Free menu memory when returning to bubble
lv_obj_remove_flag(_bubble, LV_OBJ_FLAG_HIDDEN);
if (_voltageLabel != NULL) {
lv_obj_remove_flag(_voltageLabel, LV_OBJ_FLAG_HIDDEN);
}
}
static void create_lvgl_demo(void)
@@ -393,6 +400,23 @@ static void createBubble(lv_obj_t * scr)
// (usually on the next tick, or immediately if LVGL is idle).
_bubble = level;
#if 0
// Create voltage label at the top
_voltageLabel = lv_label_create(scr);
lv_label_set_text(_voltageLabel, "---- mV");
lv_obj_align(_voltageLabel, LV_ALIGN_TOP_MID, 0, 10);
lv_obj_set_style_text_font(_voltageLabel, &lv_font_montserrat_14, 0);
// Add white background for contrast
lv_obj_set_style_bg_color(_voltageLabel, lv_color_hex(0xFFFFFF), 0);
lv_obj_set_style_bg_opa(_voltageLabel, LV_OPA_COVER, 0);
lv_obj_set_style_text_color(_voltageLabel, lv_color_hex(0x000000), 0);
lv_obj_set_style_pad_left(_voltageLabel, 8, 0);
lv_obj_set_style_pad_right(_voltageLabel, 8, 0);
lv_obj_set_style_pad_top(_voltageLabel, 4, 0);
lv_obj_set_style_pad_bottom(_voltageLabel, 4, 0);
lv_obj_set_style_radius(_voltageLabel, 4, 0);
#endif
}
@@ -1289,6 +1313,9 @@ static void show_bt_device_list(void) {
lv_obj_remove_flag(menu, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(_bubble, LV_OBJ_FLAG_HIDDEN);
if (_voltageLabel != NULL) {
lv_obj_add_flag(_voltageLabel, LV_OBJ_FLAG_HIDDEN);
}
@@ -1420,6 +1447,9 @@ static void show_volume_control(void) {
lv_obj_remove_flag(menu, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(_bubble, LV_OBJ_FLAG_HIDDEN);
if (_voltageLabel != NULL) {
lv_obj_add_flag(_voltageLabel, LV_OBJ_FLAG_HIDDEN);
}
ESP_LOGI(TAG, "Volume control displayed");
}
@@ -1685,6 +1715,9 @@ static void show_calibration_menu(void) {
lv_obj_remove_flag(menu, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(_bubble, LV_OBJ_FLAG_HIDDEN);
if (_voltageLabel != NULL) {
lv_obj_add_flag(_voltageLabel, LV_OBJ_FLAG_HIDDEN);
}
ESP_LOGI(TAG, "Calibration menu displayed");
}
@@ -1950,6 +1983,18 @@ static void gui_task(void *pvParameters)
{
ImuData_t d = system_getImuData();
bubble_setValue(_bubble, -d.angle);
#if 0
// Update voltage display
lvgl_port_lock(0);
int voltage_mv = system_getBatteryVoltage();
if (_voltageLabel != NULL) {
char buf[16];
snprintf(buf, sizeof(buf), "%d mV", voltage_mv);
lv_label_set_text(_voltageLabel, buf);
}
lvgl_port_unlock();
#endif
}
}

View File

@@ -328,6 +328,7 @@ void app_main(void)
gpio_set_level(PIN_NUM_LED_2, 1);
battery_start_monitoring_task();
#if 0
keypad_start();
@@ -363,22 +364,7 @@ void app_main(void)
#else
while (1)
{
// Read charge status and update system
bool is_charging = gpio_get_level(PIN_NUM_CHARGE_STATUS);
system_setChargeStatus(is_charging);
if (is_charging)
{
gpio_set_level(PIN_NUM_LED_0, 0);
gpio_set_level(PIN_NUM_LED_1, 1);
gpio_set_level(PIN_NUM_LED_2, 0);
}
else
{
gpio_set_level(PIN_NUM_LED_0, 1);
gpio_set_level(PIN_NUM_LED_1, 0);
gpio_set_level(PIN_NUM_LED_2, 0);
}
system_processNvsRequests();
vTaskDelay(pdMS_TO_TICKS(10));

View File

@@ -5,6 +5,7 @@
#include "esp_timer.h"
#include <string.h>
static SystemState_t _systemState;
static EventGroupHandle_t _systemEvent;
@@ -15,6 +16,7 @@ static const char* NVS_NAMESPACE = "bt_devices";
static const char* NVS_KEY_COUNT = "count";
static const char* NVS_NAMESPACE_SETTINGS = "settings";
static const char* NVS_KEY_VOLUME = "volume";
static const char* NVS_KEY_SWAP_LR = "swap_lr";
static esp_err_t nvs_load_devices_internal(paired_device_t *devices, size_t *count);
static esp_err_t nvs_save_devices_internal(const paired_device_t *devices, size_t count);
@@ -39,6 +41,9 @@ void system_init(void)
// Load saved volume from NVS
system_loadVolume();
// Load saved swap L/R setting from NVS
system_loadSwapLR();
}
int system_getPrimaryAxis(void)
@@ -138,6 +143,9 @@ void system_toggleSwapLR(void)
_systemState.swapLR = !_systemState.swapLR;
ESP_LOGI("system", "Swap L/R toggled: %s", _systemState.swapLR ? "ON" : "OFF");
xSemaphoreGive(_eventManager.mutex);
// Save to NVS
system_saveSwapLR();
}
void system_setZeroAngle(void)
@@ -354,7 +362,7 @@ esp_err_t system_loadVolume(void) {
ret = nvs_open(NVS_NAMESPACE_SETTINGS, NVS_READONLY, &nvs_handle);
if (ret != ESP_OK) {
ESP_LOGI("system", "No saved volume found, using default: %d", volume);
ESP_LOGI("system", "No saved volume found, using default: %ld", volume);
system_setVolume(volume);
return ESP_OK; // Not an error, just means no saved value
}
@@ -363,10 +371,10 @@ esp_err_t system_loadVolume(void) {
nvs_close(nvs_handle);
if (ret == ESP_OK) {
ESP_LOGI("system", "Loaded volume from NVS: %d", volume);
ESP_LOGI("system", "Loaded volume from NVS: %ld", volume);
system_setVolume(volume);
} else if (ret == ESP_ERR_NVS_NOT_FOUND) {
ESP_LOGI("system", "No saved volume found, using default: %d", volume);
ESP_LOGI("system", "No saved volume found, using default: %ld", volume);
system_setVolume(volume);
ret = ESP_OK; // Not an error
} else {
@@ -376,6 +384,67 @@ esp_err_t system_loadVolume(void) {
return ret;
}
esp_err_t system_saveSwapLR(void) {
nvs_handle_t nvs_handle;
esp_err_t ret;
bool swapLR = system_getSwapLR();
ret = nvs_open(NVS_NAMESPACE_SETTINGS, NVS_READWRITE, &nvs_handle);
if (ret != ESP_OK) {
ESP_LOGE("system", "Failed to open NVS namespace for swap L/R write: %s", esp_err_to_name(ret));
return ret;
}
ret = nvs_set_u8(nvs_handle, NVS_KEY_SWAP_LR, swapLR ? 1 : 0);
if (ret != ESP_OK) {
ESP_LOGE("system", "Failed to write swap L/R to NVS: %s", esp_err_to_name(ret));
nvs_close(nvs_handle);
return ret;
}
ret = nvs_commit(nvs_handle);
nvs_close(nvs_handle);
if (ret == ESP_OK) {
ESP_LOGI("system", "Swap L/R %s saved to NVS", swapLR ? "ON" : "OFF");
} else {
ESP_LOGE("system", "Failed to commit swap L/R to NVS: %s", esp_err_to_name(ret));
}
return ret;
}
esp_err_t system_loadSwapLR(void) {
nvs_handle_t nvs_handle;
esp_err_t ret;
uint8_t swapLR_u8 = 0; // Default value (OFF)
ret = nvs_open(NVS_NAMESPACE_SETTINGS, NVS_READONLY, &nvs_handle);
if (ret != ESP_OK) {
ESP_LOGI("system", "No saved swap L/R found, using default: OFF");
system_setSwapLR(false);
return ESP_OK; // Not an error, just means no saved value
}
ret = nvs_get_u8(nvs_handle, NVS_KEY_SWAP_LR, &swapLR_u8);
nvs_close(nvs_handle);
if (ret == ESP_OK) {
bool swapLR = (swapLR_u8 != 0);
ESP_LOGI("system", "Loaded swap L/R from NVS: %s", swapLR ? "ON" : "OFF");
system_setSwapLR(swapLR);
} else if (ret == ESP_ERR_NVS_NOT_FOUND) {
ESP_LOGI("system", "No saved swap L/R found, using default: OFF");
system_setSwapLR(false);
ret = ESP_OK; // Not an error
} else {
ESP_LOGE("system", "Failed to read swap L/R from NVS: %s", esp_err_to_name(ret));
}
return ret;
}
void system_initNvsService(void) {
_nvsRequestQueue = xQueueCreate(10, sizeof(nvs_request_t));
if (_nvsRequestQueue == NULL) {

View File

@@ -108,6 +108,8 @@ int system_getBatteryPercentage(void);
void system_setSwapLR(bool swap);
bool system_getSwapLR(void);
void system_toggleSwapLR(void);
esp_err_t system_saveSwapLR(void);
esp_err_t system_loadSwapLR(void);
void system_setZeroAngle(void);
void system_clearZeroAngle(void);