Use the new flash config module

This commit is contained in:
Thomas Kolb 2022-09-25 17:24:21 +02:00
parent 4ebb231346
commit 481cf6f9f4
6 changed files with 79 additions and 149 deletions

View file

@ -6,7 +6,7 @@
#include "measurement.h"
#include "charge_pump.h"
#include "rs485.h"
#include "config.h"
#include "flash_config.h"
#include "charge_control.h"
@ -92,9 +92,9 @@ static enum ChargeState control_solar_charging(
}
// low-current limit (go to sleep at night)
if((time_in_state > SLEEP_STATE_DELAY)
if((time_in_state > FLASH_CONFIG_SLEEP_STATE_DELAY)
&& (current_switch_state == true)
&& (solar_switch_onoff_duration > SLEEP_SWITCH_DELAY)
&& (solar_switch_onoff_duration > FLASH_CONFIG_SLEEP_SWITCH_DELAY)
&& (meas->avg_i_solar < sleep_solar_current)) {
return CHARGE_SLEEP;
}
@ -152,20 +152,20 @@ static void solar_fsm_update(uint64_t uptime_ms, struct MeasurementResult *meas)
}
// time limit for initial hold charging
if(charge_time_in_state > INITIAL_CHARGE_HOLD_TIME) {
if(charge_time_in_state > FLASH_CONFIG_INITIAL_CHARGE_HOLD_TIME) {
charge_state = CHARGE_TRANSITION;
}
break;
case CHARGE_TRANSITION:
if(charge_time_in_state < INITIAL_TO_FLOAT_TRANSITION_TIME) {
if(charge_time_in_state < FLASH_CONFIG_INITIAL_TO_FLOAT_TRANSITION_TIME) {
// dynamically adjust thresholds
fxp_t u_bat_full =
fxp_add(u_bat_initial_full,
fxp_mult(
fxp_sub(u_bat_float_full, u_bat_initial_full),
fxp_div(charge_time_in_state, INITIAL_TO_FLOAT_TRANSITION_TIME)));
fxp_div(charge_time_in_state, FLASH_CONFIG_INITIAL_TO_FLOAT_TRANSITION_TIME)));
fxp_t u_bat_low = fxp_sub(u_bat_full, u_bat_regulation_corridor);
@ -260,7 +260,7 @@ static void load_fsm_update(uint64_t uptime_ms, struct MeasurementResult *meas)
}
if((meas->i_load > load_current_limit)
&& (discharge_time_in_state > LOAD_CURRENT_INRUSH_TIME)) {
&& (discharge_time_in_state > FLASH_CONFIG_LOAD_CURRENT_INRUSH_TIME)) {
discharge_state = DISCHARGE_OVERCURRENT;
}
@ -277,7 +277,7 @@ static void load_fsm_update(uint64_t uptime_ms, struct MeasurementResult *meas)
// Can only switch on again after a specific amount of time has passed
if((meas->avg_u_bat > u_bat_load_on)
&& (discharge_time_in_state > LOAD_ON_DELAY)) {
&& (discharge_time_in_state > FLASH_CONFIG_LOAD_ON_DELAY)) {
discharge_state = DISCHARGE_OK;
}
break;
@ -307,30 +307,30 @@ void charge_control_init(void)
discharge_state_entered = true;
/* calculate thresholds */
u_bat_regulation_corridor = fxp_div(FXP_FROM_INT(U_BAT_REGULATION_CORRIDOR),
u_bat_regulation_corridor = fxp_div(FXP_FROM_INT(FLASH_CONFIG_U_BAT_REGULATION_CORRIDOR),
FXP_FROM_INT(1000));
u_bat_initial_full = fxp_div(FXP_FROM_INT(U_BAT_INITIAL_FULL), FXP_FROM_INT(1000));
u_bat_initial_full = fxp_div(FXP_FROM_INT(FLASH_CONFIG_U_BAT_INITIAL_FULL), FXP_FROM_INT(1000));
u_bat_initial_low = fxp_sub(u_bat_initial_full, u_bat_regulation_corridor);
u_bat_initial_hold_cancel = fxp_div(FXP_FROM_INT(U_BAT_INITIAL_HOLD_CANCEL), FXP_FROM_INT(1000));
u_bat_initial_hold_cancel = fxp_div(FXP_FROM_INT(FLASH_CONFIG_U_BAT_INITIAL_HOLD_CANCEL), FXP_FROM_INT(1000));
u_bat_float_full = fxp_div(FXP_FROM_INT(U_BAT_FLOAT_FULL), FXP_FROM_INT(1000));
u_bat_float_full = fxp_div(FXP_FROM_INT(FLASH_CONFIG_U_BAT_FLOAT_FULL), FXP_FROM_INT(1000));
u_bat_float_low = fxp_sub(u_bat_float_full, u_bat_regulation_corridor);
min_charge_pump_excess_voltage = fxp_div(FXP_FROM_INT(MIN_CHARGE_PUMP_EXCESS_VOLTAGE),
min_charge_pump_excess_voltage = fxp_div(FXP_FROM_INT(FLASH_CONFIG_MIN_CHARGE_PUMP_EXCESS_VOLTAGE),
FXP_FROM_INT(1000));
u_bat_load_on = fxp_div(FXP_FROM_INT(U_BAT_LOAD_ON), FXP_FROM_INT(1000));
u_bat_load_off = fxp_div(FXP_FROM_INT(U_BAT_LOAD_OFF), FXP_FROM_INT(1000));
u_bat_load_on = fxp_div(FXP_FROM_INT(FLASH_CONFIG_U_BAT_LOAD_ON), FXP_FROM_INT(1000));
u_bat_load_off = fxp_div(FXP_FROM_INT(FLASH_CONFIG_U_BAT_LOAD_OFF), FXP_FROM_INT(1000));
load_current_limit = fxp_div(FXP_FROM_INT(LOAD_CURRENT_LIMIT_MA), FXP_FROM_INT(1000));
load_current_limit = fxp_div(FXP_FROM_INT(FLASH_CONFIG_LOAD_CURRENT_LIMIT_MA), FXP_FROM_INT(1000));
internal_temperature_limit = fxp_div(FXP_FROM_INT(INTERNAL_TEMPERATURE_LIMIT), FXP_FROM_INT(10));
internal_temperature_recovery = fxp_div(FXP_FROM_INT(INTERNAL_TEMPERATURE_RECOVERY), 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));
sleep_solar_current = fxp_div(FXP_FROM_INT(SLEEP_SOLAR_CURRENT), FXP_FROM_INT(1000));
sleep_solar_excess_voltage = fxp_div(FXP_FROM_INT(SLEEP_SOLAR_EXCESS_VOLTAGE), 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));
}

