Data Set Consideration for Battery SOC Prediction

Q - Battery Capacity

SOC is measured using Coulomb counting approach where Battery Capacity (Q) is one of the key parameter. Below is the formula of SOC measurement using Coulomb counting

\[SOC_{t} = SOC_{t_0} \pm \frac{1}{Q_{nominal}} \int_{t_0}^{t} I(\tau) \, d\tau\]

Q is one of the computation variable. Hence, Generated dataset from pybamm should specific for a target battery model capacity. Each variant of Q need to have dedicated dataset.

Q (Battery Capacity) is changing based on the battery aging**. capacity will  be gradually reduced from 100% to 90% .. 80% etc. 

Each scenario might need dedicated dataset.

I - Current

Power-Current relationship

\[P = V \cdot I \quad \Rightarrow \quad I = \frac{P}{V}\]

C-Rate Definition

\[C\text{-rate} = \frac{I}{Q} \quad \Rightarrow \quad I = C\text{-rate} \cdot Q\]

Based on above equation, The higher charging rate (C-Rate) will resulting in higher Current(I) and finally increase the eletricity drained from battery. Simulating Charging rate (C-Rate) and Current (I) would be quite difficult as its depend on several variables such as Voltage (V), Power (P) and Capacity (C)

Pybamm can come in handy to generate simulated data for battery behavior

Those variable will be computed and simulated by pybamm using mathematical modelling.

Dataset Generation Scenario

Use Cases Scope

SoC Prediction will based on Hyndai Ionic 5 information that available on the internet.

  • Battery capacity: 77.4 KwH
  • Chemistry: Lithium Ion
  • Q (Ah): 128 Ah

Since the model param used is Chen2020, 5 Ah will be used.

Paramter

Battery Model is Lithium Ion SPM with Chen2020 Model Input parameter

Below is the updated / Overrided Parameter

NoParameterTypeSources
1Battery Capacity (Q)Model InputSet to 5
2SoCModel OutputComputed using Coulomb Counting

Variation

a total of 40 dataset are generated to cater battery aging scenario up to 40% loss or 60% battery capacity.

Dataset is generated per 1% capacity decrease from the initial value  

Major EV OEM suggest to replace the battery at 70~80% capacity.

VariantCapacity (%)Q (Ah)
11005.00
2994.95
3984.90
4974.85
5964.80
6954.75
7944.70
8934.65
9924.60
10914.55
11904.50
12894.45
13884.40
14874.35
15864.30
16854.25
17844.20
18834.15
19824.10
20814.05
21804.00
22793.95
23783.90
24773.85
25763.80
26753.75
27743.70
28733.65
29723.60
30713.55
31703.50
32693.45
33683.40
34673.35
35663.30
36653.25
37643.20
38633.15
39623.10
40613.05

Script to Generate Batch Battery Dataset

Install pybamm and Pandas

%pip install pybamm
%pip install pandas

Generate Dataset (40 Variant)

  1. Running simulation for Variant 1 with Q = 5.0 Ah
  2. Running simulation for Variant 2 with Q = 4.95 Ah
  3. Running simulation for Variant 3 with Q = 4.9 Ah
  4. Running simulation for Variant 4 with Q = 4.85 Ah
  5. Running simulation for Variant 5 with Q = 4.8 Ah
  6. Running simulation for Variant 6 with Q = 4.75 Ah
  7. Running simulation for Variant 7 with Q = 4.7 Ah
  8. Running simulation for Variant 8 with Q = 4.65 Ah
  9. Running simulation for Variant 9 with Q = 4.6 Ah
  10. Running simulation for Variant 10 with Q = 4.55 Ah
  11. Running simulation for Variant 11 with Q = 4.5 Ah
  12. Running simulation for Variant 12 with Q = 4.45 Ah
  13. Running simulation for Variant 13 with Q = 4.4 Ah
  14. Running simulation for Variant 14 with Q = 4.35 Ah
  15. Running simulation for Variant 15 with Q = 4.3 Ah
  16. Running simulation for Variant 16 with Q = 4.25 Ah
  17. Running simulation for Variant 17 with Q = 4.2 Ah
  18. Running simulation for Variant 18 with Q = 4.15 Ah
  19. Running simulation for Variant 19 with Q = 4.1 Ah
  20. Running simulation for Variant 20 with Q = 4.05 Ah
  21. Running simulation for Variant 21 with Q = 4.0 Ah
  22. Running simulation for Variant 22 with Q = 3.95 Ah
  23. Running simulation for Variant 23 with Q = 3.9 Ah
  24. Running simulation for Variant 24 with Q = 3.85 Ah
  25. Running simulation for Variant 25 with Q = 3.8 Ah
  26. Running simulation for Variant 26 with Q = 3.75 Ah
  27. Running simulation for Variant 27 with Q = 3.7 Ah
  28. Running simulation for Variant 28 with Q = 3.65 Ah
  29. Running simulation for Variant 29 with Q = 3.6 Ah
  30. Running simulation for Variant 30 with Q = 3.55 Ah
  31. Running simulation for Variant 31 with Q = 3.5 Ah
  32. Running simulation for Variant 32 with Q = 3.45 Ah
  33. Running simulation for Variant 33 with Q = 3.4 Ah
  34. Running simulation for Variant 34 with Q = 3.35 Ah
  35. Running simulation for Variant 35 with Q = 3.3 Ah
  36. Running simulation for Variant 36 with Q = 3.25 Ah
  37. Running simulation for Variant 37 with Q = 3.2 Ah
  38. Running simulation for Variant 38 with Q = 3.15 Ah
  39. Running simulation for Variant 39 with Q = 3.1 Ah
  40. Running simulation for Variant 40 with Q = 3.05 Ah
