Battery nominal capacity estimation using Coulomb Counting

59 views (last 30 days)
Matteo Valentini on 16 Nov 2022
Hi all,
I'm trying to estimate the nominal capacity of a PV plant battery pack collecting SOC data from the BMS using current discharge. Once I've collected current, time and SOC data I put those data into matlab and use an optimization algorithm to evaluate the capacity using the following expression (in the attachment) and the following code:
%% Optimization phase
clear all;
clc;
%% Estimation procedure using LSQNONLIN with two possible approach evaluated
% in 'SOCestimation.m': (1) Estimate the C by comparing the REAL SOC (filtered)
% and the one evaluated with CC in each single point till the end; (2) Evaluate C as
% same as before but considering the specific EOD (End of Discharge) point.
% x = C_estimated for battery pack (React) in Ah
x = 5;
x0 = rand*[x];
% Capacity (x stands for unknown) lower and upper bounds
xlb=[1];
xub=[50];
% Setting the optimization alg.
options = optimset('MaxFunEvals',15000,'MaxIter',10,'TolFun',1e-100,'TolX',1e-100,'Algorithm', 'levenberg-marquardt','Display','iter-detailed', 'FinDiffType', 'central'); %'levenberg-marquardt'
[x,resnorm,residual,exitflag,output]=lsqnonlin(@SOCestimation, x0, [xlb], [], options);
---------------------------------------------------------------------------------------------
%% Soc estimation file
function [f] = SOCestimation(x)
%% Loading OCV curve (discharge curves at 200 W during 02/03 november)
%% Filtering the SOC_real from a stepped curve into a linear one (can be commented out)
%
% y = smooth(SOC, 1e100, 'moving');
% filt_len = 1;
% a = 1;
% b = (1/filt_len)*ones(1,filt_len);
% SOC_real_filtered = filter(b,a,y);
%% Evaluate SOC as a function of C in Ah (=x) and the difference between SOC real
% and calculated (Discharge current is negative)
SOC_estim = ((1-(1/(x*3600))*cumtrapz(Time, -Current))*100);
% Estimate the C by comparing the real SOC (filtered or not) with the Coulomb Counting one
% considering also the last SOC value (End of Discharge)
f=SOC_real-SOC_estim;
plot(Time,SOC_real,Time,SOC_estim)
legend({'Real SOC filtered from stepped function','SOC estimated studying the C'})
drawnow
end
The problem is that I'm analyzing different discharge curves (1kW, 200W, 2kW constant power discharge) and I'm obtaining always different nominal capacity:
• 16.06 Ah for 1kW discharge;
• 15.9 Ah for 200W discharge;
• 14.97 Ah for 2kW discharge.
From the datasheet I've got that this battery pack has 4.8 kWh initial capacity and 288V as nominal voltage so nominal initial capacity is 16.8Ah but during lifetime is reported that the nominal capacity is around 4.0 kWh and 4.4 kWh so 13.8Ah - 15.4 Ah.
Please..what is wrong with my code? I'm trying to estimate the maximum capacity of the battery in order to evaluate for example the state of health comparing it to a new battery pack.
Here's the expression used:
Matteo Valentini on 5 Dec 2022
Hi,
Using the expression presented above the aim is to evaluate that formula in order to match the real SOC (obtained from BMS data) with the one calculated estimating the nominal battery capacity (with CC). When the two plots are in match, the C_max is estimated.

Askic V on 17 Nov 2022
Hello Mateo,
I don't think there is a problem in your code. It seems that you used correct way to perform numerical integration.
I have examined your data with the following script:
clear all
clc
close all
subplot(3, 1, 1)
plot(Tempo, Corrente);
xlabel('Tempo')
ylabel('Corrente');
title('data\_R1\_15-11-2022');
clear % clear variable from previous load
subplot(3,1,2)
Tempo = Tempo_ext_R1;
plot(Tempo, Corrente);
xlabel('Tempo')
ylabel('Corrente');
title('R1\_02nov');
clear % clear variable from previous load
subplot(3,1,3)
Tempo = Tempo_ext_R1;
Corrente = Corrente_ext_R1;
plot(Tempo, Corrente);
xlabel('Tempo')
ylabel('Corrente');
title('R1\_19\_ott');
and the results are shown in the following figure. It seems that you have an unusual spikes in the current. So the difference can be because of the data you used for estimation.
Matteo Valentini on 17 Nov 2022
Looking at the SOC formulation, I thought that the nominal capacity is an intrinsic parameter of the battery, so the maximum amount of charge inside the battery itself should be the same in every experiments, or at least I'm not expecting a big change like in this case. For what I've seen, changing the discharge current will change the so called "C-rate" so the amount of time where the battery capacity can be used.
Thank you for your time :)

Askic V on 16 Nov 2022
Try to add the following line immediately before lsqnonlin call
rng default
I cannot test it myself, because your function use variable 'Time' that is not defined (perhaps global).
Matteo Valentini on 16 Nov 2022
I've tried this change, but unfortunately the results are the same..

Categories

Find more on Energy Storage in Help Center and File Exchange

R2022b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!