View file

@ -1,98 +0,0 @@
#ifndef CONFIG_H
#define CONFIG_H
/* Thresholds for charging control */
/* Battery regulation corridor width (in mV). */
#define U_BAT_REGULATION_CORRIDOR 100
/* Initial charge battery voltage threshold (in mV). */
#define U_BAT_INITIAL_FULL 28600 // stop charging if battery voltage reaches this threshold
/* Cancel initial charge voltage hold below this battery voltage (in mV). */
#define U_BAT_INITIAL_HOLD_CANCEL 27000
/* Transition to floating voltage levels after this time (in ms). */
#define INITIAL_CHARGE_HOLD_TIME 1800000
/* Duration of the transistion from initial charging to float (in ms). */
#define INITIAL_TO_FLOAT_TRANSITION_TIME 600000
/* Float charge battery voltage threshold (in mV). */
#define U_BAT_FLOAT_FULL 27600 // stop charging if battery voltage reaches this threshold
/* Minimum voltage difference to U_bat that the solar panels must produce
* before charging is resumed after it was switched off (in mV). */
#define SLEEP_SOLAR_EXCESS_VOLTAGE 1000
/* Minimum charge current required before charging is stopped to save power at
* the charge pump (in mA). */
#define SLEEP_SOLAR_CURRENT 1
/* Delay between state change and sleep state check (in ms). */
#define SLEEP_STATE_DELAY 60000
/* 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
* set this too high as the heat has to propagate from the power MOSFETs. */
#define INTERNAL_TEMPERATURE_LIMIT 500
/* Resume operation below this temperature (in units of 0.1 °C). */
#define INTERNAL_TEMPERATURE_RECOVERY 450
/* Thresholds for load control */
/* Voltage above which the load is turned on (in mV). */
#define U_BAT_LOAD_ON 27000
/* Voltage below which the load is turned off (in mV). */
#define U_BAT_LOAD_OFF 24000
/* Current at which the overload protection triggers (in mA). */
#define LOAD_CURRENT_LIMIT_MA 10000
/* Inrush tolerance time (in ms). Overload protection is not enforced for this
* time after load power-on. */
#define LOAD_CURRENT_INRUSH_TIME 10
/* Minimum voltage that the charge pump must produce above U_bat before any
* power FET is switched on (in mV). */
#define MIN_CHARGE_PUMP_EXCESS_VOLTAGE 10000
/* The minimum time the load must be off before it can be switched on again (in ms). */
#define LOAD_ON_DELAY 10000
/* Measurement Averaging:
* Alpha is specified in units of 1/1000. 1000 means that only the latest
* value is relevant, 0 means that the measurement has no influence. The latter
* is useless.
*
* The formula to calculate the next averaged value avg from a measurement meas is:
* avg[k] = meas * (alpha/1000) + avg[k-1] * (1 - alpha/1000)
*
* For overload protection (battery voltage, load current), the latest values
* are always used.
* */
/* Averaging factor for load current. */
#define AVG_ALPHA_I_SOLAR 10
#define AVG_ALPHA_I_LOAD 10
#define AVG_ALPHA_U_BAT 100
#define AVG_ALPHA_U_SW 100
#define AVG_ALPHA_U_SOLAR 100
#define AVG_ALPHA_TEMP 10
/* Generic configuration */
/* Time (in ms) to stay active in idle state before entering deep sleep. */
#define DEEPSLEEP_DELAY 1000
/* Deep sleep duration (in seconds). */
#define DEEPSLEEP_DURATION 10
#endif // CONFIG_H

