Merge branch 'main' into bmp280
This commit is contained in:
commit
055186180f
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -4,3 +4,6 @@
|
||||||
|
|
||||||
# Vim swap files
|
# Vim swap files
|
||||||
.*.sw?
|
.*.sw?
|
||||||
|
|
||||||
|
# generated config HEX files
|
||||||
|
utils/*.hex
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -32,7 +32,7 @@ LDFLAGS+=--static \
|
||||||
-nostartfiles -Wl,--gc-sections \
|
-nostartfiles -Wl,--gc-sections \
|
||||||
-mthumb -mcpu=cortex-m0 -mthumb -mfloat-abi=soft
|
-mthumb -mcpu=cortex-m0 -mthumb -mfloat-abi=soft
|
||||||
|
|
||||||
# the LD script
|
# the LD script (RAM-only does not work because the code is too large)
|
||||||
#LDFLAGS+=-Tldscripts/lnsc-2420-$(BUILD).ld
|
#LDFLAGS+=-Tldscripts/lnsc-2420-$(BUILD).ld
|
||||||
LDFLAGS+=-Tldscripts/lnsc-2420-release.ld
|
LDFLAGS+=-Tldscripts/lnsc-2420-release.ld
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
/*rom (rx) : ORIGIN = 0x08000000, LENGTH = 64K*/
|
/*rom (rx) : ORIGIN = 0x08000000, LENGTH = 64K*/
|
||||||
|
conf (r) : ORIGIN = 0x08007c00, LENGTH = 1K
|
||||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 4K
|
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 4K
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +97,10 @@ SECTIONS
|
||||||
|
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
end = .;
|
end = .;
|
||||||
|
|
||||||
|
.conf : {
|
||||||
|
__conf_start = .;
|
||||||
|
} >conf
|
||||||
}
|
}
|
||||||
|
|
||||||
PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));
|
PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));
|
||||||
|
|
|
@ -3,10 +3,18 @@
|
||||||
/* Define memory regions. */
|
/* Define memory regions. */
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 32K
|
rom (rx) : ORIGIN = 0x08000000, LENGTH = 31K
|
||||||
|
conf (r) : ORIGIN = 0x08007c00, LENGTH = 1K
|
||||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 4K
|
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 4K
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Include the common ld script. */
|
/* Include the common ld script. */
|
||||||
INCLUDE cortex-m-generic.ld
|
INCLUDE cortex-m-generic.ld
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
.conf : {
|
||||||
|
__conf_start = .;
|
||||||
|
. = ALIGN(4);
|
||||||
|
} >conf
|
||||||
|
}
|
||||||
|
|
|
@ -6,10 +6,24 @@
|
||||||
* than the actual voltage, you have to scale by 1.02 and therefore specify
|
* than the actual voltage, you have to scale by 1.02 and therefore specify
|
||||||
* 1020 in this list. */
|
* 1020 in this list. */
|
||||||
|
|
||||||
|
/* Values for the device at the B26 tower */
|
||||||
|
|
||||||
|
#if 0
|
||||||
#define CAL_FACTOR_U_BAT 994
|
#define CAL_FACTOR_U_BAT 994
|
||||||
#define CAL_FACTOR_U_SOLAR 997
|
#define CAL_FACTOR_U_SOLAR 997
|
||||||
#define CAL_FACTOR_U_SW 996
|
#define CAL_FACTOR_U_SW 996
|
||||||
#define CAL_FACTOR_I_SOLAR 1015
|
#define CAL_FACTOR_I_SOLAR 1015
|
||||||
#define CAL_FACTOR_I_LOAD 1000
|
#define CAL_FACTOR_I_LOAD 1000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Values for the development device */
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
#define CAL_FACTOR_U_BAT 1012
|
||||||
|
#define CAL_FACTOR_U_SOLAR 1015
|
||||||
|
#define CAL_FACTOR_U_SW 1006
|
||||||
|
#define CAL_FACTOR_I_SOLAR 3980
|
||||||
|
#define CAL_FACTOR_I_LOAD 1000
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // CALIBRATION_H
|
#endif // CALIBRATION_H
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include "measurement.h"
|
#include "measurement.h"
|
||||||
#include "charge_pump.h"
|
#include "charge_pump.h"
|
||||||
#include "rs485.h"
|
#include "rs485.h"
|
||||||
#include "config.h"
|
#include "flash_config.h"
|
||||||
|
|
||||||
#include "charge_control.h"
|
#include "charge_control.h"
|
||||||
|
|
||||||
|
@ -92,9 +92,9 @@ static enum ChargeState control_solar_charging(
|
||||||
}
|
}
|
||||||
|
|
||||||
// low-current limit (go to sleep at night)
|
// 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)
|
&& (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)) {
|
&& (meas->avg_i_solar < sleep_solar_current)) {
|
||||||
return CHARGE_SLEEP;
|
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
|
// 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;
|
charge_state = CHARGE_TRANSITION;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CHARGE_TRANSITION:
|
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
|
// dynamically adjust thresholds
|
||||||
fxp_t u_bat_full =
|
fxp_t u_bat_full =
|
||||||
fxp_add(u_bat_initial_full,
|
fxp_add(u_bat_initial_full,
|
||||||
fxp_mult(
|
fxp_mult(
|
||||||
fxp_sub(u_bat_float_full, u_bat_initial_full),
|
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);
|
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)
|
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;
|
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
|
// Can only switch on again after a specific amount of time has passed
|
||||||
if((meas->avg_u_bat > u_bat_load_on)
|
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;
|
discharge_state = DISCHARGE_OK;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -307,30 +307,30 @@ void charge_control_init(void)
|
||||||
discharge_state_entered = true;
|
discharge_state_entered = true;
|
||||||
|
|
||||||
/* calculate thresholds */
|
/* 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));
|
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_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);
|
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));
|
FXP_FROM_INT(1000));
|
||||||
|
|
||||||
u_bat_load_on = fxp_div(FXP_FROM_INT(U_BAT_LOAD_ON), 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(U_BAT_LOAD_OFF), 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_limit = fxp_div(FXP_FROM_INT(FLASH_CONFIG_INTERNAL_TEMPERATURE_LIMIT), FXP_FROM_INT(10));
|
||||||
internal_temperature_recovery = fxp_div(FXP_FROM_INT(INTERNAL_TEMPERATURE_RECOVERY), 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_current = fxp_div(FXP_FROM_INT(FLASH_CONFIG_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_excess_voltage = fxp_div(FXP_FROM_INT(FLASH_CONFIG_SLEEP_SOLAR_EXCESS_VOLTAGE), FXP_FROM_INT(1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
98
src/config.h
98
src/config.h
|
@ -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 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
|
|
||||||
* 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
7
src/flash_config.c
Normal 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);
|
||||||
|
}
|
123
src/flash_config.h
Normal file
123
src/flash_config.h
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
#ifndef FLASH_CONFIG_H
|
||||||
|
#define FLASH_CONFIG_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
extern uint8_t __conf_start;
|
||||||
|
|
||||||
|
#define FLASH_CONFIG_BASE_PTR ((uint8_t*)(&__conf_start))
|
||||||
|
|
||||||
|
/***** Calibration factors *****/
|
||||||
|
|
||||||
|
/* Calibration factor defined here are divided by 1000 to determine the actual
|
||||||
|
* scaling factor. Therefore, if the voltage determined by the firmware is 2%
|
||||||
|
* lower than the actual voltage, you have to scale by 1.02 and therefore
|
||||||
|
* specify 1020 in this list. */
|
||||||
|
|
||||||
|
#define FLASH_CONFIG_CAL_FACTOR_U_BAT (*(uint16_t*)(FLASH_CONFIG_BASE_PTR + 0x0000))
|
||||||
|
#define FLASH_CONFIG_CAL_FACTOR_U_SOLAR (*(uint16_t*)(FLASH_CONFIG_BASE_PTR + 0x0002))
|
||||||
|
#define FLASH_CONFIG_CAL_FACTOR_U_SW (*(uint16_t*)(FLASH_CONFIG_BASE_PTR + 0x0004))
|
||||||
|
#define FLASH_CONFIG_CAL_FACTOR_I_SOLAR (*(uint16_t*)(FLASH_CONFIG_BASE_PTR + 0x0006))
|
||||||
|
#define FLASH_CONFIG_CAL_FACTOR_I_LOAD (*(uint16_t*)(FLASH_CONFIG_BASE_PTR + 0x0008))
|
||||||
|
|
||||||
|
/***** General configuration *****/
|
||||||
|
|
||||||
|
/* Battery regulation corridor width (in mV). */
|
||||||
|
#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 (*(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 (*(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))
|
||||||
|
|
||||||
|
/* Duration of the transistion from initial charging to float (in ms). */
|
||||||
|
#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 (*(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 (*(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 (*(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))
|
||||||
|
|
||||||
|
/* Delay between charging switch state change and sleep state check(in ms). */
|
||||||
|
#define FLASH_CONFIG_SLEEP_SWITCH_DELAY (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0124))
|
||||||
|
|
||||||
|
/* 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 (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x0128))
|
||||||
|
|
||||||
|
/* Resume operation below this temperature (in units of 0.1 °C). */
|
||||||
|
#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 (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x0130))
|
||||||
|
/* Voltage below which the load is turned off (in mV). */
|
||||||
|
#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 (*(int32_t*)(FLASH_CONFIG_BASE_PTR + 0x0138))
|
||||||
|
|
||||||
|
/* Inrush tolerance time (in ms). Overload protection is not enforced for this
|
||||||
|
* time after load power-on. */
|
||||||
|
#define FLASH_CONFIG_LOAD_CURRENT_INRUSH_TIME (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x013C))
|
||||||
|
|
||||||
|
/* 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 (*(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))
|
||||||
|
|
||||||
|
|
||||||
|
/* 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 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 */
|
||||||
|
|
||||||
|
/* Time (in ms) to stay active in idle state before entering deep sleep. */
|
||||||
|
#define FLASH_CONFIG_DEEPSLEEP_DELAY (*(uint32_t*)(FLASH_CONFIG_BASE_PTR + 0x0160))
|
||||||
|
|
||||||
|
/* 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
|
21
src/main.c
21
src/main.c
|
@ -19,7 +19,7 @@
|
||||||
#include "bmp280.h"
|
#include "bmp280.h"
|
||||||
|
|
||||||
#include "pinout.h"
|
#include "pinout.h"
|
||||||
#include "config.h"
|
#include "flash_config.h"
|
||||||
|
|
||||||
volatile int wait_frame = 1;
|
volatile int wait_frame = 1;
|
||||||
|
|
||||||
|
@ -43,6 +43,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)
|
static bool ledtest(uint64_t timebase_ms)
|
||||||
{
|
{
|
||||||
if(timebase_ms == 0) {
|
if(timebase_ms == 0) {
|
||||||
|
@ -326,9 +336,14 @@ int main(void)
|
||||||
ledtest_done = ledtest(timebase_ms);
|
ledtest_done = ledtest(timebase_ms);
|
||||||
led_chplex_periodic();
|
led_chplex_periodic();
|
||||||
} else if(!startup_done) {
|
} else if(!startup_done) {
|
||||||
|
if(flash_config_is_present()) {
|
||||||
charge_pump_start();
|
charge_pump_start();
|
||||||
|
|
||||||
startup_done = true;
|
startup_done = true;
|
||||||
|
} else {
|
||||||
|
config_err_blink_code(timebase_ms);
|
||||||
|
led_chplex_periodic();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
measurement_start();
|
measurement_start();
|
||||||
|
|
||||||
|
@ -366,8 +381,8 @@ int main(void)
|
||||||
charge_control_idle_since = timebase_ms;
|
charge_control_idle_since = timebase_ms;
|
||||||
} else {
|
} else {
|
||||||
// charge control already idle
|
// charge control already idle
|
||||||
if((timebase_ms - charge_control_idle_since) > DEEPSLEEP_DELAY) {
|
if((timebase_ms - charge_control_idle_since) > FLASH_CONFIG_DEEPSLEEP_DELAY) {
|
||||||
low_power_mode(DEEPSLEEP_DURATION);
|
low_power_mode(FLASH_CONFIG_DEEPSLEEP_DURATION);
|
||||||
charge_control_was_idle = false;
|
charge_control_was_idle = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
#include "measurement.h"
|
#include "measurement.h"
|
||||||
#include "calibration.h"
|
#include "calibration.h"
|
||||||
#include "config.h"
|
#include "flash_config.h"
|
||||||
|
|
||||||
#define ADC_NUM_CHANNELS 6
|
#define ADC_NUM_CHANNELS 6
|
||||||
static volatile int16_t adc_values[ADC_NUM_CHANNELS];
|
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)
|
static fxp_t adc_val_to_pin_voltage(uint16_t adc_val)
|
||||||
{
|
{
|
||||||
return fxp_div(
|
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));
|
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));
|
fxp_div(FXP_FROM_INT(CAL_FACTOR_I_LOAD), FXP_FROM_INT(1000));
|
||||||
|
|
||||||
// Convert and precalculate coefficients for exponential averaging
|
// 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_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(AVG_ALPHA_I_LOAD), 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(AVG_ALPHA_U_BAT), 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(AVG_ALPHA_U_SW), 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(AVG_ALPHA_U_SOLAR), 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(AVG_ALPHA_TEMP), 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
|
// Inverse (1 - alpha) exponential averaging coefficients
|
||||||
avg_alpha_i_solar_inv = fxp_sub(FXP_FROM_INT(1), avg_alpha_i_solar);
|
avg_alpha_i_solar_inv = fxp_sub(FXP_FROM_INT(1), avg_alpha_i_solar);
|
||||||
|
|
108
utils/config_b26.yaml
Normal file
108
utils/config_b26.yaml
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
# Values for the device at the B26 tower
|
||||||
|
|
||||||
|
calibration:
|
||||||
|
# Calibration factor defined here are divided by 1000 to determine the actual
|
||||||
|
# scaling factor. Therefore, if the voltage determined by the firmware is 2%
|
||||||
|
# lower than the actual voltage, you have to scale by 1.02 and therefore
|
||||||
|
# specify 1020 in this list.
|
||||||
|
CAL_FACTOR_U_BAT: 994
|
||||||
|
CAL_FACTOR_U_SOLAR: 997
|
||||||
|
CAL_FACTOR_U_SW: 996
|
||||||
|
CAL_FACTOR_I_SOLAR: 1015
|
||||||
|
CAL_FACTOR_I_LOAD: 1000
|
||||||
|
|
||||||
|
config:
|
||||||
|
# Thresholds for charging control
|
||||||
|
|
||||||
|
# Battery regulation corridor width (in mV).
|
||||||
|
U_BAT_REGULATION_CORRIDOR: 100
|
||||||
|
|
||||||
|
# Initial charge battery voltage threshold (in mV).
|
||||||
|
# stop charging if battery voltage reaches this threshold
|
||||||
|
U_BAT_INITIAL_FULL: 28600
|
||||||
|
|
||||||
|
# Cancel initial charge voltage hold below this battery voltage (in mV).
|
||||||
|
U_BAT_INITIAL_HOLD_CANCEL: 27000
|
||||||
|
|
||||||
|
# Transition to floating voltage levels after this time (in ms).
|
||||||
|
INITIAL_CHARGE_HOLD_TIME: 1800000
|
||||||
|
|
||||||
|
# Duration of the transistion from initial charging to float (in ms).
|
||||||
|
INITIAL_TO_FLOAT_TRANSITION_TIME: 600000
|
||||||
|
|
||||||
|
# Float charge battery voltage threshold (in mV).
|
||||||
|
# stop charging if battery voltage reaches this threshold
|
||||||
|
U_BAT_FLOAT_FULL: 27600
|
||||||
|
|
||||||
|
# Minimum voltage difference to U_bat that the solar panels must produce
|
||||||
|
# before charging is resumed after it was switched off (in mV).
|
||||||
|
SLEEP_SOLAR_EXCESS_VOLTAGE: 1000
|
||||||
|
|
||||||
|
# Minimum charge current required before charging is stopped to save power at
|
||||||
|
# the charge pump (in mA).
|
||||||
|
SLEEP_SOLAR_CURRENT: 1
|
||||||
|
|
||||||
|
# Delay between state change and sleep state check (in ms).
|
||||||
|
SLEEP_STATE_DELAY: 60000
|
||||||
|
|
||||||
|
# Delay between charging switch state change and sleep state check(in ms).
|
||||||
|
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.
|
||||||
|
INTERNAL_TEMPERATURE_LIMIT: 500
|
||||||
|
|
||||||
|
# Resume operation below this temperature (in units of 0.1 °C).
|
||||||
|
INTERNAL_TEMPERATURE_RECOVERY: 450
|
||||||
|
|
||||||
|
|
||||||
|
# Thresholds for load control
|
||||||
|
|
||||||
|
# Voltage above which the load is turned on (in mV).
|
||||||
|
U_BAT_LOAD_ON: 27000
|
||||||
|
# Voltage below which the load is turned off (in mV).
|
||||||
|
U_BAT_LOAD_OFF: 24000
|
||||||
|
|
||||||
|
# Current at which the overload protection triggers (in mA).
|
||||||
|
LOAD_CURRENT_LIMIT_MA: 10000
|
||||||
|
|
||||||
|
# Inrush tolerance time (in ms). Overload protection is not enforced for this
|
||||||
|
# time after load power-on.
|
||||||
|
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).
|
||||||
|
MIN_CHARGE_PUMP_EXCESS_VOLTAGE: 10000
|
||||||
|
|
||||||
|
# The minimum time the load must be off before it can be switched on again (in ms).
|
||||||
|
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.
|
||||||
|
AVG_ALPHA_I_SOLAR: 10
|
||||||
|
AVG_ALPHA_I_LOAD: 10
|
||||||
|
AVG_ALPHA_U_BAT: 100
|
||||||
|
AVG_ALPHA_U_SW: 100
|
||||||
|
AVG_ALPHA_U_SOLAR: 100
|
||||||
|
AVG_ALPHA_TEMP: 10
|
||||||
|
|
||||||
|
|
||||||
|
# Generic configuration
|
||||||
|
|
||||||
|
# Time (in ms) to stay active in idle state before entering deep sleep.
|
||||||
|
DEEPSLEEP_DELAY: 1000
|
||||||
|
|
||||||
|
# Deep sleep duration (in seconds).
|
||||||
|
DEEPSLEEP_DURATION: 10
|
108
utils/config_dev.yaml
Normal file
108
utils/config_dev.yaml
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
# Values for the development device
|
||||||
|
|
||||||
|
calibration:
|
||||||
|
# Calibration factor defined here are divided by 1000 to determine the actual
|
||||||
|
# scaling factor. Therefore, if the voltage determined by the firmware is 2%
|
||||||
|
# lower than the actual voltage, you have to scale by 1.02 and therefore
|
||||||
|
# specify 1020 in this list.
|
||||||
|
CAL_FACTOR_U_BAT: 1012
|
||||||
|
CAL_FACTOR_U_SOLAR: 1015
|
||||||
|
CAL_FACTOR_U_SW: 1006
|
||||||
|
CAL_FACTOR_I_SOLAR: 3980
|
||||||
|
CAL_FACTOR_I_LOAD: 1000
|
||||||
|
|
||||||
|
config:
|
||||||
|
# Thresholds for charging control
|
||||||
|
|
||||||
|
# Battery regulation corridor width (in mV).
|
||||||
|
U_BAT_REGULATION_CORRIDOR: 100
|
||||||
|
|
||||||
|
# Initial charge battery voltage threshold (in mV).
|
||||||
|
# stop charging if battery voltage reaches this threshold
|
||||||
|
U_BAT_INITIAL_FULL: 28600
|
||||||
|
|
||||||
|
# Cancel initial charge voltage hold below this battery voltage (in mV).
|
||||||
|
U_BAT_INITIAL_HOLD_CANCEL: 27000
|
||||||
|
|
||||||
|
# Transition to floating voltage levels after this time (in ms).
|
||||||
|
INITIAL_CHARGE_HOLD_TIME: 1800000
|
||||||
|
|
||||||
|
# Duration of the transistion from initial charging to float (in ms).
|
||||||
|
INITIAL_TO_FLOAT_TRANSITION_TIME: 600000
|
||||||
|
|
||||||
|
# Float charge battery voltage threshold (in mV).
|
||||||
|
# stop charging if battery voltage reaches this threshold
|
||||||
|
U_BAT_FLOAT_FULL: 27600
|
||||||
|
|
||||||
|
# Minimum voltage difference to U_bat that the solar panels must produce
|
||||||
|
# before charging is resumed after it was switched off (in mV).
|
||||||
|
SLEEP_SOLAR_EXCESS_VOLTAGE: 1000
|
||||||
|
|
||||||
|
# Minimum charge current required before charging is stopped to save power at
|
||||||
|
# the charge pump (in mA).
|
||||||
|
SLEEP_SOLAR_CURRENT: 1
|
||||||
|
|
||||||
|
# Delay between state change and sleep state check (in ms).
|
||||||
|
SLEEP_STATE_DELAY: 60000
|
||||||
|
|
||||||
|
# Delay between charging switch state change and sleep state check(in ms).
|
||||||
|
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.
|
||||||
|
INTERNAL_TEMPERATURE_LIMIT: 500
|
||||||
|
|
||||||
|
# Resume operation below this temperature (in units of 0.1 °C).
|
||||||
|
INTERNAL_TEMPERATURE_RECOVERY: 450
|
||||||
|
|
||||||
|
|
||||||
|
# Thresholds for load control
|
||||||
|
|
||||||
|
# Voltage above which the load is turned on (in mV).
|
||||||
|
U_BAT_LOAD_ON: 27000
|
||||||
|
# Voltage below which the load is turned off (in mV).
|
||||||
|
U_BAT_LOAD_OFF: 24000
|
||||||
|
|
||||||
|
# Current at which the overload protection triggers (in mA).
|
||||||
|
LOAD_CURRENT_LIMIT_MA: 10000
|
||||||
|
|
||||||
|
# Inrush tolerance time (in ms). Overload protection is not enforced for this
|
||||||
|
# time after load power-on.
|
||||||
|
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).
|
||||||
|
MIN_CHARGE_PUMP_EXCESS_VOLTAGE: 10000
|
||||||
|
|
||||||
|
# The minimum time the load must be off before it can be switched on again (in ms).
|
||||||
|
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.
|
||||||
|
AVG_ALPHA_I_SOLAR: 10
|
||||||
|
AVG_ALPHA_I_LOAD: 10
|
||||||
|
AVG_ALPHA_U_BAT: 100
|
||||||
|
AVG_ALPHA_U_SW: 100
|
||||||
|
AVG_ALPHA_U_SOLAR: 100
|
||||||
|
AVG_ALPHA_TEMP: 10
|
||||||
|
|
||||||
|
|
||||||
|
# Generic configuration
|
||||||
|
|
||||||
|
# Time (in ms) to stay active in idle state before entering deep sleep.
|
||||||
|
DEEPSLEEP_DELAY: 1000
|
||||||
|
|
||||||
|
# Deep sleep duration (in seconds).
|
||||||
|
DEEPSLEEP_DURATION: 10
|
69
utils/config_to_hex.py
Executable file
69
utils/config_to_hex.py
Executable file
|
@ -0,0 +1,69 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import struct
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
from intelhex import IntelHex
|
||||||
|
|
||||||
|
BASE_ADDR = 0x08007C00
|
||||||
|
|
||||||
|
CALIBRATION_KEY_TO_OFFSET = {
|
||||||
|
"CAL_FACTOR_U_BAT": 0x0000,
|
||||||
|
"CAL_FACTOR_U_SOLAR": 0x0002,
|
||||||
|
"CAL_FACTOR_U_SW": 0x0004,
|
||||||
|
"CAL_FACTOR_I_SOLAR": 0x0006,
|
||||||
|
"CAL_FACTOR_I_LOAD": 0x0008,
|
||||||
|
}
|
||||||
|
|
||||||
|
CONFIG_KEY_TO_OFFSET = {
|
||||||
|
"U_BAT_REGULATION_CORRIDOR": 0x0100,
|
||||||
|
"U_BAT_INITIAL_FULL": 0x0104,
|
||||||
|
"U_BAT_INITIAL_HOLD_CANCEL": 0x0108,
|
||||||
|
"INITIAL_CHARGE_HOLD_TIME": 0x010C,
|
||||||
|
"INITIAL_TO_FLOAT_TRANSITION_TIME": 0x0110,
|
||||||
|
"U_BAT_FLOAT_FULL": 0x0114,
|
||||||
|
"SLEEP_SOLAR_EXCESS_VOLTAGE": 0x0118,
|
||||||
|
"SLEEP_SOLAR_CURRENT": 0x011C,
|
||||||
|
"SLEEP_STATE_DELAY": 0x0120,
|
||||||
|
"SLEEP_SWITCH_DELAY": 0x0124,
|
||||||
|
"INTERNAL_TEMPERATURE_LIMIT": 0x0128,
|
||||||
|
"INTERNAL_TEMPERATURE_RECOVERY": 0x012C,
|
||||||
|
"U_BAT_LOAD_ON": 0x0130,
|
||||||
|
"U_BAT_LOAD_OFF": 0x0134,
|
||||||
|
"LOAD_CURRENT_LIMIT_MA": 0x0138,
|
||||||
|
"LOAD_CURRENT_INRUSH_TIME": 0x013C,
|
||||||
|
"MIN_CHARGE_PUMP_EXCESS_VOLTAGE": 0x0140,
|
||||||
|
"LOAD_ON_DELAY": 0x0144,
|
||||||
|
"AVG_ALPHA_I_SOLAR": 0x0148,
|
||||||
|
"AVG_ALPHA_I_LOAD": 0x014C,
|
||||||
|
"AVG_ALPHA_U_BAT": 0x0150,
|
||||||
|
"AVG_ALPHA_U_SW": 0x0154,
|
||||||
|
"AVG_ALPHA_U_SOLAR": 0x0158,
|
||||||
|
"AVG_ALPHA_TEMP": 0x015C,
|
||||||
|
"DEEPSLEEP_DELAY": 0x0160,
|
||||||
|
"DEEPSLEEP_DURATION": 0x0164,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
output = IntelHex()
|
||||||
|
|
||||||
|
if len(sys.argv) < 3:
|
||||||
|
print(f"usage: {sys.argv[0]} <yaml-config> <output-hex>")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
with open(sys.argv[1], 'r') as configfile:
|
||||||
|
config = yaml.safe_load(configfile)
|
||||||
|
|
||||||
|
for key, offset in CALIBRATION_KEY_TO_OFFSET.items():
|
||||||
|
value = config['calibration'][key]
|
||||||
|
enc_bytes = struct.pack('<H', value)
|
||||||
|
output.puts(BASE_ADDR + offset, enc_bytes)
|
||||||
|
|
||||||
|
for key, offset in CONFIG_KEY_TO_OFFSET.items():
|
||||||
|
value = config['config'][key]
|
||||||
|
enc_bytes = struct.pack('<I', value)
|
||||||
|
output.puts(BASE_ADDR + offset, enc_bytes)
|
||||||
|
|
||||||
|
output.write_hex_file(sys.argv[2])
|
18
utils/upload_config_hex.sh
Executable file
18
utils/upload_config_hex.sh
Executable file
|
@ -0,0 +1,18 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
HEXFILE="$1"
|
||||||
|
|
||||||
|
if [ ! -f "$HEXFILE" ]; then
|
||||||
|
echo "$HEXFILE cannot be accessed."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
JLinkExe -device STM32F030C8 -speed 1000 -if SWD <<EOF
|
||||||
|
connect
|
||||||
|
loadfile $HEXFILE
|
||||||
|
r
|
||||||
|
g
|
||||||
|
exit
|
||||||
|
EOF
|
Loading…
Reference in a new issue