Extended Kalman Filter (EKF) for Lithium-Ion Battery State-of-Charge Estimation in MATLAB
Dr. Elena Rostova, PhD 15 min read Doctoral Peer-Reviewed Updated Sep 2026
Toolboxes:MATLAB BaseSimscape Battery
Executive Engineering Summary
Complete, runnable MATLAB implementation of an Extended Kalman Filter based on the 1st-Order Thevenin Equivalent Circuit Model (ECM). Includes covariance tuning matrix setup, Coulomb counting comparison, and automated terminal plotting.
Battery management systems need an accurate State-of-Charge (SOC) estimate to calculate driving range and protect cells from over-discharge. You cannot measure SOC directly with a physical probe. Integrating current over time (Coulomb counting: SOC(t) = SOC0 − (1 / Qn) ∫ I(t) dt) suffers from sensor bias that accumulates drift, and any error in your starting assumption persists indefinitely. Looking up open-circuit voltage (OCV) avoids this drift, but resting voltage curves only match terminal voltage once the cell has sat idle for several hours.
An Extended Kalman Filter (EKF) combines both methods. It treats Coulomb counting as a predictive state step and uses real-time terminal voltage measurements to correct the estimate whenever the model drifts from sensor data.
1. The 1st-order Thevenin equivalent circuit model (ECM)
To run the filter, we represent the cell as a 1st-order RC network with three primary elements:
Voc(SOC): Open-circuit voltage source that varies nonlinearly with charge.
R0: Ohmic resistance capturing immediate IR voltage drops across the electrolyte and current collectors.
R1 β₯ C1: Parallel RC branch with time constant τ = R1 · C1 that models charge transfer and diffusion dynamics.
Discrete-Time State Space Equations:
State 1 (Charge): SOCk+1 = SOCk − [η Δt / (3600 · Qn)] · Ik + w1,k
Where τ = R1 · C1, Ik > 0 denotes discharge, and wk, vk are zero-mean Gaussian process and measurement noises with covariance matrices Q and R.
2. Filter formulation and linearization
The state dynamics are linear, but the measurement equation is not: the open-circuit voltage curve Voc(SOC) is strongly nonlinear. Because the standard Kalman filter requires a linear observation matrix, we linearize Vt,k around the predicted state using a first-order Taylor expansion:
Measurement Jacobian Matrix:
Hk = [ (∂Voc / ∂SOC) |xΜk|k−1 , −1 ]
The scalar term (∂Voc / ∂SOC) is the local slope of the OCV curve evaluated at the current state estimate. On flat portions of the curve, this derivative is small, so terminal voltage provides little information about charge. On steeper portions, this derivative is large, and the filter updates the state estimate aggressively.
3. Runnable MATLAB implementation
This script builds an ECM for a 2.5 Ah cylindrical cell, simulates a 1-hour dynamic current profile, and corrupts current and voltage with realistic sensor noise (100 mA and 15 mV standard deviations). We deliberately initialize the filter at 65% SOC while the true cell starts at 85% to test convergence under real operating conditions.
4. Tuning the covariance matrices Q and R
The filter's convergence speed and noise rejection come down to the balance between Q and R:
Measurement variance R: Match this directly to your ADC hardware noise: R = σV2. For an analog front end with 15 mV RMS noise, set R = (0.015)2 = 2.25 × 10−4 V2. Setting R too small makes the filter chase sensor jitter; setting it too high causes the estimate to ignore valid voltage corrections.
Process noise Q(1, 1) for SOC: This controls how much the algorithm trusts Coulomb counting against model discrepancies. A value around 10−6 to 10−5 works well for typical dynamic load cycles. Setting it below 10−8 makes the filter behave like open-loop Coulomb counting, preventing it from correcting initial SOC errors. Setting it above 10−3 allows dynamic current pulses to cause artificial jumps in estimated SOC.
Process noise Q(2, 2) for V1: Set this between 10−5 and 10−4 to absorb unmodeled polarization effects that the single RC pair misses.
Drop-in MATLAB Implementation
The following production-ready helper script can be downloaded or integrated directly into your workspace:
Contributing Simulation & Algorithm Research Engineer at the MATLAB Helpers Technical Laboratory. Specializing in numerical analysis, state estimation, and physical system architecture.
Need Hands-on Engineering Assistance With This Model?
Whether diagnosing non-converging numerical solvers, tuning observers, or optimizing embedded code generation, our doctoral team collaborates directly on complex engineering codebases.