charge_control: refactoring, bug fixes

- Moved shared state transition checks to separate function
- Improved behaviour when the battery is full
This commit is contained in:
Thomas Kolb 2021-06-18 20:25:53 +02:00
parent d9bc181973
commit 7ca6104e80
2 changed files with 65 additions and 32 deletions

View File

@ -57,13 +57,46 @@ static fxp_t sleep_solar_current;
static fxp_t sleep_solar_excess_voltage; 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(); power_switch_solar_off();
} else if(u_bat <= corridor_low) { } else if(meas->u_bat <= corridor_low) {
power_switch_solar_on(); 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; break;
case CHARGE_INITIAL: case CHARGE_INITIAL:
control_solar_switch(meas->u_bat, u_bat_initial_full, u_bat_initial_low); charge_state = control_solar_charging(
u_bat_initial_full,
// temperature limit u_bat_initial_low,
if(meas->temperature > internal_temperature_limit) { uptime_ms,
charge_state = CHARGE_HIGH_TEMPERATURE; meas,
break; charge_state,
} charge_time_in_state);
// time limit for initial charging // time limit for initial charging
if(charge_time_in_state > INITIAL_CHARGE_HOLD_TIME) { if(charge_time_in_state > INITIAL_CHARGE_HOLD_TIME) {
charge_state = CHARGE_TRANSITION; 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; break;
case CHARGE_TRANSITION: case CHARGE_TRANSITION:
// FIXME: dynamically adjust thresholds // FIXME: dynamically adjust thresholds
control_solar_switch(meas->u_bat, u_bat_float_full, u_bat_float_low); charge_state = control_solar_charging(
u_bat_float_full,
// temperature limit u_bat_float_low,
if(meas->temperature > internal_temperature_limit) { uptime_ms,
charge_state = CHARGE_HIGH_TEMPERATURE; meas,
break; charge_state,
} charge_time_in_state);
// time limit for transition to float charging // time limit for transition to float charging
if(charge_time_in_state > INITIAL_TO_FLOAT_TRANSITION_TIME) { if(charge_time_in_state > INITIAL_TO_FLOAT_TRANSITION_TIME) {
charge_state = CHARGE_FLOAT; charge_state = CHARGE_FLOAT;
break; break;
} }
// low-current limit (go to sleep at night)
if(meas->i_solar < sleep_solar_current) {
charge_state = CHARGE_SLEEP;
break;
}
break; break;
case CHARGE_FLOAT: 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 // temperature limit
if(meas->temperature > internal_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 // calculate charge pump output excess voltage over battery voltage
// and compare to the threshold // and compare to the threshold
if(fxp_sub(meas->u_sw, meas->u_bat) > min_charge_pump_excess_voltage) { if(fxp_sub(meas->u_sw, meas->u_bat) > min_charge_pump_excess_voltage) {
discharge_state = DISCHARGE_VOLTAGE_LOW; discharge_state = DISCHARGE_OK;
} }
break; break;

View File

@ -24,7 +24,13 @@
/* Minimum charge current required before charging is stopped to save power at /* Minimum charge current required before charging is stopped to save power at
* the charge pump (in mA). */ * 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 /* 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 * temperature is exceeded, charging is stopped. The load is kept on. Do not