The problem
As Li-ion cells age, internal resistance rises and capacity falls; rising resistance reduces available power and increases heating. A BMS that tracks resistance online can warn of ageing without a full capacity test. The challenge is that measured resistance also depends on SOC, temperature and measurement timing, which must be separated from true ageing.
Objectives
- Measure internal resistance on board from load-step voltage changes.
- Estimate current from measured voltage and calibrated load resistance and state its error.
- Build correction tables for SOC and temperature effects on resistance.
- Log resistance with timestamps to SPI flash across repeated cycles.
- Compare a resistance-based SOH indicator with capacity measured by full discharge.
What you need
From the EV Embedded Development Kit
- STM32F103C8T6 microcontroller unit (Arm Cortex-M3)
- 1S battery with connector and T-sense input
- Load section: three switchable resistive loads with LEDs
- Charge/discharge control relay
- Battery charging unit with its own switch
- SPI flash memory
- RTC with CR2032 backup cell
- 16×2 LCD with contrast control
Software
- STM32CubeIDE
- Embedded C with STM32 HAL
- Python with NumPy, pandas and matplotlib
Extra parts
None. Everything this project needs is on the kit.
This project uses the kit's lithium cell. Respect polarity, never short the terminals, and don't leave the cell charging unattended.
Key concepts
- Internal resistance from a load step
- R = (V_before − V_after) / I_load, where I_load is the current drawn after the step. With a known load resistance, I_load = V_after / R_load, so no current sensor is needed for the measurement.
- Measurement timing
- A sample a few milliseconds after the step gives mostly ohmic resistance; a sample after a second or more includes polarisation. The chosen delay must be fixed and reported.
- SOH indicators
- SOH by capacity is current capacity divided by rated capacity; SOH by resistance compares present resistance with its value when new. They do not have to move together.
- Confounding factors
- Resistance rises at low SOC and at low temperature, so a raw reading can look like ageing when it is just a cold or empty cell. Corrections or fixed measurement conditions are required.
Step-by-step guide
- 1
Define the SOH method and conditions
Choose a standard measurement: one load combination, a fixed sample delay after the step (for example 10 ms for ohmic and 1 s for total), taken only when SOC and temperature are inside a defined window. Define SOH_R = R_initial / R_now, and plan reference capacity tests at the start, middle and end of the cycling campaign. Since one cell ages slowly, plan to use a public dataset such as NASA PCoE for the long-term trend analysis.
Checkpoint: A written method with measurement conditions, delays, SOH definitions and the cycling plan.
- 2
Set up the board
Check cell polarity and keep terminals covered. Enable DIP switches for battery sense, T-sense, loads, relay, SPI flash, RTC and LCD. Configure the ADC triggered by a timer at 1 kHz into a DMA ring buffer and calibrate voltage against a multimeter. Measure the load resistance with the board unpowered. Set the RTC and bring up the SPI flash with a JEDEC ID check.
Checkpoint: Calibrated 1 kHz voltage samples and a working RTC and flash.
- 3
Estimate current and its error
After the load step, current is V_after / R_load. Analyse the error: a 1 per cent load-resistance error gives a 1 per cent resistance error; heating of the load during the step is small if the step is short. Include the switch and wiring resistance in R_load by measuring through the switch path if possible. Write an uncertainty budget for R combining voltage resolution, noise and R_load error.
Checkpoint: An uncertainty budget for the measured internal resistance, for example ±5 per cent.
- 4
Implement the measurement routine
Write a function that checks conditions, records an averaged voltage before the step, switches the load on, captures the samples at the chosen delays, switches the load off and records the recovery. Compute ohmic and total resistance in integer micro-ohm units. Repeat the step five times and use the median to reject outliers. Show the result on the LCD. Log every individual step, not only the median, so noise can be analysed later.
Checkpoint: Five repeated measurements at rest agree within the uncertainty budget.
- 5
Map SOC dependence
From a full charge, discharge in steps and measure resistance at each SOC level after a fixed rest. Plot ohmic and total resistance against SOC. Identify the window where resistance is flat enough to compare readings over time, typically the middle range, and decide whether to restrict measurements to it or apply a correction table. Measure at least ten SOC levels and repeat the map on a second day to see whether the shape is repeatable before using it to correct readings.
Checkpoint: A resistance against SOC plot and a chosen measurement window or correction table.
- 6
Map temperature dependence
Measure at the few temperatures you can reach safely around the desk, such as early-morning room temperature and a warmer afternoon, recording the T-sense value. Fit a simple correction, for example an Arrhenius-style or linear relation over the small range, and state that it is only valid there. Never heat the cell with external heat sources. Repeat each measurement at the same SOC, because SOC and temperature effects would otherwise mix. Be clear that a narrow temperature range limits how far the correction can be trusted.
Checkpoint: A correction relation with the temperature range it covers and its fit quality.
- 7
Log to flash
Define a log record: timestamp, cycle number, SOC estimate, temperature, raw and corrected ohmic and total resistance, and a CRC. Append records to SPI flash in a circular log. Write a UART command that dumps the log as CSV for Python analysis. Plan the log size: with one record per measurement and a few measurements per cycle, a single flash sector can hold many cycles. Handle the case where the log wraps round so the newest records overwrite the oldest without corrupting the index.
Checkpoint: Records survive a power cycle and dump correctly as CSV.
- 8
Cycle the cell and measure capacity
Run repeated supervised charge and discharge cycles over the project, measuring resistance in the standard window each cycle and full capacity at the planned points. Keep the cell's operating limits strictly. Expect only small change in a few weeks; the aim is to prove the method and its noise floor, not to age the cell significantly. Keep a written logbook of every cycle and any interruption, so gaps in the data can be explained later.
Checkpoint: A cycle log with resistance per cycle and at least three capacity measurements.
- 9
Analyse SOH trends
Plot corrected resistance against cycle number with its uncertainty. Compare SOH_R with capacity-based SOH. Then apply the same resistance-from-step method offline to a public dataset such as NASA PCoE, which covers ageing to end of life, to show how the indicator behaves over a long trend that the kit cell cannot reach in one semester. Report the correlation between the two SOH measures and the spread around the trend, and check whether the temperature correction reduced that spread.
Checkpoint: Plots of SOH_R and capacity SOH for the kit cell and for the public dataset.
- 10
Write up
Report the method, uncertainty budget, SOC and temperature correction, logging design, kit results and public-dataset results. Discuss the minimum resistance change the method can detect, and compare it with typical end-of-life criteria described in literature. State limitations openly. Explain how the method would be used in a vehicle, where dedicated pulses are not always possible and normal load changes must be used instead. Include the raw logs, the analysis scripts and the configuration of every test so the results can be reproduced and checked by a reviewer.
Checkpoint: A report giving the detectable change in resistance and the evidence supporting it.
Testing & validation
- Repeatability of five consecutive measurements at fixed conditions.
- Resistance against SOC and temperature with fitted corrections.
- Flash log integrity after power cycles.
- Resistance trend compared with capacity measurements.
- Method applied to a public ageing dataset for long-term behaviour.
Expected results
An embedded internal-resistance SOH estimator with corrections, a measured noise floor, cycle-by-cycle logs for the kit cell and a comparison with capacity-based SOH, extended with public ageing data.
Research angle for your M.Tech thesis
Research questions: how small a resistance change can a low-cost, sensorless-current method detect, and how well does SOH from resistance track SOH from capacity? Metrics: measurement repeatability, detectable change, correlation between SOH_R and capacity SOH. Baselines: capacity tests on the kit and the NASA PCoE or CALCE ageing data. A rigorous uncertainty analysis plus validation on public ageing data makes this suitable for a conference paper on low-cost SOH monitoring.
Take it further
- Add an INA219 add-on and compare measured-current resistance with the V / R estimate.
- Estimate resistance continuously from normal load changes instead of dedicated pulses.
- Use the resistance to predict available power at low SOC.
- Send SOH over CAN as part of a BMS status message.
Viva and review questions
How do you get current without a current sensor?
After the load is switched on, current is the measured cell voltage divided by the calibrated load resistance, including the switch path.
Why does the sample delay matter?
Immediately after the step the drop is mostly ohmic; later samples include polarisation. Different delays give different resistances, so it must be fixed.
Why correct for SOC and temperature?
Resistance rises at low SOC and low temperature, so without correction or fixed conditions those effects would look like ageing.
Why use a public dataset?
One cell will not age significantly in a semester. A public ageing dataset shows how the indicator behaves over the full life.