Case Study — Battery Pack with Fault Using Arrays
Overview of the Model
This case study explains how you can use component arrays to model a battery pack consisting of multiple series-connected cells. It also shows how you can introduce a fault into one of the cells to see the impact on battery performance and cell temperatures. Both the number of cells and the position of the faulted cell are the top-level component parameters modifiable by the block user.
The case study is based on the Lithium-Ion Battery Pack with Fault Using Arrays example. To open the example model, at the MATLAB® command prompt, enter:
openExample('simscape/LithiumIonBatteryPackWithFaultUsingArraysExample')
The Battery Pack block is a composite component modeling an array of battery cells. The source files for this example are in the following namespace folder:
matlabroot/toolbox/physmod/simscape/supporting_files/example_libraries/+BatteryPack
where matlabroot
is the MATLAB root folder on your machine, as returned by entering
matlabroot
at the MATLAB command prompt.
The +BatteryPack
namespace contains the following files:
battery_cell.ssc
— Component file representing the individual battery cell. The source for this component is generated usingsubsystem2ssc
from the Lithium Cell 1RC subsystem in the Lithium Battery Cell - One RC-Branch Equivalent Circuit example.battery_pack.ssc
— Composite component that models the battery pack as an array ofbattery_cell
components.
component battery_pack % Battery Pack % This block models a scalable battery pack with faults using arrays. % Copyright 2019 The MathWorks, Inc. parameters Ncells = 20; % Number of series-connected cells cell_mass = {1, 'kg'}; % Cell mass cell_area = {0.1019, 'm^2'}; % Cell area h_conv = {5, 'W/(m^2 * K)'}; % Heat transfer coefficient cell_Cp_heat = {810.5328, 'J/(kg*K)'}; %Cell specific heat Qe_init = {15.6845, 'hr*A'}; %Initial cell charge deficit T_init = {293.15, 'K'}; % Initial cell temperature SOC_LUT = [0; .1; .25; .5; .75; .9; 1]; %SOC table breakpoints (Mx1 array) Temperature_LUT = {[278.15, 293.15, 313.15], 'K'}; %Temperature table breakpoints (1xN array) Capacity_LUT = {[28.0081, 27.625, 27.6392], 'hr*A'}; %Capacity (1xN table) Em_LUT = {[3.4966, 3.5057, 3.5148; 3.5519, 3.566, 3.5653; 3.6183, 3.6337, 3.6402; 3.7066, 3.7127, 3.7213; 3.9131, 3.9259, 3.9376; 4.0748, 4.0777, 4.0821; 4.1923, 4.1928, 4.193], 'V'}; %Em open-circuit voltage, Em (MxN table) R0_LUT = {[.0117, .0085, .009; .011, .0085, .009; .0114, .0087, .0092; .0107, .0082, .0088; .0107, .0083, .0091; .0113, .0085, .0089; .0116, .0085, .0089], 'Ohm'}; %R0 terminal resistance (MxN table) R1_LUT = {[.0109, .0029, .0013; .0069, .0024, .0012; .0047, .0026, .0013; .0034, .0016, .001; .0033, .0023, .0014; .0033, .0018, .0011; .0028, .0017, .0011], 'Ohm'}; %R1 cell resistance (MxN table) C1_LUT = {[1913.6, 12447, 30609; 4625.7, 18872, 32995; 23306, 40764, 47535; 10736, 18721, 26325; 18036, 33630, 48274; 12251, 18360, 26839; 9022.9, 23394, 30606], 'F'}; %C1 capacitance (MxN table) % Fault cell fault_cell_position = 10; %Fault cell position fault_cell_Capacity_LUT = {[28.0081, 27.625, 27.6392]*0.95, 'hr*A'}; %Fault cell capacity (1xN table) fault_cell_Em_LUT = {[3.4966, 3.5057, 3.5148; 3.5519, 3.566, 3.5653; 3.6183, 3.6337, 3.6402; 3.7066, 3.7127, 3.7213; 3.9131, 3.9259, 3.9376; 4.0748, 4.0777, 4.0821; 4.1923, 4.1928, 4.193]*0.90, 'V'}; %Fault cell Em open-circuit voltage, Em (MxN table) fault_cell_R0_LUT = {[.0117, .0085, .009; .011, .0085, .009; .0114, .0087, .0092; .0107, .0082, .0088; .0107, .0083, .0091; .0113, .0085, .0089; .0116, .0085, .0089]*5, 'Ohm'}; % Fault cell R0 terminal resistance (MxN table) fault_cell_R1_LUT = {[.0109, .0029, .0013; .0069, .0024, .0012; .0047, .0026, .0013; .0034, .0016, .001; .0033, .0023, .0014; .0033, .0018, .0011; .0028, .0017, .0011]*5, 'Ohm'}; % fault cell R1 cell resistance (MxN table) fault_cell_C1_LUT = {[1913.6, 12447, 30609; 4625.7, 18872, 32995; 23306, 40764, 47535; 10736, 18721, 26325; 18036, 33630, 48274; 12251, 18360, 26839; 9022.9, 23394, 30606]*0.95, 'F'}; % Fault cell C1 capacitance (MxN table) end nodes p = foundation.electrical.electrical; % +:top n = foundation.electrical.electrical; % -:bottom H = foundation.thermal.thermal; % H:bottom end variables(Access=protected) T = {ones(1,Ncells),'K'}; SOC = ones(1,Ncells); end outputs m = {ones(1,Ncells),'K'}; % m:top end for i =1:Ncells components(ExternalAccess=none) battery_cell(i) = BatteryPack.battery_cell(cell_mass=cell_mass,cell_Cp_heat=cell_Cp_heat,... C1_LUT=(if i==fault_cell_position,fault_cell_C1_LUT;else C1_LUT; end),... SOC_LUT=SOC_LUT,Temperature_LUT=Temperature_LUT,... Capacity_LUT=(if i==fault_cell_position,fault_cell_Capacity_LUT;else Capacity_LUT; end),... Em_LUT=(if i==fault_cell_position,fault_cell_Em_LUT;else Em_LUT; end),Qe_init=Qe_init,... R0_LUT=(if i==fault_cell_position,fault_cell_R0_LUT;else R0_LUT; end),... R1_LUT=(if i==fault_cell_position,fault_cell_R1_LUT;else R1_LUT; end),T_init.value=T_init); convection(i) = foundation.thermal.elements.convection(area=cell_area,heat_tr_coeff=h_conv); end connections connect(battery_cell(i).H,convection(i).B); connect(H,convection(i).A); end end connections connect(battery_cell(1).p,p); connect(battery_cell(Ncells).n,n); end equations assert(mod(Ncells, 1) == 0 && Ncells > 0, 'Number of series-connected cells must be a positive integer'); assert(mod(fault_cell_position, 1) == 0 && fault_cell_position > 0 && fault_cell_position <= Ncells , 'Fault cell position must be a positive integer less than or equal to Number of series-connected cells'); T == [battery_cell.T_init]; SOC == [battery_cell.SOC]; m == T; end for i=1:Ncells-1 components(ExternalAccess=none) conduction(i) = foundation.thermal.elements.conduction(area={1e-3,'m^2'},... th_cond={200,'W/(m*K)'}); end connections connect(battery_cell(i+1).p,battery_cell(i).n); connect(battery_cell(i).H,conduction(i).A); connect(battery_cell(i+1).H,conduction(i).B); end end end
This schematic represents the equivalent circuit for the composite component.
The composite component has two electrical nodes, p
and
n
, and one thermal node, H
:
nodes p = foundation.electrical.electrical; % +:top n = foundation.electrical.electrical; % -:bottom H = foundation.thermal.thermal; % H:bottom end
The component also has an output, m
, to output the temperature
data:
outputs m = {ones(1,Ncells),'K'}; % m:top end
Introducing the Fault
The fault is represented by changing the parameters for one of the battery cells, reducing both capacity and open-circuit voltage, and increasing the resistance values.
To account for the fault, top-level composite component parameters are divided in two
groups: generic parameters and those specific to the faulted cell. For example, cell mass is
the same for all cells. However, the capacitance of the faulted cell is different from all
the other cells, therefore it needs a separate fault_cell_Capacity_LUT
parameter, instead of the generic Capacity_LUT
.
parameters Ncells = 20; % Number of series-connected cells cell_mass = {1, 'kg'}; % Cell mass cell_area = {0.1019, 'm^2'}; % Cell area h_conv = {5, 'W/(m^2 * K)'}; % Heat transfer coefficient cell_Cp_heat = {810.5328, 'J/(kg*K)'}; %Cell specific heat Qe_init = {15.6845, 'hr*A'}; %Initial cell charge deficit T_init = {293.15, 'K'}; % Initial cell temperature SOC_LUT = [0; .1; .25; .5; .75; .9; 1]; %SOC table breakpoints (Mx1 array) Temperature_LUT = {[278.15, 293.15, 313.15], 'K'}; %Temperature table breakpoints (1xN array) Capacity_LUT = {[28.0081, 27.625, 27.6392], 'hr*A'}; %Capacity (1xN table) Em_LUT = {[3.4966, ... 4.1928, 4.193], 'V'}; %Em open-circuit voltage, Em (MxN table) R0_LUT = {[.0117, ... .0085, .0089], 'Ohm'}; %R0 terminal resistance (MxN table) R1_LUT = {[.0109, ... .0017, .0011], 'Ohm'}; %R1 cell resistance (MxN table) C1_LUT = {[1913.6, ... 23394, 30606], 'F'}; %C1 capacitance (MxN table) % Fault cell fault_cell_position = 10; %Fault cell position fault_cell_Capacity_LUT = {[28.0081, 27.625, 27.6392]*0.95, 'hr*A'}; %Fault cell capacity (1xN table) fault_cell_Em_LUT = {[3.4966, ... 4.1928, 4.193]*0.90, 'V'}; %Fault cell Em open-circuit voltage, Em (MxN table) fault_cell_R0_LUT = {[.0117, ... .0085, .0089]*5, 'Ohm'}; % Fault cell R0 terminal resistance (MxN table) fault_cell_R1_LUT = {[.0109, ... .0017, .0011]*5, 'Ohm'}; % fault cell R1 cell resistance (MxN table) fault_cell_C1_LUT = {[1913.6, ... 23394, 30606]*0.95, 'F'}; % Fault cell C1 capacitance (MxN table) end
Both the number of cells, Ncells
, and the position of the faulted
cell, fault_cell_position
, are top-level parameters of the composite
component, which means that they will be modifiable by the block user.
Declaring Arrays of Member Components
Declare an array of cells, with the number of elements defined by the
Ncells
parameter.
for i =1:Ncells components(ExternalAccess=none) battery_cell(i) = BatteryPack.battery_cell(cell_mass=cell_mass,cell_Cp_heat=cell_Cp_heat,... C1_LUT=(if i==fault_cell_position,fault_cell_C1_LUT;else C1_LUT; end),... SOC_LUT=SOC_LUT,Temperature_LUT=Temperature_LUT,... Capacity_LUT=(if i==fault_cell_position,fault_cell_Capacity_LUT;else Capacity_LUT; end),... Em_LUT=(if i==fault_cell_position,fault_cell_Em_LUT;else Em_LUT; end),Qe_init=Qe_init,... R0_LUT=(if i==fault_cell_position,fault_cell_R0_LUT;else R0_LUT; end),... R1_LUT=(if i==fault_cell_position,fault_cell_R1_LUT;else R1_LUT; end),T_init.value=T_init); end end
For each member, associate its parameters with the top-level parameters of the composite component. For the iterator value that corresponds to the faulted cell position, specify the faulted cell parameters instead of the respective generic ones, as needed. For example, all cells have the same cell mass:
cell_mass=cell_mass
However, the capacitance of the faulted cell is different from all the other cells,
therefore, for the iterator value that corresponds to the faulted cell position, assign the
Capacity_LUT
parameter of the cell to the
fault_cell_Capacity_LUT
parameter of the composite component, and for
all other cells assign it to Capacity_LUT
:
Capacity_LUT=(if i==fault_cell_position,fault_cell_Capacity_LUT;else Capacity_LUT; end)
An array of N
cells requires N
identical convections and N-1
identical conductions. These are
thermal components from the Foundation library.
for i =1:Ncells components(ExternalAccess=none) convection(i) = foundation.thermal.elements.convection(area=cell_area,heat_tr_coeff=h_conv); end end
for i=1:Ncells-1 components(ExternalAccess=none) conduction(i) = foundation.thermal.elements.conduction(area={1e-3,'m^2'},... th_cond={200,'W/(m*K)'}); end end
Connecting the Components
Use a for
-loop to connect all the electrical nodes of the cells in
series, by connecting the negative port of each cell (except the last one) to the positive
port of the next cell:
for i=1:Ncells-1 connections connect(battery_cell(i+1).p,battery_cell(i).n); end end
Then connect this internal chain to the two electrical nodes of the composite component:
connections connect(battery_cell(1).p,p); connect(battery_cell(Ncells).n,n); end
Use another for
-loop to connect thermal node H
of
each of the cells to node B
of its respective convection component, and
also to connect nodes A
of all the convection components to thermal node
H
of the composite component:
for i=1:Ncells connections connect(battery_cell(i).H,convection(i).B); connect(H,convection(i).A); end end
Finally, incorporate the thermal conduction elements by connecting node
A
to node H
of the previous cell and node
B
to node H
of the next cell:
for i=1:Ncells-1 connections connect(battery_cell(i).H,conduction(i).A); connect(battery_cell(i+1).H,conduction(i).B); end end
Outputting Data as a Numeric Array
The physical signal output port, m
, outputs the temperature data for
the battery pack as a multidimensional physical signal, composed of the temperature data for
each cell. The vector size is determined by the Ncells
parameter value.
outputs m = {ones(1,Ncells),'K'}; % m:top end
To get the temperature data from the array of components, use the
equations
section. Declare the variable
T
as protected, because public variables cannot reference parameters,
and then use this variable to extract the temperature values from the member cells.
variables(Access=protected) T = {ones(1,Ncells),'K'}; end equations T == [battery_cell.T_init]; m == T; end
Indexing into member component variables, battery_cell.T_init
,
returns a comma-separated list. You can then concatenate the comma-separated list into a
numeric array, [battery_cell.T_init]
, and use it in the component
equations. For more information, see How to Use Comma-Separated Lists.
Battery Pack Block
The Battery Pack block generated from this composite component has two electrical ports, + and -, a thermal port, H, and a physical signal output port, m. The parameters modifiable through the block interface include the number of cells in the battery pack and the position of the faulted cell. The block user can modify the parameters of the faulted cell to see the impact of the fault on battery performance and cell temperatures.