charge_control: block charging if external temperature is too low

This commit is contained in:
Thomas Kolb 2022-10-15 21:44:27 +02:00
parent d7b8c90cb4
commit 5c6497fb82
2 changed files with 47 additions and 11 deletions

View file

@ -2,6 +2,7 @@
#include <fxp.h> #include <fxp.h>
#include "bmp280.h"
#include "power_switch.h" #include "power_switch.h"
#include "measurement.h" #include "measurement.h"
#include "charge_pump.h" #include "charge_pump.h"
@ -10,17 +11,18 @@
#include "charge_control.h" #include "charge_control.h"
static const char *CHARGE_STATE_TEXT[] = { static const char *CHARGE_STATE_TEXT[CHARGE_NUM_STATES] = {
"WAIT_CHARGEPUMP", "WAIT_CHARGEPUMP",
"INITIAL", "INITIAL",
"INITIAL_HOLD", "INITIAL_HOLD",
"TRANSITION", "TRANSITION",
"FLOAT", "FLOAT",
"SLEEP", "SLEEP",
"HIGH_TEMPERATURE" "HIGH_INTERNAL_TEMPERATURE",
"LOW_EXTERNAL_TEMPERATURE"
}; };
static const char *DISCHARGE_STATE_TEXT[] = { static const char *DISCHARGE_STATE_TEXT[DISCHARGE_NUM_STATES] = {
"WAIT_CHARGEPUMP", "WAIT_CHARGEPUMP",
"OK", "OK",
"VOLTAGE_LOW", "VOLTAGE_LOW",
@ -56,6 +58,9 @@ static fxp_t load_current_limit;
static fxp_t internal_temperature_limit; static fxp_t internal_temperature_limit;
static fxp_t internal_temperature_recovery; static fxp_t internal_temperature_recovery;
static fxp_t external_temperature_limit;
static fxp_t external_temperature_recovery;
static fxp_t sleep_solar_current; static fxp_t sleep_solar_current;
static fxp_t sleep_solar_excess_voltage; static fxp_t sleep_solar_excess_voltage;
@ -86,9 +91,15 @@ static enum ChargeState control_solar_charging(
solar_switch_onoff_duration = 0; solar_switch_onoff_duration = 0;
} }
// temperature limit // internal temperature limit: prevent overheating of the power transistors.
if(meas->avg_temperature > internal_temperature_limit) { if(meas->avg_temperature > internal_temperature_limit) {
return CHARGE_HIGH_TEMPERATURE; return CHARGE_HIGH_INTERNAL_TEMPERATURE;
}
// external temperature limit: prevent charging the battery if temperature is too low.
if(bmp280_are_measurements_valid() &&
bmp280_get_temperature() < external_temperature_limit) {
return CHARGE_LOW_EXTERNAL_TEMPERATURE;
} }
// low-current limit (go to sleep at night) // low-current limit (go to sleep at night)
@ -195,7 +206,7 @@ static void solar_fsm_update(uint64_t uptime_ms, struct MeasurementResult *meas)
// temperature limit // temperature limit
if(meas->temperature > internal_temperature_limit) { if(meas->temperature > internal_temperature_limit) {
charge_state = CHARGE_HIGH_TEMPERATURE; charge_state = CHARGE_HIGH_INTERNAL_TEMPERATURE;
break; break;
} }
break; break;
@ -217,7 +228,7 @@ static void solar_fsm_update(uint64_t uptime_ms, struct MeasurementResult *meas)
break; break;
case CHARGE_HIGH_TEMPERATURE: case CHARGE_HIGH_INTERNAL_TEMPERATURE:
if(charge_state_entered) { if(charge_state_entered) {
power_switch_solar_off(); power_switch_solar_off();
} }
@ -228,6 +239,21 @@ static void solar_fsm_update(uint64_t uptime_ms, struct MeasurementResult *meas)
} }
break; break;
case CHARGE_LOW_EXTERNAL_TEMPERATURE:
if(charge_state_entered) {
power_switch_solar_off();
}
// this state can only be entered if the BMP280 measurement is valid, so
// no need to check it again here.
if(bmp280_get_temperature() > external_temperature_recovery) {
charge_state = CHARGE_WAIT_CHARGEPUMP;
break;
}
break;
default: default:
// unknown state // unknown state
break; break;
@ -329,6 +355,9 @@ void charge_control_init(void)
internal_temperature_limit = fxp_div(FXP_FROM_INT(FLASH_CONFIG_INTERNAL_TEMPERATURE_LIMIT), FXP_FROM_INT(10)); internal_temperature_limit = fxp_div(FXP_FROM_INT(FLASH_CONFIG_INTERNAL_TEMPERATURE_LIMIT), FXP_FROM_INT(10));
internal_temperature_recovery = fxp_div(FXP_FROM_INT(FLASH_CONFIG_INTERNAL_TEMPERATURE_RECOVERY), FXP_FROM_INT(10)); internal_temperature_recovery = fxp_div(FXP_FROM_INT(FLASH_CONFIG_INTERNAL_TEMPERATURE_RECOVERY), FXP_FROM_INT(10));
external_temperature_limit = fxp_div(FXP_FROM_INT(FLASH_CONFIG_EXTERNAL_TEMPERATURE_LIMIT), FXP_FROM_INT(10));
external_temperature_recovery = fxp_div(FXP_FROM_INT(FLASH_CONFIG_EXTERNAL_TEMPERATURE_RECOVERY), FXP_FROM_INT(10));
sleep_solar_current = fxp_div(FXP_FROM_INT(FLASH_CONFIG_SLEEP_SOLAR_CURRENT), FXP_FROM_INT(1000)); sleep_solar_current = fxp_div(FXP_FROM_INT(FLASH_CONFIG_SLEEP_SOLAR_CURRENT), FXP_FROM_INT(1000));
sleep_solar_excess_voltage = fxp_div(FXP_FROM_INT(FLASH_CONFIG_SLEEP_SOLAR_EXCESS_VOLTAGE), FXP_FROM_INT(1000)); sleep_solar_excess_voltage = fxp_div(FXP_FROM_INT(FLASH_CONFIG_SLEEP_SOLAR_EXCESS_VOLTAGE), FXP_FROM_INT(1000));
} }
@ -381,7 +410,8 @@ void charge_control_update(uint64_t uptime_ms, struct MeasurementResult *meas)
bool charge_control_is_idle(void) bool charge_control_is_idle(void)
{ {
return (((charge_state == CHARGE_SLEEP) return (((charge_state == CHARGE_SLEEP)
|| (charge_state == CHARGE_HIGH_TEMPERATURE)) || (charge_state == CHARGE_HIGH_INTERNAL_TEMPERATURE)
|| (charge_state == CHARGE_LOW_EXTERNAL_TEMPERATURE))
&& ((discharge_state == DISCHARGE_VOLTAGE_LOW) && ((discharge_state == DISCHARGE_VOLTAGE_LOW)
|| (discharge_state == DISCHARGE_OVERCURRENT))); || (discharge_state == DISCHARGE_OVERCURRENT)));
} }
@ -390,7 +420,8 @@ bool charge_control_is_idle(void)
bool charge_control_is_charge_blocked(void) bool charge_control_is_charge_blocked(void)
{ {
switch(charge_state) { switch(charge_state) {
case CHARGE_HIGH_TEMPERATURE: case CHARGE_HIGH_INTERNAL_TEMPERATURE:
case CHARGE_LOW_EXTERNAL_TEMPERATURE:
case CHARGE_WAIT_CHARGEPUMP: case CHARGE_WAIT_CHARGEPUMP:
return true; return true;

View file

@ -15,7 +15,10 @@ enum ChargeState
CHARGE_TRANSITION, CHARGE_TRANSITION,
CHARGE_FLOAT, CHARGE_FLOAT,
CHARGE_SLEEP, CHARGE_SLEEP,
CHARGE_HIGH_TEMPERATURE CHARGE_HIGH_INTERNAL_TEMPERATURE,
CHARGE_LOW_EXTERNAL_TEMPERATURE,
CHARGE_NUM_STATES
}; };
enum DischargeState enum DischargeState
@ -23,7 +26,9 @@ enum DischargeState
DISCHARGE_WAIT_CHARGEPUMP, DISCHARGE_WAIT_CHARGEPUMP,
DISCHARGE_OK, DISCHARGE_OK,
DISCHARGE_VOLTAGE_LOW, DISCHARGE_VOLTAGE_LOW,
DISCHARGE_OVERCURRENT DISCHARGE_OVERCURRENT,
DISCHARGE_NUM_STATES
}; };
// Error flags // Error flags