BMS Firmware Layers
A production BMS firmware stack has clear separation: Hardware Abstraction (ADC drivers, GPIO for contactors), Measurement Layer (calibrated readings), Estimation Layer (SoC, SoH), Protection Layer (OV/UV/OC/OT), Balancing Layer, and Communication (CAN/LIN).
Coulomb Counting
void bms_update_coulomb_count(void) {
float i_avg = adc_get_pack_current();
float dt = 0.1f; /* 100ms */
pack.coulombs += i_avg * dt;
pack.soc_raw = pack.coulombs / PACK_CAPACITY_AS;
pack.soc_raw = fminf(1.0f, fmaxf(0.0f, pack.soc_raw));
}Extended Kalman Filter for SoC
Coulomb counting drifts over time. EKF fuses current integration with OCV (Open Circuit Voltage) measurements. The predict step advances SoC using current; the update step corrects using measured OCV vs expected OCV from lookup table.
Passive Cell Balancing
Bleed excess charge from high-SoC cells via bypass resistors. Simple and reliable, but wastes energy as heat. Compare each cell SoC to pack minimum — enable balance switch if delta exceeds threshold (typically 2%).
Key Design Decisions
- Measurement timing — Sample all cells synchronously to avoid current ripple artifacts.
- OCV lookup tables — Characterize at multiple temperatures. LFP and NMC have very different OCV curves.
- Protection hysteresis — Add hysteresis to thresholds (cut at 4.20V, recover at 4.15V) to prevent rapid cycling.