Skip to content
Snippets Groups Projects
Commit d8460af6 authored by uvos's avatar uvos
Browse files

Estimate soc based on charge curve

parent 152eb5d6
No related branches found
No related tags found
No related merge requests found
...@@ -85,6 +85,7 @@ class CellMeta: ...@@ -85,6 +85,7 @@ class CellMeta:
def __init__(self, cellid: int, globalstep: int, substep: int, charge_files: list[ChargeFile], total_cells: int): def __init__(self, cellid: int, globalstep: int, substep: int, charge_files: list[ChargeFile], total_cells: int):
closest_avg = ChargeFile.FindClosest(charge_files, globalstep, -1) closest_avg = ChargeFile.FindClosest(charge_files, globalstep, -1)
closest_charge = ChargeFile.FindClosest(charge_files, globalstep, cellid) closest_charge = ChargeFile.FindClosest(charge_files, globalstep, cellid)
if closest_charge is not None:
assert closest_charge.cell == cellid assert closest_charge.cell == cellid
self.charge_cycles = charge_cycles_at_step(globalstep, substep) if cellid not in non_charge_cycle_cell else 0 self.charge_cycles = charge_cycles_at_step(globalstep, substep) if cellid not in non_charge_cycle_cell else 0
...@@ -94,3 +95,4 @@ class CellMeta: ...@@ -94,3 +95,4 @@ class CellMeta:
self.last_cap = abs(closest_charge.capacity) if closest_charge is not None else -1 self.last_cap = abs(closest_charge.capacity) if closest_charge is not None else -1
self.last_cap_step = closest_charge.step if closest_charge is not None else -1 self.last_cap_step = closest_charge.step if closest_charge is not None else -1
self.thermal_range = cell_thermal_range[cellid] self.thermal_range = cell_thermal_range[cellid]
self.soc = ChargeFile.GetSoc(charge_files, globalstep, cellid, total_cells)
...@@ -20,12 +20,12 @@ def calc_capacity(charge_curve: list[dict]): ...@@ -20,12 +20,12 @@ def calc_capacity(charge_curve: list[dict]):
class ChargeFile: class ChargeFile:
def __init__(self, filename: str): def __init__(self, filename: str):
self.start_voltage = 0 self.start_voltage = 0.0
self.end_voltage = 0 self.end_voltage = 0.0
self.capacity = 0 self.capacity = 0.0
self.cell = -1 self.cell = -1
self.discharge = False self.discharge = False
self.current = 0 self.current = 0.0
self.full_cycle = False self.full_cycle = False
self.step = 0 self.step = 0
...@@ -54,11 +54,14 @@ class ChargeFile: ...@@ -54,11 +54,14 @@ class ChargeFile:
self.capacity = calc_capacity(charge_curve) self.capacity = calc_capacity(charge_curve)
self.full_cycle = self.start_voltage > 4.05 and self.end_voltage < 3.15 or self.start_voltage < 3.15 and self.end_voltage > 4.05 self.full_cycle = self.start_voltage > 4.05 and self.end_voltage < 3.15 or self.start_voltage < 3.15 and self.end_voltage > 4.05
def FindClosest(charge_files: list, step, cellid=-1, full_cycle=True): @staticmethod
def FindClosest(charge_files: list, step: int, cellid: int = -1, full_cycle=True, only_before=False):
closest_file = None closest_file = None
for charge_file in charge_files: for charge_file in charge_files:
if charge_file.cell != cellid: if charge_file.cell != cellid:
continue continue
if only_before and charge_file.step > step:
continue
if not full_cycle or charge_file.full_cycle: if not full_cycle or charge_file.full_cycle:
if closest_file is not None: if closest_file is not None:
if abs(step - closest_file.step) > abs(step - charge_file.step): if abs(step - closest_file.step) > abs(step - charge_file.step):
...@@ -68,3 +71,36 @@ class ChargeFile: ...@@ -68,3 +71,36 @@ class ChargeFile:
if closest_file is None: if closest_file is None:
print(f"Warning could not find a charge {"full" if full_cycle else ""} file close to {step} for cell {cellid}") print(f"Warning could not find a charge {"full" if full_cycle else ""} file close to {step} for cell {cellid}")
return closest_file return closest_file
@staticmethod
def GetSoc(charge_files: list, step: int, cellid: int, cell_count: int) -> float:
common_closest_full = ChargeFile.FindClosest(charge_files, step, -1, True, True)
specific_closest_full = ChargeFile.FindClosest(charge_files, step, cellid, True, True)
if specific_closest_full is None and common_closest_full is None:
return -1.0
if common_closest_full is None:
closest_full = specific_closest_full
elif specific_closest_full is None:
closest_full = common_closest_full
elif step - specific_closest_full.step < step - common_closest_full.step:
closest_full = specific_closest_full
else:
closest_full = common_closest_full
charge_counter = 0.0
for charge_file in charge_files:
if charge_file.step <= step and charge_file.step > closest_full.step:
if charge_file.cell == -1:
charge_counter += charge_file.capacity / cell_count
else:
charge_counter += charge_file.capacity
full_cap = closest_full.capacity
if closest_full.cell == -1:
full_cap = full_cap / cell_count
soc = abs(charge_counter) / abs(full_cap)
return soc
...@@ -10,7 +10,6 @@ if __name__ == "__main__": ...@@ -10,7 +10,6 @@ if __name__ == "__main__":
parser = argparse.ArgumentParser("KissExpiramentCreateDataset") parser = argparse.ArgumentParser("KissExpiramentCreateDataset")
parser.add_argument('--data', '-d', required=True, help="Data input directory") parser.add_argument('--data', '-d', required=True, help="Data input directory")
parser.add_argument('--out', '-o', required=True, help="output directory") parser.add_argument('--out', '-o', required=True, help="output directory")
parser.add_argument('--cell_count', '-c', type=int, required=True, help="number of active cells")
args = parser.parse_args() args = parser.parse_args()
filenames = [f for f in os.listdir(args.data) if os.path.isfile(os.path.join(args.data, f))] filenames = [f for f in os.listdir(args.data) if os.path.isfile(os.path.join(args.data, f))]
...@@ -28,19 +27,21 @@ if __name__ == "__main__": ...@@ -28,19 +27,21 @@ if __name__ == "__main__":
charge_files.append(ChargeFile(os.path.join(args.data, filename))) charge_files.append(ChargeFile(os.path.join(args.data, filename)))
cells = set() cells = set()
for filename in tqdm(spectra_filenames):
tokens = filename.split('.')[0].split('-')
cellid = int(tokens[1])
cells.add(cellid)
print(f"{len(cells)} cells where involved")
for filename in tqdm(spectra_filenames): for filename in tqdm(spectra_filenames):
tokens = filename.split('.')[0].split('-') tokens = filename.split('.')[0].split('-')
step = int(tokens[0]) step = int(tokens[0])
cellid = int(tokens[1]) cellid = int(tokens[1])
substep = int(tokens[2]) substep = int(tokens[2])
cells.add(cellid)
celldir = os.path.join(args.out, str(cellid)) celldir = os.path.join(args.out, str(cellid))
if not os.path.exists(celldir): if not os.path.exists(celldir):
os.makedirs(celldir) os.makedirs(celldir)
sf = SpectraFile(os.path.join(args.data, filename), cellid, step, substep, charge_files, args.cell_count) sf = SpectraFile(os.path.join(args.data, filename), cellid, step, substep, charge_files, len(cells))
sf.write(celldir) sf.write(celldir)
if len(cells) != int(args.cell_count):
print(f"INCORRECT CELL COUNT!! found {len(cells)} but expected {args.cell_count}")
...@@ -12,8 +12,8 @@ class SpectraFile: ...@@ -12,8 +12,8 @@ class SpectraFile:
self.step = step self.step = step
self.substep = substep self.substep = substep
self.filename = filename self.filename = filename
self.temperature = -1 self.temperature = -1.0
self.ocv = -1 self.ocv = -1.0
self.meta = CellMeta(cellid, step, substep, charge_files, total_cells) self.meta = CellMeta(cellid, step, substep, charge_files, total_cells)
self.filename = os.path.split(filename)[1] self.filename = os.path.split(filename)[1]
...@@ -26,9 +26,9 @@ class SpectraFile: ...@@ -26,9 +26,9 @@ class SpectraFile:
raise ParseError(f"file name and file content of SpectraFile {filename} do not match") raise ParseError(f"file name and file content of SpectraFile {filename} do not match")
def write(self, directory: str): def write(self, directory: str):
meta_dsc_string = "step, substep, cellid, temparature, ocv, charge_cycles, thermal_cycles, last_avg_cap, last_avg_step, last_cap, last_cap_step" meta_dsc_string = "step, substep, cellid, temparature, ocv, charge_cycles, thermal_cycles, last_avg_cap, last_avg_step, last_cap, last_cap_step, soc"
metastring = f"{self.step}, {self.substep}, {self.cellid}, {self.temperature}, {self.ocv}, {self.meta.charge_cycles}, {self.meta.thermal_cycles}, " metastring = f"{self.step}, {self.substep}, {self.cellid}, {self.temperature}, {self.ocv}, {self.meta.charge_cycles}, {self.meta.thermal_cycles}, "
metastring += f"{self.meta.last_avg_cap}, {self.meta.last_avg_cap_step}, {self.meta.last_cap}, {self.meta.last_cap_step}" metastring += f"{self.meta.last_avg_cap}, {self.meta.last_avg_cap_step}, {self.meta.last_cap}, {self.meta.last_cap_step}, {self.meta.soc}"
self.spectra.headerDescription = meta_dsc_string self.spectra.headerDescription = meta_dsc_string
self.spectra.header = metastring self.spectra.header = metastring
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment