Battery Pack Optimizer Project Report

A practical Python GUI for grouping measured 18650 cells using capacity, DCIR, and configurable voltage-spread screening.

Python PySide6 GUI Excel input/output Simulated annealing Voltage-spread screening

Executive Summary

The application is a planning aid for assigning measured cells into series groups with parallel slots. It validates spreadsheet data, selects cells when extras are available, optimizes group balance, applies configurable voltage-spread screening, visualizes the layout, and exports a formatted workbook. It does not determine whether a pack is safe to build or use.

Primary Goal
Balanced groups
  • Similar group capacity
  • Similar parallel DCIR
  • Configured voltage-spread limits inside each parallel group
Example Screening Bands
Voltage matching
  • Lowest penalty: ≤ 0.02 V
  • Small penalty: 0.02–0.05 V
  • Strong penalty: > 0.05 V
  • Example rejection level: > 0.10 V
Final Output
Planning report
  • Pack summary
  • Visual layout
  • Grouped cells table
  • Excel export with screening colors

Inputs

The app expects an Excel sheet with measured cell data. Voltage is now part of the expected input because it matters before cells are physically connected in parallel.

Required columns
  • Cell ID
  • Model
  • Capacity (mAh)
  • DCIR (mΩ)
  • Voltage (V)
User settings
  • Pack configuration, such as 10S4P
  • Nominal and full cell voltage
  • Capacity, DCIR, and voltage weights
  • Max allowed parallel voltage spread
  • User-defined rejection threshold

How the Optimizer Works

The optimizer starts from a reasonable first layout, then repeatedly swaps cells between groups to reduce the pack score.

Capacity

Parallel cell capacities are summed within each series group. The optimizer tries to make those group totals similar.

group_capacity = sum(cell capacities) capacity_score = std(group_capacities) / mean(group_capacities)
DCIR

Cells in parallel behave like resistors in parallel, so group DCIR is calculated using reciprocal resistance.

group_DCIR = 1 / sum(1 / cell_DCIR) dcir_score = std(group_DCIRs) / mean(group_DCIRs)
Voltage-spread screen

Voltage is treated differently from capacity and DCIR. Capacity/DCIR are balanced between series groups. Voltage spread is checked inside each parallel group, because cells connected in parallel must be close in voltage before connection.

group_voltage_spread = max(group voltages) minus min(group voltages)

How the Score Is Calculated

The score is a single number that tells the optimizer how good a proposed pack layout is. A lower score is better. Each possible layout is judged by how evenly it distributes capacity, how evenly it distributes internal resistance, and whether any parallel group has a risky voltage spread.

Capacity balance

First, the app adds the cell capacities inside each series group. It then compares those group totals. If one group has much less capacity than the others, that group will limit the whole pack, so the score goes up.

capacity_score = standard deviation of group capacities divided by average group capacity
DCIR balance

DCIR is calculated as parallel resistance inside each group. At a given current, higher-resistance groups can experience more voltage drop and resistive heating, so the optimizer tries to keep group resistance values close together.

dcir_score = standard deviation of group DCIR values divided by average group DCIR
Voltage penalty

Voltage is handled as a configurable screening input inside each parallel group. Larger spreads add a penalty because directly connecting cells at different voltages can drive equalization current between them.

  • Up to 0.02 V adds no penalty
  • 0.02 to 0.05 V adds a small penalty
  • Above 0.05 V adds a strong penalty
  • Above 0.10 V reaches the example rejection setting
Weighted total

The final score combines the three parts using user-selected weights. The resulting score compares candidate layouts under those settings; it is not a safety rating.

total_score = capacity_weight times capacity_score plus dcir_weight times dcir_score plus voltage_weight times voltage_penalty
How to read the score

The score is mainly useful for comparing layouts from the same cell set and same settings. It is not a universal battery quality number. If the optimizer finds a lower score, it has found a layout with better balance or fewer voltage concerns under the chosen weights.

Voltage-Spread Screening Logic

Voltage spread inside a proposed parallel group is one relevant screening input. Directly connecting cells at different voltages can drive equalization current between them, but no universal spread threshold makes a pack safe. Cell model, chemistry, state of charge, condition, temperature, protection, construction, and manufacturer guidance also matter.

No penalty
≤ 0.02 V
Small penalty
0.02–0.05 V
Strong penalty
> 0.05 V
Example reject
> 0.10 V
Current scoring behavior

The example voltage bands are scoring settings, not validated safety limits.

  • ≤ 0.02 V: no voltage penalty
  • 0.02 to 0.05 V: small nudge penalty
  • > 0.05 V: strong penalty or rejection
  • > 0.10 V: example rejection warning
Important limitation

Before any physical work, cell compatibility and acceptable conditions must be established from the cell manufacturer's guidance and an appropriate pack-safety process. This tool does not provide that validation.

Outputs

In the GUI
  • Pack summary with voltage-spread screening result
  • Visual pack layout by series group and parallel slot
  • Grouped cells table
  • Group summary table
  • Capacity, DCIR, and voltage spread charts
Excel export
  • Grouped Cells
  • Group Summary
  • Pack Summary
  • Unused Cells
  • Conditional formatting for configured screening bands

Challenges Faced During Development

Initial UI density

The first version was functional but looked like a default desktop tool. The layout was redesigned with a clearer sidebar, better summary cards, stronger buttons, and cleaner charts.

Screen fit

The first visual pass was too tall for smaller screens. The sidebar was changed so settings scroll independently, while the Optimize button, status log, and progress bar remain pinned at the bottom.

Voltage screening

The app originally optimized capacity and DCIR only. Voltage was added because cells connected in parallel need close voltages before assembly to reduce equalization current risk.

Too strict voltage scoring

The first voltage scoring method penalized every tiny voltage spread. This caused the optimizer to lock onto the voltage-sorted starting layout. The scoring was changed so the lowest example band has no penalty and larger spreads act as a configurable constraint.

Diagnostics noise

Detailed optimizer diagnostics helped debug the algorithm, but they were too noisy for the status panel. The status panel now focuses on progress and final score, while detailed information remains in the summary/export path.