# 4.2. Balancing Module

## 4.2.1. Module Files

### 4.2.1.1. Driver

• src/app/application/bms/history/bal_strategy_history.c (API, source)

• src/app/application/bms/history/bal_strategy_history.h (API, source)

• src/app/application/bms/none/bal_strategy_none.c (API, source)

• src/app/application/bms/none/bal_strategy_none.h (API, source)

• src/app/application/bms/voltage/bal_strategy_voltage.c (API, source)

• src/app/application/bms/voltage/bal_strategy_voltage.h (API, source)

• src/app/application/bms/bal.c (API, source)

• src/app/application/bms/bal.h (API, source)

### 4.2.1.2. Configuration

• src/app/application/config/bal_cfg.h (API, source)

### 4.2.1.3. Unit Test

• tests/unit/app/application/bal/history/test_bal_strategy_history.c (API, source)

• tests/unit/app/application/bal/none/test_bal_strategy_none.c (API, source)

• tests/unit/app/application/bal/voltage/test_bal_strategy_voltage.c (API, source)

• tests/unit/app/application/bal/test_bal.c (API, source)

## 4.2.2. Detailed Description

### 4.2.2.1. Voltage-based Balancing

In voltage-based balancing, the balancing module takes the minimum battery cell voltage of the complete battery pack and activates balancing for all the cells whose voltage is above the minimum + BAL_GetBalancingThreshold_mV(). Once all cells have been balanced, the threshold is set to BAL_GetBalancingThreshold_mV() + BAL_HYSTERESIS_mV to avoid an oscillating behavior between balancing and not balancing.

### 4.2.2.2. History-based Balancing

The SOC history-based balancing works as follows: at one point in time, when no current is flowing and the cell voltages have fully relaxed (e.g., after 3 hours rest time), the voltages of all cells are measured. With a suitable SOC versus voltage look-up table, the voltages are converted to their respective SOC. These SOC are then translated to Depth-of-Discharge (DOD) using the nominal capacity, with:

$DOD = Capacity \times (1-SOC)$

The cell with the highest DOD is taken as a reference, since it is the most discharged cell in the battery pack. Its charge difference is set to 0. For all other cells, the charge difference is computed via:

$Charge_{\mathrm{difference}}(C_{\mathrm{c}}) = DOD(C_\mathrm{r}) - DOD(C_{\mathrm{c}})$

where $$C_{\mathrm{c}}$$ is the considered cell and $$C_{\mathrm{r}}$$ is the reference cell.

Balancing is then switched on for all cells. Every second, for each cell, the voltage is taken and the balancing current $$I_{\mathrm{balancing}}$$ computed by

$I_{\mathrm{balancing}} = U_{\mathrm{C}} / R_{\mathrm{balancing}}$

where $$U_{\mathrm{C}}$$ is the cell voltage and $$R_{\mathrm{balancing}}$$ is the balancing resistance.

The balancing quantity $$I_{\mathrm{balancing}} \times 1s$$ is subtracted from the charge difference. Balancing is stays turned on until the charge difference reaches 0.

In SOC history-based balancing, BS_BALANCING_RESISTANCE_ohm must be defined identically to the balancing resistances soldered on the Slave Board. When the imbalances are computed, they are set to a non-zero value to balance each specific cell only if its cell voltage is above the minimum cell voltage of the battery pack plus a threshold. The threshold is set in this case to BAL_GetBalancingThreshold_mV() + BAL_HYSTERESIS_mV.

The correspondence between cell voltage and SOC must be defined by the user depending on the specific battery cells used. Currently, it is done in the function SE_GetStateOfChargeFromVoltage() in sox.c. This function gets a voltage in V and return an SOC between 0.0 and 1.0.

### 4.2.2.3. No Balancing

No balancing is performed on any cell.