Battery Charger

Battery and charger configuration and functions.

Enums

enum BatType

Battery cell types

Values:

enumerator BAT_TYPE_CUSTOM

Custom battery type.

enumerator BAT_TYPE_FLOODED

Old flooded (wet) lead-acid batteries.

enumerator BAT_TYPE_GEL

VRLA gel batteries (maintainance-free)

enumerator BAT_TYPE_AGM

AGM batteries (maintainance-free)

enumerator BAT_TYPE_LFP

LiFePO4 Li-ion batteries (3.3V nominal)

enumerator BAT_TYPE_NMC

NMC/Graphite Li-ion batteries (3.7V nominal)

enumerator BAT_TYPE_NMC_HV

NMC/Graphite High Voltage Li-ion batteries (3.7V nominal, 4.35 max)

enum ChargerState

Possible charger states

Further information:

Values:

enumerator CHG_STATE_IDLE

Idle

Initial state of the charge controller. If the solar voltage is high enough and the battery is not full, bulk charging mode is started.

enumerator CHG_STATE_BULK

Bulk / CC / MPPT charging

The battery is charged with maximum possible current (MPPT algorithm is active) until the CV voltage limit is reached.

enumerator CHG_STATE_TOPPING

Topping / CV / absorption charging

Lead-acid batteries are charged for some time using a slightly higher charge voltage. After a current cutoff limit or a time limit is reached, the charger goes into float or equalization mode for lead-acid batteries or back into Standby for Li-ion batteries.

enumerator CHG_STATE_FLOAT

Float / trickle charging

This mode is kept forever for a lead-acid battery and keeps the battery at full state of charge. If too much power is drawn from the battery, the charger switches back into CC / bulk charging mode.

enumerator CHG_STATE_EQUALIZATION

Equalization charging

This mode is only used for lead-acid batteries after several deep-discharge cycles or a very long period of time with no equalization. Voltage is increased to 15V or above, so care must be taken for the other system components attached to the battery. (currently, no equalization charging is enabled in the software)

enumerator CHG_STATE_FOLLOWER

Parallel operation of multiple converters

This mode is enabled if the device receives commands from an external controller with higher priority on the CAN bus. The device goes in current control modes and tries to match the current of the other controller.

Functions

void battery_conf_init(BatConf *bat, int type, int num_cells, float nominal_capacity)

Basic initialization of battery configuration

Configures battery based on settings defined in config.h and initializes bat_user with same values

Parameters:
  • bat – Battery configuration that should be initialized

  • type – Battery type, one of enum BatType (declared as int instead of enum BatType because configuration via Kconfig symbol cannot handle enums)

  • num_cells – Number of cells (e.g. 6 for 12V lead-acid battery)

  • nominal_capacity – Nominal capacity (Ah)

bool battery_conf_check(BatConf *bat)

Checks battery user settings for plausibility

void battery_conf_overwrite(BatConf *source, BatConf *destination, Charger *charger = NULL)

Overwrites battery settings (config should be checked first)

Settings specified in bat_user will be copied to actual battery_t, if suggested updates are valid (includes plausibility check!)

bool battery_conf_changed(BatConf *a, BatConf *b)

Checks if incoming configuration is different to current configuration

Returns true if changed

struct BatConf
#include <bat_charger.h>

Battery configuration data

Data will be initialized in battery_init depending on configured cell type in config.h.

Public Members

float nominal_capacity

Nominal battery capacity or sum of parallel cells capacity (Ah)

The nominal capacity is used for SOC calculation and definition of current limits.

float recharge_voltage

Recharge voltage (V)

Start charging again if voltage of fully charged battery drops below this threshold.

Remark: Setting the value too close to the max voltage will cause more charging stress on lithium based batteries.

uint32_t time_limit_recharge

Recharge time limit (sec)

Start charging of previously fully charged battery earliest after this period of time.

float absolute_max_voltage

Absolute maximum voltage (V)

Above this voltage the battery or loads might get damaged.

float absolute_min_voltage

Absolute minimum voltage (V)

Below this voltage the battery is considered damaged.

float charge_current_max

Maximum charge current in CC/bulk phase (A)

Limits the current if the PCB allows more than the battery. (positive value)

float discharge_current_max

Maximum discharge current via load port (A)

Limits the current if the PCB allows more than the battery. (positive value)

float topping_voltage

Maximum voltage in CV/absorption phase (V)

Charger target voltage, switching from CC to CV at this voltage threshold.

float topping_cutoff_current

CV phase cut-off current limit (A)

Constant voltage charging phase stopped if current is below this value.

uint32_t topping_duration

CV phase cut-off time limit (s)

After this time, CV charging is stopped independent of current.

bool float_enabled

Enable float/trickle charging

Caution: Do not enable float charging for lithium-ion batteries

float float_voltage

Float voltage (V)

