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 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;

View File

@ -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