7
src/flash_config.c Normal file
View file

@ -0,0 +1,7 @@
#include "flash_config.h"
bool flash_config_is_present(void)
{
return (FLASH_CONFIG_CAL_FACTOR_U_BAT != 0xFFFF)
&& (FLASH_CONFIG_U_BAT_REGULATION_CORRIDOR != -1);
}

View file

@ -2,6 +2,7 @@
#define FLASH_CONFIG_H
#include <stdint.h>
#include <stdbool.h>
extern uint8_t __conf_start;
@ -23,13 +24,13 @@ extern uint8_t __conf_start;
/***** General configuration *****/
/* Battery regulation corridor width (in mV). */
#define FLASH_CONFIG_U_BAT_REGULATION_CORRIDOR (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0100))
#define FLASH_CONFIG_U_BAT_REGULATION_CORRIDOR (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x0100))
/* Initial charge battery voltage threshold (in mV). */
#define FLASH_CONFIG_U_BAT_INITIAL_FULL (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0104))
#define FLASH_CONFIG_U_BAT_INITIAL_FULL (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x0104))
/* Cancel initial charge voltage hold below this battery voltage (in mV). */
#define FLASH_CONFIG_U_BAT_INITIAL_HOLD_CANCEL (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0108))
#define FLASH_CONFIG_U_BAT_INITIAL_HOLD_CANCEL (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x0108))
/* Transition to floating voltage levels after this time (in ms). */
#define FLASH_CONFIG_INITIAL_CHARGE_HOLD_TIME (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x010C))
@ -38,15 +39,15 @@ extern uint8_t __conf_start;
#define FLASH_CONFIG_INITIAL_TO_FLOAT_TRANSITION_TIME (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0110))
/* Float charge battery voltage threshold (in mV). */
#define FLASH_CONFIG_U_BAT_FLOAT_FULL (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0114))
#define FLASH_CONFIG_U_BAT_FLOAT_FULL (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x0114))
/* Minimum voltage difference to U_bat that the solar panels must produce
* before charging is resumed after it was switched off (in mV). */
#define FLASH_CONFIG_SLEEP_SOLAR_EXCESS_VOLTAGE (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0118))
#define FLASH_CONFIG_SLEEP_SOLAR_EXCESS_VOLTAGE (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x0118))
/* Minimum charge current required before charging is stopped to save power at
* the charge pump (in mA). */
#define FLASH_CONFIG_SLEEP_SOLAR_CURRENT (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x011C))
#define FLASH_CONFIG_SLEEP_SOLAR_CURRENT (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x011C))
/* Delay between state change and sleep state check (in ms). */
#define FLASH_CONFIG_SLEEP_STATE_DELAY (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0120))
@ -57,21 +58,21 @@ extern uint8_t __conf_start;
/* 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
* set this too high as the heat has to propagate from the power MOSFETs. */
#define FLASH_CONFIG_INTERNAL_TEMPERATURE_LIMIT (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0128))
#define FLASH_CONFIG_INTERNAL_TEMPERATURE_LIMIT (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x0128))
/* Resume operation below this temperature (in units of 0.1 °C). */
#define FLASH_CONFIG_INTERNAL_TEMPERATURE_RECOVERY (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x012C))
#define FLASH_CONFIG_INTERNAL_TEMPERATURE_RECOVERY (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x012C))
/* Thresholds for load control */
/* Voltage above which the load is turned on (in mV). */
#define FLASH_CONFIG_U_BAT_LOAD_ON (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0130))
#define FLASH_CONFIG_U_BAT_LOAD_ON (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x0130))
/* Voltage below which the load is turned off (in mV). */
#define FLASH_CONFIG_U_BAT_LOAD_OFF (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0134))
#define FLASH_CONFIG_U_BAT_LOAD_OFF (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x0134))
/* Current at which the overload protection triggers (in mA). */
#define FLASH_CONFIG_LOAD_CURRENT_LIMIT_MA (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0138))
#define FLASH_CONFIG_LOAD_CURRENT_LIMIT_MA (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x0138))
/* Inrush tolerance time (in ms). Overload protection is not enforced for this
* time after load power-on. */
@ -79,7 +80,7 @@ extern uint8_t __conf_start;
/* Minimum voltage that the charge pump must produce above U_bat before any
* power FET is switched on (in mV). */
#define FLASH_CONFIG_MIN_CHARGE_PUMP_EXCESS_VOLTAGE (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0140))
#define FLASH_CONFIG_MIN_CHARGE_PUMP_EXCESS_VOLTAGE (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x0140))
/* The minimum time the load must be off before it can be switched on again (in ms). */
#define FLASH_CONFIG_LOAD_ON_DELAY (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0144))
@ -98,12 +99,12 @@ extern uint8_t __conf_start;
* */
/* Averaging factor for load current. */
#define FLASH_CONFIG_AVG_ALPHA_I_SOLAR (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0148))
#define FLASH_CONFIG_AVG_ALPHA_I_LOAD (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x014C))
#define FLASH_CONFIG_AVG_ALPHA_U_BAT (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0150))
#define FLASH_CONFIG_AVG_ALPHA_U_SW (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0154))
#define FLASH_CONFIG_AVG_ALPHA_U_SOLAR (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0158))
#define FLASH_CONFIG_AVG_ALPHA_TEMP (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x015C))
#define FLASH_CONFIG_AVG_ALPHA_I_SOLAR (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x0148))
#define FLASH_CONFIG_AVG_ALPHA_I_LOAD (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x014C))
#define FLASH_CONFIG_AVG_ALPHA_U_BAT (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x0150))
#define FLASH_CONFIG_AVG_ALPHA_U_SW (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x0154))
#define FLASH_CONFIG_AVG_ALPHA_U_SOLAR (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x0158))
#define FLASH_CONFIG_AVG_ALPHA_TEMP (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x015C))
/* Generic configuration */
@ -114,4 +115,9 @@ extern uint8_t __conf_start;
/* Deep sleep duration (in seconds). */
#define FLASH_CONFIG_DEEPSLEEP_DURATION (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0164))
/* Functions */
bool flash_config_is_present(void);
#endif // FLASH_CONFIG_H

