88#include <math.h>
99#include "esp_log.h"
1010#include "esp_check.h"
11+ #include "esp_timer.h"
1112#include "adc_battery_estimation.h"
1213
1314static const char * TAG = "adc_battery_estimation" ;
@@ -22,11 +23,16 @@ typedef struct {
2223 size_t battery_points_count ;
2324 adc_battery_charging_detect_cb_t charging_detect_cb ;
2425 void * charging_detect_user_data ;
25- float last_capacity ; /*!< Last calculated battery capacity in percentage */
26- bool is_first_read ; /*!< Flag for first capacity reading */
27- bool last_charging_state ; /*!< Last charging state */
28- float voltage_divider_ratio ; /*!< Voltage divider ratio */
29- float filter_alpha ; /*!< Low-pass filter coefficient (0 < alpha < 1) */
26+ float last_capacity ; /*!< Last calculated battery capacity in percentage */
27+ bool is_first_read ; /*!< Flag for first capacity reading */
28+ bool last_charging_state ; /*!< Last charging state */
29+ float voltage_divider_ratio ; /*!< Voltage divider ratio */
30+ float filter_alpha ; /*!< Low-pass filter coefficient (0 < alpha < 1) */
31+ #if CONFIG_BATTERY_STATE_SOFTWARE_ESTIMATION
32+ uint64_t last_time_ms ; /*!< Last time in milliseconds */
33+ int battery_state_estimation_buffer [CONFIG_SOFTWARE_ESTIMATION_SAMPLE_COUNT ]; /*!< Buffer to store ADC readings */
34+ int battery_state_estimation_index ; /*!< Current index in the buffer */
35+ #endif
3036} adc_battery_estimation_ctx_t ;
3137
3238// Helper function to calculate battery capacity based on voltage
@@ -53,6 +59,32 @@ static float calculate_battery_capacity(float voltage, const battery_point_t *po
5359 }
5460}
5561
62+ // Helper function to analyze battery trend
63+ static bool analyze_battery_trend (const int * buffer , int buffer_size , bool last_charging_state )
64+ {
65+ int increasing_count = 0 ;
66+ int decreasing_count = 0 ;
67+
68+ // Count increasing and decreasing points
69+ for (int i = 1 ; i < buffer_size ; i ++ ) {
70+ if (buffer [i ] > buffer [i - 1 ]) {
71+ increasing_count ++ ;
72+ } else if (buffer [i ] < buffer [i - 1 ]) {
73+ decreasing_count ++ ;
74+ }
75+ }
76+
77+ // Log the analysis results
78+ ESP_LOGD (TAG , "Trend analysis: increasing=%d, decreasing=%d" , increasing_count , decreasing_count );
79+
80+ // If increasing and decreasing counts are equal, keep the last state
81+ if (increasing_count == decreasing_count ) {
82+ return last_charging_state ;
83+ }
84+ // Otherwise, determine by increasing/decreasing trend
85+ return increasing_count > decreasing_count ;
86+ }
87+
5688adc_battery_estimation_handle_t adc_battery_estimation_create (adc_battery_estimation_t * config )
5789{
5890 ESP_RETURN_ON_FALSE (config , NULL , TAG , "Config is NULL" );
@@ -127,6 +159,11 @@ adc_battery_estimation_handle_t adc_battery_estimation_create(adc_battery_estima
127159 ctx -> voltage_divider_ratio = config -> lower_resistor / total_resistance ;
128160 ctx -> filter_alpha = CONFIG_BATTERY_CAPACITY_LPF_COEFFICIENT / 10.0f ;
129161
162+ #if CONFIG_BATTERY_STATE_SOFTWARE_ESTIMATION
163+ ctx -> battery_state_estimation_index = 0 ;
164+ ctx -> last_time_ms = 0 ;
165+ #endif
166+
130167 return (adc_battery_estimation_handle_t ) ctx ;
131168}
132169
@@ -172,11 +209,19 @@ esp_err_t adc_battery_estimation_get_capacity(adc_battery_estimation_handle_t ha
172209
173210 adc_battery_estimation_ctx_t * ctx = (adc_battery_estimation_ctx_t * ) handle ;
174211 bool is_charging = false;
175-
212+ #if CONFIG_BATTERY_STATE_SOFTWARE_ESTIMATION
213+ uint64_t current_time_ms = esp_timer_get_time () / 1000 ;
214+ #endif
176215 // Check charging state if callback is provided
177216 if (ctx -> charging_detect_cb ) {
178217 is_charging = ctx -> charging_detect_cb (ctx -> charging_detect_user_data );
179218 }
219+ #if CONFIG_BATTERY_STATE_SOFTWARE_ESTIMATION
220+ else {
221+ // Use last charging state if no callback is provided
222+ is_charging = ctx -> last_charging_state ;
223+ }
224+ #endif
180225
181226 // Get ADC reading via filtering
182227 int vol [CONFIG_ADC_FILTER_WINDOW_SIZE ] = {0 };
@@ -215,9 +260,33 @@ esp_err_t adc_battery_estimation_get_capacity(adc_battery_estimation_handle_t ha
215260 filtered_result = filtered_vol / filtered_count ;
216261 }
217262
263+ #if CONFIG_BATTERY_STATE_SOFTWARE_ESTIMATION
264+ // Record filtered_result every CONFIG_SOFTWARE_ESTIMATION_SAMPLE_INTERVAL ms
265+ if (current_time_ms - ctx -> last_time_ms >= CONFIG_SOFTWARE_ESTIMATION_SAMPLE_INTERVAL ) {
266+ // Store the new value at current index
267+ ctx -> battery_state_estimation_buffer [ctx -> battery_state_estimation_index ] = filtered_result ;
268+ // Update index, wrap around when reaching the end
269+ ctx -> battery_state_estimation_index = (ctx -> battery_state_estimation_index + 1 ) % CONFIG_SOFTWARE_ESTIMATION_SAMPLE_COUNT ;
270+
271+ // If buffer is full (index is 0), analyze the trend
272+ if (ctx -> battery_state_estimation_index == 0 ) {
273+ bool trend_is_charging = analyze_battery_trend (ctx -> battery_state_estimation_buffer ,
274+ CONFIG_SOFTWARE_ESTIMATION_SAMPLE_COUNT ,
275+ ctx -> last_charging_state );
276+ ESP_LOGD (TAG , "Battery trend analysis: %s" , trend_is_charging ? "Charging" : "Discharging" );
277+
278+ // Update last charging state
279+ ctx -> last_charging_state = trend_is_charging ;
280+ // If no charging detection callback is provided, use trend analysis
281+ if (!ctx -> charging_detect_cb ) {
282+ is_charging = trend_is_charging ;
283+ }
284+ }
285+ ctx -> last_time_ms = current_time_ms ;
286+ }
287+ #endif
218288 // Convert ADC voltage (mV) to battery voltage (V)
219289 float battery_voltage = (float )filtered_result / 1000.0f / ctx -> voltage_divider_ratio ;
220- ESP_LOGD (TAG , "Battery voltage: %.2fV" , battery_voltage );
221290
222291 // Calculate battery capacity based on voltage
223292 float current_capacity = calculate_battery_capacity (battery_voltage , ctx -> battery_points , ctx -> battery_points_count );
@@ -265,8 +334,7 @@ esp_err_t adc_battery_estimation_get_charging_state(adc_battery_estimation_handl
265334 if (ctx -> charging_detect_cb ) {
266335 * is_charging = ctx -> charging_detect_cb (ctx -> charging_detect_user_data );
267336 } else {
268- ESP_LOGE (TAG , "Charging detection callback is not set" );
269- return ESP_ERR_INVALID_STATE ;
337+ * is_charging = ctx -> last_charging_state ;
270338 }
271339
272340 return ESP_OK ;
0 commit comments