Technical Summary: Estimating State of Charge (SoC) in electric vehicle battery packs requires combining a physical cell model with recursive state estimation. While Coulomb counting drifts due to current sensor noise, Extended Kalman Filters (EKF) frequently suffer from covariance divergence during flat open-circuit voltage regions or abrupt load transients. This guide details how to build a second-order equivalent circuit model in Simscape, derive the discrete Jacobian matrices, and implement the Joseph stabilized covariance update to prevent filter breakdown.

The challenge with battery State of Charge estimation

State of Charge cannot be measured directly with a physical sensor. In electric vehicles, the battery management system must infer the internal charge level using terminal voltage, pack current, and temperature measurements.

The simplest approach is Coulomb counting (current integration). While computationally cheap, Coulomb counting has two fundamental flaws: it requires an accurate initial condition, and it integrates current sensor bias over time. A 50 mA sensor offset across a four-hour drive cycle introduces significant drift into the calculation.

To correct this drift, engineers use closed-loop observers, most commonly the Extended Kalman Filter. The filter combines an internal equivalent circuit model with real-time terminal voltage feedback to continuously correct the state estimate. However, building this pipeline in MATLAB and Simscape introduces numerical instabilities that cause the filter to diverge, yielding NaN outputs or imaginary state vectors during simulation.

Building the battery plant model in Simscape

An accurate observer requires a plant model that balances physical fidelity with simulation speed. In Simscape Electrical, the two-resistor-capacitor (2-RC) Thevenin equivalent circuit provides the standard baseline for automotive cells.

The circuit consists of three main elements placed in series:

  • Open-circuit voltage source (OCV): A voltage source governed by a nonlinear lookup table as a function of SoC and temperature.
  • Ohmic resistance (R0): Represents the immediate voltage drop caused by electrolyte and contact resistance when current steps occur.
  • Two parallel RC networks (R1-C1 and R2-C2): Represent charge-transfer polarization (fast dynamics, time constant of seconds) and solid-state diffusion in the electrodes (slow dynamics, time constant of tens to hundreds of seconds).

In Simscape, you can construct this using the pre-built Table-Based Battery block or by connecting fundamental electrical components: a Controlled Voltage Source driven by a 2D lookup table, an internal resistor R0, and two series RC branches. When configuring the cell, set the solver to stiff variable-step options like ode15s or ode23t. Standard explicit solvers like ode45 will struggle with the disparate time constants between the switching electronics and the slow electrochemical diffusion.

Formulating the discrete state-space model

Before writing the filter code, the continuous differential equations of the 2-RC model must be discretized with a fixed sample time Ts (typically 0.05 to 0.1 seconds in real-world BMS controllers).

The state vector contains three states:

x_k = [ SoC_k;  V_RC1_k;  V_RC2_k ]
    

The state update equations are:

SoC(k) = SoC(k-1) - (Ts / (3600 * Q_total)) * I(k-1) * eta
V_RC1(k) = exp(-Ts / (R1 * C1)) * V_RC1(k-1) + R1 * (1 - exp(-Ts / (R1 * C1))) * I(k-1)
V_RC2(k) = exp(-Ts / (R2 * C2)) * V_RC2(k-1) + R2 * (1 - exp(-Ts / (R2 * C2))) * I(k-1)

Where Q_total is the nominal cell capacity in Ampere-hours, eta is the coulombic efficiency, and current I is positive during discharge.

The terminal voltage measurement equation is nonlinear because of the OCV function:

V_terminal(k) = OCV(SoC(k)) - V_RC1(k) - V_RC2(k) - I(k) * R0

Why the Extended Kalman Filter diverges

During simulations of aggressive drive cycles like US06 or WLTP, the estimated SoC frequently diverges from the true Simscape plant state. In engineering assignments, master dissertations, and prototype verification, this failure usually traces back to four specific mechanisms:

1. Flat OCV curves and loss of observability (especially in LFP cells)

The measurement Jacobian matrix relies directly on the derivative of open-circuit voltage with respect to SoC:

C_k = [ d(OCV)/d(SoC),  -1,  -1 ]
    

For Lithium Iron Phosphate (LFP) chemistry, the OCV curve between 20% and 80% SoC is virtually horizontal. In this plateau region, d(OCV)/d(SoC) approaches zero. As a result, the Kalman gain for the SoC state drops to near zero, meaning the filter ignores voltage measurement feedback and acts like open-loop Coulomb counting. Any small modeling error or sensor noise during this phase causes the covariance to grow unchecked.

2. Asymmetry in the error covariance matrix

The standard textbook update equation for error covariance is:

P = (eye(3) - K * C) * P_pred
    

Mathematically, P must remain symmetric and positive-definite. In digital floating-point execution, round-off errors gradually erode this symmetry. Once one eigenvalue of P dips below zero, the filter calculates impossible negative variances, the Kalman gain computes erroneous values, and the state estimates diverge to infinity.

3. Mismatched sample times between plant and controller

If the Simscape physical network runs under a continuous variable-step solver while the discrete EKF block is sampled asynchronously without an explicit rate transition, the current fed into the state transition matrix does not match the current that produced the measured terminal voltage. This timing skew introduces an artificial phase delay that causes high-frequency oscillations in the innovation step.

How to fix divergence: the stabilized EKF implementation

To prevent divergence and ensure robust convergence across wide temperature and current swings, implement the following modifications:

  • Use the Joseph stabilized covariance update: Replace the standard covariance equation with the Joseph formulation, which guarantees mathematical symmetry and positive semi-definiteness regardless of floating-point rounding.
  • Force manual symmetrization: Enforce P = 0.5 * (P + P') at the end of every time step.
  • Tune process noise covariance (Q) dynamically: When entering the flat OCV region, decrease process noise slightly on the voltage states and avoid setting the SoC process noise too low, which keeps the filter receptive to correction.

The full, runnable MATLAB simulation script demonstrating this stabilized filter with noisy sensor input and initial condition recovery is provided in the code section below.