Skip to main content

Reference implementations

Example models

Four reference estimators — a coulomb counter, an EKF, a feedforward network and an LSTM — each as a MATLAB and a Python package. Read the schematic and the annotated source, download the package, or run it on a public drive cycle with one click to see what a result looks like.

Example 1 — coulomb counter

Coulomb counterComplexity 1 · Trivial

Integrate current, divide by capacity. Twenty lines, the best way to learn the interface.

The simplest possible estimator: charge in and out of the cell is counted by integrating current at the 1 Hz sample rate and dividing by a fixed nominal capacity. The previous SOC is carried between calls in z.

It assumes the battery always starts full, ignores temperature-dependent capacity, and has no way to correct itself — so any current-sensor offset accumulates without bound. That is exactly why the robustness test cases exist.

Coulomb counter

Open-loop current integration

I(t)current∫ dtaccumulate÷ CcapacitySOCz = previous SOCV, T unused

Governing equation

SOCk=SOCk1+IkΔt3600Cn\mathrm{SOC}_k = \mathrm{SOC}_{k-1} + \frac{I_k\,\Delta t}{3600\, C_n}

C_n = 4.6 Ah, Δt = 1 s

State carried in z

Previous SOC only.

Uses

CurrentVoltageTemperature

Where it shines

  • Trivial to implement and verify
  • Zero latency, negligible compute
  • Exact if capacity, initial SOC and current are exact

Where it struggles

  • Drifts with any current-sensor offset
  • Fails the initial-SOC test outright (assumes 100 %)
  • Ignores temperature-dependent usable capacity
Model.mmatlab
1% SOC Estimation Example V2
2% Online Coulomb Counting SOC Estimator - McMaster University 2024
3function [Y_est, z] = Model(X, z)
4 % Input X: Measured current, voltage, and temperature values
5 % X: 3 columns, 1 row
6
7 % Current is negative-discharging, positive-charging
8 Current = X(1); % in [Amps]
9
10 % Voltage is unused in this Coulomb Counter
11 % Voltage = X(2); % in [Volts]
12
13 % Temperature is unused in this Coulomb Counter
14 % Temperature = X(3); % in [Celsius]
15
16 Capacity = 4.6; % in [Ah], nominal capacity of the cell
17
18 % Coulomb Counting SOC Estimator: SOC = integral of current
19 if nargin == 1 % start of measurement (z = [])
20 SOC = 1; % assume battery always starts fully charged
21 z = SOC; % send back previous SOC as memory z
22 else
23 previous_SOC = z; % load z as previous SOC
24 SOC = previous_SOC + Current*(1/3600)/Capacity; % integrate current
25 z = SOC; % send back previous SOC as memory z
26 end
27
28 % Output Y: Estimated SOC (1 row, 1 column)
29 Y_est = SOC';
30end

See it evaluated

Queues a dry run of the shipped MATLAB package on one public cycle — the same check you get for your own model. Counts toward your 5 test runs per hour.

Sign in to run it

Adapting an example

  1. Keep the signature — MATLAB [Y, z] = Model(X, z) with a nargin < 2 initialisation block, or Python def Model(X, z=None) returning (Y, z).
  2. Put every parameter your model needs either inline or in a .mat loaded once at initialisation — never in the per-sample path.
  3. Return SOC on 0–1 and store all memory in z; the evaluator keeps nothing else between calls.
  4. Use Test your package first on the Submit page, then submit.