From 5c6497fb82a5a45cb8f4ecabc094081e259ae6d6 Mon Sep 17 00:00:00 2001 From: Thomas Kolb Date: Sat, 15 Oct 2022 21:44:27 +0200 Subject: [PATCH] charge_control: block charging if external temperature is too low --- src/charge_control.c | 49 ++++++++++++++++++++++++++++++++++++-------- src/charge_control.h | 9 ++++++-- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/src/charge_control.c b/src/charge_control.c index 3b8a13a..e1898e8 100644 --- a/src/charge_control.c +++ b/src/charge_control.c @@ -2,6 +2,7 @@ #include +#include "bmp280.h" #include "power_switch.h" #include "measurement.h" #include "charge_pump.h" @@ -10,17 +11,18 @@ #include "charge_control.h" -static const char *CHARGE_STATE_TEXT[] = { +static const char *CHARGE_STATE_TEXT[CHARGE_NUM_STATES] = { "WAIT_CHARGEPUMP", "INITIAL", "INITIAL_HOLD", "TRANSITION", "FLOAT", "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", "OK", "VOLTAGE_LOW", @@ -56,6 +58,9 @@ static fxp_t load_current_limit; static fxp_t internal_temperature_limit; 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_excess_voltage; @@ -86,9 +91,15 @@ static enum ChargeState control_solar_charging( solar_switch_onoff_duration = 0; } - // temperature limit + // internal temperature limit: prevent overheating of the power transistors. 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) @@ -195,7 +206,7 @@ static void solar_fsm_update(uint64_t uptime_ms, struct MeasurementResult *meas) // temperature limit if(meas->temperature > internal_temperature_limit) { - charge_state = CHARGE_HIGH_TEMPERATURE; + charge_state = CHARGE_HIGH_INTERNAL_TEMPERATURE; break; } break; @@ -217,7 +228,7 @@ static void solar_fsm_update(uint64_t uptime_ms, struct MeasurementResult *meas) break; - case CHARGE_HIGH_TEMPERATURE: + case CHARGE_HIGH_INTERNAL_TEMPERATURE: if(charge_state_entered) { power_switch_solar_off(); } @@ -228,6 +239,21 @@ static void solar_fsm_update(uint64_t uptime_ms, struct MeasurementResult *meas) } 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: // unknown state 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_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_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) { 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_OVERCURRENT))); } @@ -390,7 +420,8 @@ bool charge_control_is_idle(void) bool charge_control_is_charge_blocked(void) { switch(charge_state) { - case CHARGE_HIGH_TEMPERATURE: + case CHARGE_HIGH_INTERNAL_TEMPERATURE: + case CHARGE_LOW_EXTERNAL_TEMPERATURE: case CHARGE_WAIT_CHARGEPUMP: return true; diff --git a/src/charge_control.h b/src/charge_control.h index ecb26bb..003b553 100644 --- a/src/charge_control.h +++ b/src/charge_control.h @@ -15,7 +15,10 @@ enum ChargeState CHARGE_TRANSITION, CHARGE_FLOAT, CHARGE_SLEEP, - CHARGE_HIGH_TEMPERATURE + CHARGE_HIGH_INTERNAL_TEMPERATURE, + CHARGE_LOW_EXTERNAL_TEMPERATURE, + + CHARGE_NUM_STATES }; enum DischargeState @@ -23,7 +26,9 @@ enum DischargeState DISCHARGE_WAIT_CHARGEPUMP, DISCHARGE_OK, DISCHARGE_VOLTAGE_LOW, - DISCHARGE_OVERCURRENT + DISCHARGE_OVERCURRENT, + + DISCHARGE_NUM_STATES }; // Error flags