Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split battery EOD #404

Open
wants to merge 5 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion examples/sim.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

def run_example():
# Step 1: Create a model object
batt = Battery()
batt = Battery(process_noise_dist='none')

# Step 2: Define future loading function
def future_loading(t, x=None):
Expand Down Expand Up @@ -64,6 +64,7 @@ def future_loading(t, x=None):
# Note that even though the step size is 2, the odd points in the save frequency are met perfectly, dt is adjusted automatically to capture the save points

simulated_results.outputs.plot()
simulated_results.event_states.plot()

if isinstance(batt, BatteryElectroChem):
# Plotting max current with time
Expand Down
49 changes: 40 additions & 9 deletions src/prog_models/models/battery_electrochem.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ def update_v0(params: dict) -> dict:
'v0': Vep - Ven - params['x0']['Vo'] - params['x0']['Vsn'] - params['x0']['Vsp']
}

def update_QEOD(params: dict) -> dict:
# Update the charge after which the battery is considered discharged
return {
'QEOD': params['qnMax']*params['SOC_Thresh']
}

def update_qSBmax(params : dict) -> dict:
# max charge at surface, bulk (pos and neg)
return {
Expand All @@ -164,10 +170,14 @@ class BatteryElectroChemEOD(PrognosticsModel):
Vectorized prognostics :term:`model` for a battery, represented by an electrochemical equations as described in the following paper:
`M. Daigle and C. Kulkarni, "Electrochemistry-based Battery Modeling for Prognostics," Annual Conference of the Prognostics and Health Management Society 2013, pp. 249-261, New Orleans, LA, October 2013. https://papers.phmsociety.org/index.php/phmconf/article/view/2252`. This model predicts the end of discharge event.

This model has 2 primary events: discharge and lowvoltage, and a third EOD event that combines the two (kept for backwards compatability). Discharge event occurs when the battery is fully discharged (i.e., there is no charge remaining), while lowvoltage occurs when the voltage falls below an acceptable threshold.

The default model parameters included are for Li-ion batteries, specifically 18650-type cells. Experimental discharge curves for these cells can be downloaded from the `Prognostics Center of Excellence Data Repository https://ti.arc.nasa.gov/tech/dash/groups/pcoe/prognostic-data-repository/`.

:term:`Events<event>`: (1)
EOD: End of Discharge
:term:`Events<event>`: (3)
EOD: Original End of discharge event - combination of discharge and lowvoltage events
discharge: Battery is fully discharged
lowvoltage: Voltage falls below minimum threshold

:term:`Inputs/Loading<input>`: (1)
i: Current draw on the battery
Expand Down Expand Up @@ -246,14 +256,23 @@ class BatteryElectroChemEOD(PrognosticsModel):
Redlich-Kister parameter (- electrode)
VEOD : float
End of Discharge Voltage Threshold
SOC_Thresh : float
Percentage of initial qnB + qnS (0-1) that defines the minimum charge, after which the battery is considered discharged. Used to calculate apparent soc.
VDropoff : float
Voltage (above VEOD) at which voltage starts playing a role in EOD event state
x0 : dict[str, float]
Initial :term:`state`
v0 : Initial voltage

See Also
--------
BatteryElectroChemEOL, BatteryElectroChem, BatteryElectroChemEODEOL

Note
--------
lowvoltage can occur either when the battery is discharge (i.e., discharge :term:`event state` is approaching 0), or when there is a high current draw. If the discharge :term:`event state` is still high and the lowvoltage :term:`event` is occuring, decreasing the current draw will fix the lowvoltage issue. Maximum sustainable current without triggering lowvoltage decreases as the battery discharges.
"""
events = ['EOD']
events = ['discharge', 'lowvoltage', 'EOD']
inputs = ['i']
states = ['tb', 'Vo', 'Vsn', 'Vsp', 'qnB', 'qnS', 'qpB', 'qpS']
outputs = ['t', 'v']
Expand Down Expand Up @@ -300,9 +319,9 @@ class BatteryElectroChemEOD(PrognosticsModel):

'process_noise': 1e-3,

# End of discharge voltage threshold
'VEOD': 3.0,
'VDropoff': 0.1 # Voltage above EOD after which voltage will be considered in SOC calculation
'SOC_Thresh': 0.05,
'VDropoff': 0.1
}

state_limits = {
Expand All @@ -314,7 +333,14 @@ class BatteryElectroChemEOD(PrognosticsModel):
}

param_callbacks = { # Callbacks for derived parameters
'An': [update_v0],
'Ap': [update_v0],
'x0': [update_v0],
'qnMax': [update_QEOD],
'qSMax': [update_v0],
'qMobile': [update_qmax],
'U0n': [update_v0],
'U0p': [update_v0],
'VolSFraction': [update_vols, update_qpSBmin, update_qpSBmax, update_qSBmax],
'Vol': [update_vols],
'qMax': [update_qpmin, update_qpmax, update_qpSBmin, update_qpSBmax, update_qnmin, update_qnmax, update_qpSBmin, update_qpSBmax, update_qSBmax],
Expand Down Expand Up @@ -493,10 +519,13 @@ def event_state(self, x : dict) -> dict:
Vep = params['U0p'] + R*x['tb']/F*np.log(one_minus_xpS/xpS) + sum(VepParts)
v = Vep - Ven - x['Vo'] - x['Vsn'] - x['Vsp']

charge_EOD = (x['qnS'] + x['qnB'])/self.parameters['qnMax']
voltage_EOD = (v - self.parameters['VEOD'])/self.parameters['VDropoff']
charge_EOD = (x['qnS'] + x['qnB']-params['QEOD'])/(self.parameters['qnMax']-params['QEOD'])
voltage_EOD = (v - self.parameters['VEOD'])/(self.parameters['v0'] - self.parameters['VEOD'])
voltage_EOD_old = (v - self.parameters['VEOD'])/self.parameters['VDropoff']
return {
'EOD': min(charge_EOD, voltage_EOD)
'discharge': max(min(charge_EOD, 1),0),
'lowvoltage': max(min(voltage_EOD, 1),0),
'EOD': max(min(min(charge_EOD, voltage_EOD_old), 1), 0)
}

def output(self, x : dict):
Expand Down Expand Up @@ -557,7 +586,9 @@ def threshold_met(self, x : dict) -> dict:

# Return true if voltage is less than the voltage threshold
return {
'EOD': z['v'] < self.parameters['VEOD']
'EOD': z['v'] < self.parameters['VEOD'],
'discharge': (x['qnB'] + x['qnS']) < self.parameters['QEOD'],
'lowvoltage': z['v'] < self.parameters['VEOD']
}


Expand Down