View file

@ -18,7 +18,7 @@
#include "deepsleep.h"
#include "pinout.h"
#include "config.h"
#include "flash_config.h"
volatile int wait_frame = 1;
@ -36,6 +36,16 @@ static void init_systick(int freq)
}
static void config_err_blink_code(uint64_t timebase_ms)
{
if(timebase_ms % 500 < 250) {
led_chplex_mask(0x3F); // all on
} else {
led_chplex_mask(0x00); // all off
}
}
static bool ledtest(uint64_t timebase_ms)
{
if(timebase_ms == 0) {
@ -260,9 +270,14 @@ int main(void)
ledtest_done = ledtest(timebase_ms);
led_chplex_periodic();
} else if(!startup_done) {
if(flash_config_is_present()) {
charge_pump_start();
startup_done = true;
} else {
config_err_blink_code(timebase_ms);
led_chplex_periodic();
}
} else {
measurement_start();
@ -297,8 +312,8 @@ int main(void)
charge_control_idle_since = timebase_ms;
} else {
// charge control already idle
if((timebase_ms - charge_control_idle_since) > DEEPSLEEP_DELAY) {
low_power_mode(DEEPSLEEP_DURATION);
if((timebase_ms - charge_control_idle_since) > FLASH_CONFIG_DEEPSLEEP_DELAY) {
low_power_mode(FLASH_CONFIG_DEEPSLEEP_DURATION);
charge_control_was_idle = false;
}
}

View file

@ -8,7 +8,7 @@
#include "measurement.h"
#include "calibration.h"
#include "config.h"
#include "flash_config.h"
#define ADC_NUM_CHANNELS 6
static volatile int16_t adc_values[ADC_NUM_CHANNELS];
@ -55,7 +55,7 @@ static fxp_t calc_temperature(uint16_t adc_val)
static fxp_t adc_val_to_pin_voltage(uint16_t adc_val)
{
return fxp_div(
fxp_mult(FXP_FROM_INT(adc_val), fxp_div(FXP_FROM_INT(33), FXP_FROM_INT(10))),
fxp_mult(FXP_FROM_INT((int32_t)adc_val), fxp_div(FXP_FROM_INT(33), FXP_FROM_INT(10))),
FXP_FROM_INT(4096));
}
@ -105,12 +105,12 @@ void measurement_init(void)
fxp_div(FXP_FROM_INT(CAL_FACTOR_I_LOAD), FXP_FROM_INT(1000));
// Convert and precalculate coefficients for exponential averaging
avg_alpha_i_solar = fxp_div(FXP_FROM_INT(AVG_ALPHA_I_SOLAR), FXP_FROM_INT(1000));
avg_alpha_i_load = fxp_div(FXP_FROM_INT(AVG_ALPHA_I_LOAD), FXP_FROM_INT(1000));
avg_alpha_u_bat = fxp_div(FXP_FROM_INT(AVG_ALPHA_U_BAT), FXP_FROM_INT(1000));
avg_alpha_u_sw = fxp_div(FXP_FROM_INT(AVG_ALPHA_U_SW), FXP_FROM_INT(1000));
avg_alpha_u_solar = fxp_div(FXP_FROM_INT(AVG_ALPHA_U_SOLAR), FXP_FROM_INT(1000));
avg_alpha_temp = fxp_div(FXP_FROM_INT(AVG_ALPHA_TEMP), FXP_FROM_INT(1000));
avg_alpha_i_solar = fxp_div(FXP_FROM_INT(FLASH_CONFIG_AVG_ALPHA_I_SOLAR), FXP_FROM_INT(1000));
avg_alpha_i_load = fxp_div(FXP_FROM_INT(FLASH_CONFIG_AVG_ALPHA_I_LOAD), FXP_FROM_INT(1000));
avg_alpha_u_bat = fxp_div(FXP_FROM_INT(FLASH_CONFIG_AVG_ALPHA_U_BAT), FXP_FROM_INT(1000));
avg_alpha_u_sw = fxp_div(FXP_FROM_INT(FLASH_CONFIG_AVG_ALPHA_U_SW), FXP_FROM_INT(1000));
avg_alpha_u_solar = fxp_div(FXP_FROM_INT(FLASH_CONFIG_AVG_ALPHA_U_SOLAR), FXP_FROM_INT(1000));
avg_alpha_temp = fxp_div(FXP_FROM_INT(FLASH_CONFIG_AVG_ALPHA_TEMP), FXP_FROM_INT(1000));
// Inverse (1 - alpha) exponential averaging coefficients
avg_alpha_i_solar_inv = fxp_sub(FXP_FROM_INT(1), avg_alpha_i_solar);