Detect Disconnected Cells in Battery Module
This example shows how to detect disconnected cells in a battery module. Cells can disconnect due to faulty wiring, corrosion, or physical damage to the cell. To prevent further damage to the battery pack, the battery management system (BMS) must detect the disconnected cells and take appropriate action.
In this example, you first use the Battery Builder to create a Simscape(TM) model for a battery module. Then you define a disconnected cell fault for a cell in the module. Finally, you detect the disconnected cell with the Battery Cell Contact Monitoring block.
Build Model for Battery Module
In this example, the cells of the battery module have a cylindrical geometry. The Battery Equivalent Circuit block represents the cells. To create a Cell
object, use the batteryCell
function.
cylindricalCell = batteryCell(batteryCylindricalGeometry);
cylindricalCell.CellModelOptions.CellModelBlockPath = "batt_lib/Cells/Battery Equivalent Circuit";
Each parallel assembly comprises 30 cells, geometrically arranged in three rows. To create a ParallelAssembly
object with these properties, use the batteryParallelAssembly
function.
parallelAssembly = batteryParallelAssembly(cylindricalCell,30,Rows=3);
The module comprises 15 series-connected parallel assemblies. To create the Module
object, use the batteryModule
function. Additionally specify the optional name-value argument ModelResolution
as "Grouped" to customize the grouping strategy of the battery. For this use-case the behavior of the cells in the first parallel assembly are of particular interest, while the cells in the other parallel assemblies can be lumped together. Specify the grouping strategy with the optional name-value arguments SeriesGrouping
and ParallelGrouping
.
module = batteryModule(parallelAssembly,15,ModelResolution="Grouped",... SeriesGrouping=[1,14],ParallelGrouping=[30,1],StackingAxis="X");
Visualize the module with the batteryChart
function.
batteryChart(module);
Generate a Simscape component for the Module
object with the buildBattery
function. To export the block parameters into a script, specify the MaskParameters
name-value argument as "VariableNamesByType"
. To define the name of the exported library, specify the LibraryName
name-value argument.
libraryName = "moduleLibrary"; buildBattery(module,... "MaskParameters","VariableNamesByType", ... "LibraryName",libraryName);
Define Disconnected Cell Fault
To simulate the electric behavior of the module, integrate the generated block into a harness model and load the battery parameters.
modelName = "disconnectedCellDetection"; moduleLibraryPath = strcat(libraryName,"_lib/",module.Name); createDischargeHarnessModel(moduleLibraryPath,modelName); moduleLibrary_param;
Specify the battery current with a realistic discharge current and save the model.
load("DischargeCycle.mat","batteryCurrent"); currentSpecificationBlock = strcat(modelName,"/","Current"); set_param(currentSpecificationBlock,"VariableName","batteryCurrent"); set_param(modelName,"StopTime","100"); save_system(modelName);
To model the module behavior with a disconnected cell, specify an Additional Resistance
fault with a high resistance value of 1000 ohm for the specific cell. In this case you trigger the fault for the first cell in the first parallel assembly after 30 seconds.
batteryPath = strcat(modelName,"/Battery"); faultPath = strcat(batteryPath,"/Cell1(1)/Additional resistance"); fault = Simulink.fault.addFault(faultPath); faultModel = strcat(modelName,"_FaultModel"); addBehavior(fault,faultModel); fault.TriggerType = "Timed"; fault.StartTime = 30;
Simulate the model and visualize the resulting parallel assembly voltages. At the beginning of the simulation, the voltages of all parallel assemblies match. At t = 30s, the voltage of the first parallel assembly, which contains the faulted cell, falls below the voltage of the other parallel assemblies.
simout = sim(modelName); vParallelAssembly = simout.simlog.Battery.vParallelAssembly; vParallelAssemblyValues = vParallelAssembly.series.values; plot(vParallelAssembly.series.time,vParallelAssemblyValues(:,[1,2])); title("vParallelAssembly"); ylabel("vParallelAssembly, V"); xlabel("Time, s"); legend(["Parallel Assembly 1","Parallel Assembly 2"],Location="best"); xlim([20,40]);
Detect Disconnected Cell
To detect the parallel assembly that contains the disconnected cells, use the Battery Cell Contact Monitoring block. The BMS has access to the measured voltages of each parallel assembly. In this example, a Probe block models the interface that accesses the parallel assembly voltages variable (vParallelAssembly
). This interface then forwards the parallel assembly voltages to the Battery Cell Contact Monitoring block.
probeBlockPath = strcat(modelName,"/Probe"); add_block('nesl_utility/Probe',probeBlockPath,position=[450,125,510,175]); simscape.probe.setBoundBlock(probeBlockPath,batteryPath); simscape.probe.setVariables(probeBlockPath,"vParallelAssembly"); probePortHandles = get_param(probeBlockPath,"PortHandles"); contactMonitoringBlockPath = strcat(modelName,"/Battery Cell Contact Monitoring"); add_block("batt_sl_lib/Protection/Battery Cell Contact Monitoring",contactMonitoringBlockPath,position=[625,110,785,190]); contactMonitoringPortHandles = get_param(contactMonitoringBlockPath,"PortHandles"); set_param(contactMonitoringPortHandles.Outport(1),"DataLogging","on"); set_param(contactMonitoringPortHandles.Outport(2),"DataLogging","on"); add_line(modelName,probePortHandles.Outport,contactMonitoringPortHandles.Inport); terminator1BlockPath = strcat(modelName,"/Terminator1"); add_block("simulink/Sinks/Terminator",terminator1BlockPath,position=[900,120,920,140]); terminator1PortHandles = get_param(terminator1BlockPath,"PortHandles"); cellConnectionErrorLine = add_line(modelName,contactMonitoringPortHandles.Outport(1),terminator1PortHandles.Inport); set_param(cellConnectionErrorLine,"Name","CellConnectionError"); terminator2BlockPath = strcat(modelName,"/Terminator2"); add_block("simulink/Sinks/Terminator",terminator2BlockPath,position=[900,160,920,180]); terminator2PortHandles = get_param(terminator2BlockPath,"PortHandles"); cellConnectionSymptomLine = add_line(modelName,contactMonitoringPortHandles.Outport(2),terminator2PortHandles.Inport); set_param(cellConnectionSymptomLine,"Name","CellConnectionSymptom"); set_param(modelName,"ZoomFactor","FitSystem");
A disconnected cell in a parallel assembly results in a higher rate of voltage change compared to the other parallel assemblies. When the Battery Cell Contact Monitoring block detects this higher rate of voltage change, the CellConnectionsSymptom output is true
. If the value of this output remains true
for longer than the duration you specified in the Qualification time parameter of the block, the CellConnectionError output is true
.
You can tune the sensitivity of the block by using multiple parameters. Set the Threshold for voltage change detection (dV/dT) parameter to exclude measurements when the battery is in idle mode or close to idle mode. To identify the value for this parameter, simulate the battery without a disconnected cell under the representative drive cycle and identify the mean and the minimum voltage change during the simulation.
Simulink.fault.enable(faultPath,false);
simout = sim(modelName);
parallelAssemblyVoltages = simout.simlog.Battery.vParallelAssembly.series.values("V");
absoluteVoltageChange = abs(diff(parallelAssemblyVoltages(:,1)));
disp(min(absoluteVoltageChange));
2.1030e-06
disp(mean(absoluteVoltageChange));
0.0017
To consider the majority of the voltage changes under normal load, set the Threshold for voltage change detection (dV/dT) parameter to a value which is lower than the mean but higher than the minimum voltage change.
set_param(contactMonitoringBlockPath,"VoltageChangeDetectionThreshold","1e-5");
You can further tune the sensitivity of the block by using the Allowed voltage change peak-to-average ratio parameter. If the voltage of a parallel assembly is greater than the average parallel assembly voltage by more than this ratio, the measurement contributes towards a disconnected cell symptom. To estimate a value for this parameter, approximate a linear relationship between the number of connected cells in a parallel assembly and the parallel assembly voltage. With this approximation, you can calculate the relative increase of the voltage change that a single disconnected cell causes by using the inverse number of cells per parallel assembly.
disconnectedVoltageChange = 1/module.ParallelAssembly.NumParallelCells; disp(disconnectedVoltageChange);
0.0333
To improve the accuracy and account for nonlinear behavior of the parallel assembly voltage change, set the Allowed voltage change peak-to-average ratio to a value lower then the approximated one.
set_param(contactMonitoringBlockPath,"VoltageChangePar","0.015");
To specify the time required for a cell contact loss symptom to result in a cell contact error, set the Qualification Time (s) parameter.
set_param(contactMonitoringBlockPath,"QualTime","5");
Enable the disconnected cell fault, simulate the model, and plot the resulting CellConnectionSymptom
and CellConnectionError
.
Simulink.fault.enable(faultPath,true); simout = sim(modelName); legendLabels = "Parallel Assembly " + string(1:15); figure("Name","Cell Connection Symptom"); simout.logsout.getElement("CellConnectionSymptom").Values.plot(); legend(legendLabels,Location="best");
figure("Name","Cell Connection Error"); simout.logsout.getElement("CellConnectionError").Values.plot(); legend(legendLabels,Location="best"); ylim([0 1]);
You can further tune the parameters depending on the requirements for the detection of the disconnected cell. Under these conditions, the block detects the cell connection error within 10 seconds from the introduction of the fault, which is acceptable.
To validate the parameterization, the simulation is run with a different discharge scenario, while the fault is again introduced at t = 30s. The disconnected cell is again correctly detected in the first parallel assembly.
load("DischargeCycle.mat","batteryCurrentValidation"); set_param(currentSpecificationBlock,"VariableName","batteryCurrentValidation"); simout = sim(modelName); figure("Name","Cell Connection Symptom"); simout.logsout.getElement("CellConnectionSymptom").Values.plot(); legend(legendLabels,Location="best");
figure("Name","Cell Connection Error"); simout.logsout.getElement("CellConnectionError").Values.plot(); legend(legendLabels,Location="best"); ylim([0 1]);