From 7ca6104e802044b8297db6eb326b882fa77dcae9 Mon Sep 17 00:00:00 2001 From: Thomas Kolb Date: Fri, 18 Jun 2021 20:25:53 +0200 Subject: [PATCH] charge_control: refactoring, bug fixes - Moved shared state transition checks to separate function - Improved behaviour when the battery is full --- src/charge_control.c | 89 +++++++++++++++++++++++++++++--------------- src/config.h | 8 +++- 2 files changed, 65 insertions(+), 32 deletions(-) diff --git a/src/charge_control.c b/src/charge_control.c index 02473d8..516223a 100644 --- a/src/charge_control.c +++ b/src/charge_control.c @@ -57,13 +57,46 @@ static fxp_t sleep_solar_current; static fxp_t sleep_solar_excess_voltage; -static void control_solar_switch(fxp_t u_bat, fxp_t corridor_high, fxp_t corridor_low) +static enum ChargeState control_solar_charging( + fxp_t corridor_high, + fxp_t corridor_low, + uint64_t uptime_ms, + struct MeasurementResult *meas, + enum ChargeState current_state, + uint64_t time_in_state) { - if(u_bat >= corridor_high) { + static uint64_t last_switch_change_time = 0; + uint64_t solar_switch_onoff_duration = uptime_ms - last_switch_change_time; + + bool last_switch_state = power_switch_solar_status(); + + if(meas->u_bat >= corridor_high) { power_switch_solar_off(); - } else if(u_bat <= corridor_low) { + } else if(meas->u_bat <= corridor_low) { power_switch_solar_on(); } + + bool current_switch_state = power_switch_solar_status(); + + if(last_switch_state != current_switch_state) { // switch changed + last_switch_change_time = uptime_ms; + solar_switch_onoff_duration = 0; + } + + // temperature limit + if(meas->temperature > internal_temperature_limit) { + return CHARGE_HIGH_TEMPERATURE; + } + + // low-current limit (go to sleep at night) + if((time_in_state > SLEEP_STATE_DELAY) + && (current_switch_state == true) + && (solar_switch_onoff_duration > SLEEP_SWITCH_DELAY) + && (meas->i_solar < sleep_solar_current)) { + return CHARGE_SLEEP; + } + + return current_state; } @@ -86,52 +119,46 @@ static void solar_fsm_update(uint64_t uptime_ms, struct MeasurementResult *meas) break; case CHARGE_INITIAL: - control_solar_switch(meas->u_bat, u_bat_initial_full, u_bat_initial_low); - - // temperature limit - if(meas->temperature > internal_temperature_limit) { - charge_state = CHARGE_HIGH_TEMPERATURE; - break; - } + charge_state = control_solar_charging( + u_bat_initial_full, + u_bat_initial_low, + uptime_ms, + meas, + charge_state, + charge_time_in_state); // time limit for initial charging if(charge_time_in_state > INITIAL_CHARGE_HOLD_TIME) { charge_state = CHARGE_TRANSITION; - break; } - // low-current limit (go to sleep at night) - if(meas->i_solar < sleep_solar_current) { - charge_state = CHARGE_SLEEP; - break; - } break; case CHARGE_TRANSITION: // FIXME: dynamically adjust thresholds - control_solar_switch(meas->u_bat, u_bat_float_full, u_bat_float_low); - - // temperature limit - if(meas->temperature > internal_temperature_limit) { - charge_state = CHARGE_HIGH_TEMPERATURE; - break; - } + charge_state = control_solar_charging( + u_bat_float_full, + u_bat_float_low, + uptime_ms, + meas, + charge_state, + charge_time_in_state); // time limit for transition to float charging if(charge_time_in_state > INITIAL_TO_FLOAT_TRANSITION_TIME) { charge_state = CHARGE_FLOAT; break; } - - // low-current limit (go to sleep at night) - if(meas->i_solar < sleep_solar_current) { - charge_state = CHARGE_SLEEP; - break; - } break; case CHARGE_FLOAT: - control_solar_switch(meas->u_bat, u_bat_float_full, u_bat_float_low); + charge_state = control_solar_charging( + u_bat_float_full, + u_bat_float_low, + uptime_ms, + meas, + charge_state, + charge_time_in_state); // temperature limit if(meas->temperature > internal_temperature_limit) { @@ -195,7 +222,7 @@ static void load_fsm_update(uint64_t uptime_ms, struct MeasurementResult *meas) // calculate charge pump output excess voltage over battery voltage // and compare to the threshold if(fxp_sub(meas->u_sw, meas->u_bat) > min_charge_pump_excess_voltage) { - discharge_state = DISCHARGE_VOLTAGE_LOW; + discharge_state = DISCHARGE_OK; } break; diff --git a/src/config.h b/src/config.h index 3a1f477..8ac166b 100644 --- a/src/config.h +++ b/src/config.h @@ -24,7 +24,13 @@ /* Minimum charge current required before charging is stopped to save power at * the charge pump (in mA). */ -#define SLEEP_SOLAR_CURRENT 5 +#define SLEEP_SOLAR_CURRENT 1 + +/* Delay between state change and sleep state check (in ms). */ +#define SLEEP_STATE_DELAY 100 + +/* Delay between charging switch state change and sleep state check(in ms). */ +#define SLEEP_SWITCH_DELAY 1000 /* Maximum allowed microcontroller temperature (in units of 0.1 °C). If this * temperature is exceeded, charging is stopped. The load is kept on. Do not