Charger target voltage for float charging of lead-acid batteries

uint32_t float_recharge_time

Float recharge time (s)

If the float voltage is not reached anymore (e.g. because of lack of solar input power) for this period of time, the charger state machine goes back into CC/bulk charging mode.

bool equalization_enabled

Enable equalization charging

Caution: Do not enable float charging for lithium-ion batteries

float equalization_voltage

Equalization voltage (V)

Charger target voltage for equalization charging of lead-acid batteries

uint32_t equalization_duration

Equalization cut-off time limit (s)

After this time, equalization charging is stopped.

float equalization_current_limit

Equalization phase maximum current (A)

The current of the charger is controlled to stay below this limit during equalization.

uint32_t equalization_trigger_days

Equalization trigger time interval (days)

After passing specified amount of days, an equalization charge is triggered.

uint32_t equalization_trigger_deep_cycles

Equalization trigger deep-discharge cycles

After specified number of deep discharges, an equalization charge is triggered.

float load_disconnect_voltage

Load disconnect open circuit voltage (V)

Load output is disabled if battery voltage is below this threshold.

The voltage is current-compensated using the battery internal resistance: threshold = load_disconnect_voltage + battery_current * internal_resistance

(Remark: battery_current negative during discharge, internal_resistance positive)

float load_reconnect_voltage

Load reconnect open circuit voltage (V)

Re-enable the load only after charged beyond this value.

The voltage is current-compensated using the battery internal resistance: threshold = load_reconnect_voltage + battery_current * internal_resistance

(Remark: battery_current positive during charge, internal_resistance positive)

float internal_resistance

Battery internal resistance (Ohm)

Resistance value for current-compensation of load switch voltage thresholds.

The value must have a positive sign. Only resistance values leading to less than 10% voltage drop at max. current are allowed.

float wire_resistance

Resistance of wire between charge controller and battery (Ohm)

Resistance value for current-compensation of charging voltages.

The value must have a positive sign. Only resistance values leading to less than 3% voltage loss at max. current are allowed.

float ocv_full

Open circuit voltage of full battery (V)

Used for simple state of charge (SOC) algorithm.

float ocv_empty

Open circuit voltage of empty battery (V)

Used for simple state of charge (SOC) algorithm.

float charge_temp_max

Maximum allowed charging temperature of the battery (°C)

float charge_temp_min

Minimum allowed charging temperature of the battery (°C)

float discharge_temp_max

Maximum allowed discharging temperature of the battery (°C)

float discharge_temp_min

Minimum allowed discharging temperature of the battery (°C)

float temperature_compensation

Voltage compensation based on battery temperature (mV/K/cell)

Suggested value: -3 mV/K/cell

class Charger
#include <bat_charger.h>

Charger configuration and battery state

Public Functions

inline Charger(PowerPort *pwr_port)
void detect_num_batteries(BatConf *bat) const

Detect if two batteries are connected in series (12V/24V auto-detection)

void discharge_control(BatConf *bat_conf)

Discharging control update (for load output), should be called once per second

void charge_control(BatConf *bat_conf)

Charger state machine update, should be called once per second

void update_soc(BatConf *bat_conf)

SOC estimation

Must be called exactly once per second, otherwise SOC calculation gets wrong.

void init_terminal(BatConf *bat) const

Initialize terminal and dc bus for battery connection

Parameters:

bat – Configuration to be used for terminal setpoints

Public Members

PowerPort *port
uint32_t state = CHG_STATE_IDLE

Current charger state (see enum ChargerState)

float bat_temperature = 25

Battery temperature (°C) from ext. temperature sensor (if existing)

bool ext_temp_sensor

Flag to indicate if external temperature sensor was detected

float usable_capacity

Estimated usable capacity (Ah) based on coulomb counting

float discharged_Ah

Coulomb counter for SOH calculation

uint16_t num_full_charges

Number of full charge cycles

uint16_t num_deep_discharges

Number of deep-discharge cycles

uint16_t soc = 100

State of Charge (%)

uint16_t soh = 100

State of Health (%)

time_t time_state_changed = CHARGER_TIME_NEVER

Timestamp of last state change

time_t time_target_voltage_reached = CHARGER_TIME_NEVER

Last time the CV limit was reached

uint32_t target_voltage_timer

Counts the number of seconds during which the target voltage of current charging phase was reached.

time_t time_last_equalization = CHARGER_TIME_NEVER

Timestamp after finish of last equalization charge

uint32_t deep_dis_last_equalization

Deep discharge counter value after last equalization

bool full

Flag to indicate if battery was fully charged

bool empty

Flag to indicate if battery was completely discharged

time_t time_last_ctrl_msg = CHARGER_TIME_NEVER

Last time a control message from external device was received

float target_current_control

Target current of the converter if operating in follower mode (received from external converter with higher priority via CAN)

Private Functions

void enter_state(int next_state)