diff --git a/.claude/settings.local.json b/.claude/settings.local.json index ac9a6bd..2f1d05b 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -8,7 +8,10 @@ "Bash(done)", "Bash(file:*)", "mcp__ide__getDiagnostics", - "Bash(python -m py_compile:*)" + "Bash(python -m py_compile:*)", + "WebSearch", + "WebFetch(domain:docs.waveshare.com)", + "WebFetch(domain:www.waveshare.com)" ] }, "outputStyle": "iseri", diff --git a/components/dashboard_ui/dashboard_ui.c b/components/dashboard_ui/dashboard_ui.c index 0f823bf..5124580 100644 --- a/components/dashboard_ui/dashboard_ui.c +++ b/components/dashboard_ui/dashboard_ui.c @@ -19,6 +19,7 @@ /* Top bar */ static lv_obj_t *lbl_ip; static lv_obj_t *lbl_batt; +static lv_obj_t *lbl_batt_v; static lv_obj_t *bar_batt_top; static lv_obj_t *lbl_ws; @@ -160,6 +161,13 @@ static void create_top_bar(lv_obj_t *parent) lv_obj_align(lbl_ws, LV_ALIGN_LEFT_MID, 140, 0); lv_label_set_text(lbl_ws, "WS:---"); + /* Battery voltage — left of bar */ + lbl_batt_v = lv_label_create(bar_cont); + lv_obj_set_style_text_color(lbl_batt_v, lv_color_white(), 0); + lv_obj_set_style_text_font(lbl_batt_v, &InziuIosevka_Slab_CC_12px, 0); + lv_obj_align(lbl_batt_v, LV_ALIGN_RIGHT_MID, -72, 0); + lv_label_set_text(lbl_batt_v, "-.--V"); + /* Battery bar (24x10) — right */ bar_batt_top = lv_bar_create(bar_cont); lv_obj_set_size(bar_batt_top, 24, 10); @@ -169,6 +177,17 @@ static void create_top_bar(lv_obj_t *parent) lv_obj_add_style(bar_batt_top, &style_bar_batt_bg, LV_PART_MAIN); lv_obj_add_style(bar_batt_top, &style_bar_batt_ind, LV_PART_INDICATOR); + /* Battery positive terminal nub */ + lv_obj_t *batt_nub = lv_obj_create(bar_cont); + lv_obj_set_size(batt_nub, 2, 4); + lv_obj_align(batt_nub, LV_ALIGN_RIGHT_MID, -37, 0); + lv_obj_set_style_bg_color(batt_nub, lv_color_white(), 0); + lv_obj_set_style_bg_opa(batt_nub, LV_OPA_COVER, 0); + lv_obj_set_style_border_width(batt_nub, 0, 0); + lv_obj_set_style_radius(batt_nub, 0, 0); + lv_obj_set_style_pad_all(batt_nub, 0, 0); + lv_obj_clear_flag(batt_nub, LV_OBJ_FLAG_SCROLLABLE); + /* Battery text — right of bar */ lbl_batt = lv_label_create(bar_cont); lv_obj_set_style_text_color(lbl_batt, lv_color_white(), 0); @@ -371,15 +390,19 @@ void dashboard_ui_update_stats(const pi_stats_t *stats) lv_label_set_text(lbl_net, net_buf); } -void dashboard_ui_update_local(float temp, float humidity, uint8_t battery) +void dashboard_ui_update_local(float temp, float humidity, uint8_t battery, bool charging, float voltage) { char buf[32]; snprintf(buf, sizeof(buf), "T: %.1f H: %.0f%%", temp, humidity); lv_label_set_text(lbl_local, buf); + /* Update top bar battery voltage */ + snprintf(buf, sizeof(buf), "%.2fV", voltage); + lv_label_set_text(lbl_batt_v, buf); + /* Update top bar battery text + bar */ - snprintf(buf, sizeof(buf), "%d%%", battery); + snprintf(buf, sizeof(buf), charging ? "%d%%C" : "%d%%", battery); lv_label_set_text(lbl_batt, buf); lv_bar_set_value(bar_batt_top, battery, LV_ANIM_OFF); } diff --git a/components/dashboard_ui/dashboard_ui.h b/components/dashboard_ui/dashboard_ui.h index 22b1fb3..e874686 100644 --- a/components/dashboard_ui/dashboard_ui.h +++ b/components/dashboard_ui/dashboard_ui.h @@ -21,7 +21,7 @@ void dashboard_ui_update_stats(const pi_stats_t *stats); /** * Update local sensor readings. LVGL lock must be held by caller. */ -void dashboard_ui_update_local(float temp, float humidity, uint8_t battery); +void dashboard_ui_update_local(float temp, float humidity, uint8_t battery, bool charging, float voltage); /** * Update clock and date display. LVGL lock must be held by caller. diff --git a/components/port_bsp/adc_bsp.cpp b/components/port_bsp/adc_bsp.cpp index 43c30fe..6e7c2dd 100644 --- a/components/port_bsp/adc_bsp.cpp +++ b/components/port_bsp/adc_bsp.cpp @@ -48,3 +48,7 @@ uint8_t Adc_GetBatteryLevel() { //ESP_LOGW("Battery","Voltage: %.3f V, Level: %.1f %%",vol,level); return (uint8_t)level; } + +bool Adc_IsCharging() { + return Adc_GetBatteryVoltage() > 4.10f; +} diff --git a/components/port_bsp/adc_bsp.h b/components/port_bsp/adc_bsp.h index 6889c3b..2c7c9b2 100644 --- a/components/port_bsp/adc_bsp.h +++ b/components/port_bsp/adc_bsp.h @@ -4,4 +4,5 @@ void Adc_PortInit(); float Adc_GetBatteryVoltage(); -uint8_t Adc_GetBatteryLevel(); \ No newline at end of file +uint8_t Adc_GetBatteryLevel(); +bool Adc_IsCharging(); \ No newline at end of file diff --git a/components/user_app/alert.cpp b/components/user_app/alert.cpp index de2a05b..63b3109 100644 --- a/components/user_app/alert.cpp +++ b/components/user_app/alert.cpp @@ -43,7 +43,7 @@ static const int s_beep_count[ALERT_TYPE_COUNT] = { 0, /* SERVICE_DOWN: triple beep */ /* DISABLED FOR TESTING */ 2, /* HIGH_TEMP: double beep */ 0, /* WS_DISCONNECT: single beep */ /* DISABLED FOR TESTING */ - 1, /* CONNECT_OK: single short beep */ + 0, /* CONNECT_OK: single short beep */ /* DISABLED FOR TESTING */ }; static void generate_tone_buffer(void) diff --git a/components/user_app/user_app.cpp b/components/user_app/user_app.cpp index 4677a7b..3246754 100644 --- a/components/user_app/user_app.cpp +++ b/components/user_app/user_app.cpp @@ -219,10 +219,12 @@ static void sensor_task(void *arg) s_shtc3->Shtc3_ReadTempHumi(&temp, &humidity); s_shtc3->Shtc3_Sleep(); + float batt_v = Adc_GetBatteryVoltage(); uint8_t batt = Adc_GetBatteryLevel(); + bool charging = Adc_IsCharging(); if (Lvgl_lock(100)) { - dashboard_ui_update_local(temp, humidity, batt); + dashboard_ui_update_local(temp, humidity, batt, charging, batt_v); Lvgl_unlock(); } }