import pybamm
import pandas as pd
from pybamm import BaseModel
from IPython.display import display

## [1] Doyle Fuller Newman [2] Single Particle Model (SPM) [3] Single Particle Model with Electrolyte (SPMe)
availableModel = ["DFN", "SPM", "SPME"]
selectedModel = availableModel[0]
model: BaseModel

# Choose model
match selectedModel:
    case "DFN":
        model = pybamm.lithium_ion.DFN()
    case "SPM":
        model = pybamm.lithium_ion.SPM()
    case "SPME":
        model = pybamm.lithium_ion.SPMe()

# List of capacities from 5.0 Ah to 3.05 Ah in 1% steps
capacity_variants = [round(5.0 * (1 - i / 100), 2) for i in range(40)]

# Final DataFrame to store all results
all_results = pd.DataFrame()

# Loop through all capacity variants
for variant_num, cap in enumerate(capacity_variants, start=1):
    print(f"Running simulation for Variant {variant_num} with Q = {cap} Ah")

    selectedInputParameter = pybamm.ParameterValues("Chen2020")
    selectedInputParameter.update({
        "Nominal cell capacity [A.h]": cap
    })
    
    experiment = pybamm.Experiment(
        [
            (
                "Charge at C/2 until 4.2 V",
                "Discharge at C/5 for 2 hours or until 2.5 V"
            )
        ],
        period="1 second"
    )

    sim = pybamm.Simulation(model, experiment=experiment, parameter_values=selectedInputParameter)
    
    try:
        sim.solve()
    except Exception as e:
        print(f"Simulation failed for Q = {cap} Ah: {e}")
        continue  # skip to the next variant

    # Prepare data collection
    output_variables = ["Time [s]", "Current [A]", "Voltage [V]", "X-averaged cell temperature [K]",
                        "BatteryCapacity", "TimeDiff", "CapacityDiff", "SOC"]
    
    data = {}
    num_rows = len(sim.solution["Time [min]"].entries)

    for var in output_variables:
        if var == "TimeDiff":
            timeDiffValues = [0] + [
                sim.solution["Time [s]"].entries[i] - sim.solution["Time [s]"].entries[i - 1]
                for i in range(1, num_rows)
            ]
            data[var] = timeDiffValues
        elif var == "BatteryCapacity":
            data[var] = [cap] * num_rows
        elif var == "CapacityDiff":
            capacityDiffValues = [0]
            for i in range(1, num_rows):
                deltaCapacity = sim.solution["Current [A]"].entries[i] * (timeDiffValues[i] / 3600) * -1
                capacityDiffValues.append(deltaCapacity)
            data[var] = capacityDiffValues
        elif var == "SOC":
            soc_values = [1]
            for i in range(1, num_rows):
                soc_values.append(soc_values[i - 1] + (data["CapacityDiff"][i] / cap))
            data[var] = soc_values
        else:
            data[var] = sim.solution[var].entries

    df = pd.DataFrame(data)
    df["Variant"] = variant_num
    all_results = pd.concat([all_results, df], ignore_index=True)

# Save to CSV
all_results.to_csv("batch_battery_simulation.csv", index=False)
display(all_results)