Battery nominal capacity estimation using Coulomb Counting

8 次查看(过去 30 天)
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:
  5 个评论
MAHENDRAN A
MAHENDRAN A 2022-11-29
Bro, Im too developing SOC estimation model using coulomb counting and kalman filter method. And based on what you asked, I too have doubt on this.
Can you explain me about this topic Battery nominal capacity estimation using Coulomb Counting
slow_hand
slow_hand 2022-12-5
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
Askic V 2022-11-17
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
load data_R1_15-11-2022.mat
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)
load R1_02_nov.mat
Tempo = Tempo_ext_R1;
plot(Tempo, Corrente);
xlabel('Tempo')
ylabel('Corrente');
title('R1\_02nov');
clear % clear variable from previous load
subplot(3,1,3)
load R1_19_ott.mat
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.
  3 个评论
Askic V
Askic V 2022-11-17
Just out of curiosity, why do you think this is an error, if you integrate the real measured data?
I have found this info:
If the battery is being discharged very quickly (i.e., the discharge current is high), then the amount of energy that can be extracted from the battery is reduced and the battery capacity is lower.
The source:
So your estimation based on integration of real data confirm this.
slow_hand
slow_hand 2022-11-17
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.
But the text you've linked talks about lower battery capacity in this case, so probably I'm wrong. I'm going to investigate more about this.
Thank you for your time :)

请先登录,再进行评论。

更多回答(1 个)

Askic V
Askic V 2022-11-16
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).
  1 个评论
slow_hand
slow_hand 2022-11-16
Thank you for the answer. I've added the data, sorry for forgetting about it.
I've tried this change, but unfortunately the results are the same..

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Estimators​ 的更多信息

产品


版本

R2022b

Community Treasure Hunt

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

Start Hunting!

Translated by