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:
parent
d9bc181973
commit
7ca6104e80
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue