MainCode/adalm1000_logger.py aktualisiert
Cycling added
Ich werde eine neue Variable continuous_mode hinzufügen, um den kontinuierlichen Betrieb zu steuern
Die run_test_sequence() Methode wird modifiziert, um in einer Schleife zu laufen
Die stop_test() Methode wird erweitert, um den kontinuierlichen Modus zu beenden
(Deepseek)
This commit is contained in:
parent
516e2a44b2
commit
07b86664c0
@ -37,6 +37,7 @@ class BatteryTester:
|
|||||||
self.session_active = False
|
self.session_active = False
|
||||||
self.measuring = False
|
self.measuring = False
|
||||||
self.test_running = False
|
self.test_running = False
|
||||||
|
self.continuous_mode = False # New flag for continuous cycling
|
||||||
self.interval = 0.1 # Measurement interval
|
self.interval = 0.1 # Measurement interval
|
||||||
self.log_dir = os.path.expanduser("~/adalm1000/logs")
|
self.log_dir = os.path.expanduser("~/adalm1000/logs")
|
||||||
os.makedirs(self.log_dir, exist_ok=True)
|
os.makedirs(self.log_dir, exist_ok=True)
|
||||||
@ -53,6 +54,7 @@ class BatteryTester:
|
|||||||
self.capacity_ah = tk.DoubleVar(value=0.0)
|
self.capacity_ah = tk.DoubleVar(value=0.0)
|
||||||
self.charge_capacity = tk.DoubleVar(value=0.0) # Added for charge capacity tracking
|
self.charge_capacity = tk.DoubleVar(value=0.0) # Added for charge capacity tracking
|
||||||
self.coulomb_efficiency = tk.DoubleVar(value=0.0) # Added for efficiency calculation
|
self.coulomb_efficiency = tk.DoubleVar(value=0.0) # Added for efficiency calculation
|
||||||
|
self.cycle_count = tk.IntVar(value=0) # Added for cycle counting
|
||||||
|
|
||||||
# Data buffers
|
# Data buffers
|
||||||
self.time_data = deque()
|
self.time_data = deque()
|
||||||
@ -122,6 +124,7 @@ class BatteryTester:
|
|||||||
("Discharge Capacity", "Ah"),
|
("Discharge Capacity", "Ah"),
|
||||||
("Charge Capacity", "Ah"),
|
("Charge Capacity", "Ah"),
|
||||||
("Coulomb Eff.", "%"),
|
("Coulomb Eff.", "%"),
|
||||||
|
("Cycle Count", ""),
|
||||||
]
|
]
|
||||||
|
|
||||||
for i, (label, unit) in enumerate(measurement_labels):
|
for i, (label, unit) in enumerate(measurement_labels):
|
||||||
@ -145,6 +148,8 @@ class BatteryTester:
|
|||||||
self.charge_capacity_label = value_label
|
self.charge_capacity_label = value_label
|
||||||
elif i == 6:
|
elif i == 6:
|
||||||
self.efficiency_label = value_label
|
self.efficiency_label = value_label
|
||||||
|
elif i == 7:
|
||||||
|
self.cycle_label = value_label
|
||||||
|
|
||||||
# Control area
|
# Control area
|
||||||
controls_frame = ttk.Frame(self.content_frame)
|
controls_frame = ttk.Frame(self.content_frame)
|
||||||
@ -185,6 +190,10 @@ class BatteryTester:
|
|||||||
self.stop_button = ttk.Button(button_frame, text="STOP TEST", command=self.stop_test, style='Warning.TButton', state=tk.DISABLED)
|
self.stop_button = ttk.Button(button_frame, text="STOP TEST", command=self.stop_test, style='Warning.TButton', state=tk.DISABLED)
|
||||||
self.stop_button.pack(side=tk.TOP, pady=5)
|
self.stop_button.pack(side=tk.TOP, pady=5)
|
||||||
|
|
||||||
|
# Continuous mode checkbox
|
||||||
|
self.continuous_var = tk.BooleanVar(value=True)
|
||||||
|
ttk.Checkbutton(button_frame, text="Continuous Mode", variable=self.continuous_var).pack(side=tk.TOP, pady=5)
|
||||||
|
|
||||||
# Plot area
|
# Plot area
|
||||||
self.plot_frame = ttk.Frame(self.content_frame)
|
self.plot_frame = ttk.Frame(self.content_frame)
|
||||||
self.plot_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=(0, 5))
|
self.plot_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=(0, 5))
|
||||||
@ -327,7 +336,8 @@ class BatteryTester:
|
|||||||
self.test_phase.get(),
|
self.test_phase.get(),
|
||||||
f"{self.capacity_ah.get():.4f}",
|
f"{self.capacity_ah.get():.4f}",
|
||||||
f"{self.charge_capacity.get():.4f}",
|
f"{self.charge_capacity.get():.4f}",
|
||||||
f"{self.coulomb_efficiency.get():.1f}"
|
f"{self.coulomb_efficiency.get():.1f}",
|
||||||
|
f"{self.cycle_count.get()}"
|
||||||
])
|
])
|
||||||
|
|
||||||
time.sleep(max(0.05, self.interval))
|
time.sleep(max(0.05, self.interval))
|
||||||
@ -351,6 +361,9 @@ class BatteryTester:
|
|||||||
if self.c_rate.get() <= 0:
|
if self.c_rate.get() <= 0:
|
||||||
raise ValueError("C-rate must be positive")
|
raise ValueError("C-rate must be positive")
|
||||||
|
|
||||||
|
# Set continuous mode based on checkbox
|
||||||
|
self.continuous_mode = self.continuous_var.get()
|
||||||
|
|
||||||
# Reset timing for new test
|
# Reset timing for new test
|
||||||
self.measurement_start_time = time.time()
|
self.measurement_start_time = time.time()
|
||||||
self.test_start_time = time.time()
|
self.test_start_time = time.time()
|
||||||
@ -369,6 +382,7 @@ class BatteryTester:
|
|||||||
self.capacity_ah.set(0.0)
|
self.capacity_ah.set(0.0)
|
||||||
self.charge_capacity.set(0.0)
|
self.charge_capacity.set(0.0)
|
||||||
self.coulomb_efficiency.set(0.0)
|
self.coulomb_efficiency.set(0.0)
|
||||||
|
self.cycle_count.set(0)
|
||||||
|
|
||||||
# Setup new log file
|
# Setup new log file
|
||||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||||
@ -376,7 +390,7 @@ class BatteryTester:
|
|||||||
|
|
||||||
with open(self.filename, 'w', newline='') as f:
|
with open(self.filename, 'w', newline='') as f:
|
||||||
writer = csv.writer(f)
|
writer = csv.writer(f)
|
||||||
writer.writerow(["Time(s)", "Voltage(V)", "Current(A)", "Phase", "Discharge_Capacity(Ah)", "Charge_Capacity(Ah)", "Coulomb_Eff(%)"])
|
writer.writerow(["Time(s)", "Voltage(V)", "Current(A)", "Phase", "Discharge_Capacity(Ah)", "Charge_Capacity(Ah)", "Coulomb_Eff(%)", "Cycle"])
|
||||||
|
|
||||||
# Start test thread
|
# Start test thread
|
||||||
self.test_running = True
|
self.test_running = True
|
||||||
@ -406,6 +420,7 @@ class BatteryTester:
|
|||||||
def stop_test(self):
|
def stop_test(self):
|
||||||
"""Stop the current test"""
|
"""Stop the current test"""
|
||||||
self.test_running = False
|
self.test_running = False
|
||||||
|
self.continuous_mode = False # Always stop continuous mode when stop is pressed
|
||||||
self.measuring = False
|
self.measuring = False
|
||||||
if hasattr(self, 'dev'):
|
if hasattr(self, 'dev'):
|
||||||
self.dev.channels['A'].constant(0) # Set zero current
|
self.dev.channels['A'].constant(0) # Set zero current
|
||||||
@ -432,187 +447,213 @@ class BatteryTester:
|
|||||||
window.geometry(f'{width}x{height}+{x}+{y}')
|
window.geometry(f'{width}x{height}+{x}+{y}')
|
||||||
|
|
||||||
def run_test_sequence(self):
|
def run_test_sequence(self):
|
||||||
"""Run the complete test sequence (discharge-rest-charge-rest-discharge) once"""
|
"""Run the complete test sequence (discharge-rest-charge-rest-discharge) in a loop"""
|
||||||
try:
|
try:
|
||||||
# Calculate target current
|
# Calculate target current
|
||||||
test_current = self.c_rate.get() * self.capacity.get()
|
test_current = self.c_rate.get() * self.capacity.get()
|
||||||
|
|
||||||
# 1. Initial Discharge (to known state)
|
while self.test_running and (self.continuous_mode or self.cycle_count.get() == 0):
|
||||||
#self.test_phase.set("Initial Discharge")
|
# Increment cycle count
|
||||||
#self.status_var.set(f"Discharging to {self.discharge_cutoff.get()}V @ {test_current:.3f}A")
|
self.cycle_count.set(self.cycle_count.get() + 1)
|
||||||
|
self.root.after(0, lambda: self.cycle_label.config(text=str(self.cycle_count.get())))
|
||||||
|
|
||||||
#self.measuring = True
|
# 1. Initial Discharge (to known state)
|
||||||
#self.dev.channels['A'].mode = pysmu.Mode.SIMV
|
self.test_phase.set("Initial Discharge")
|
||||||
#self.dev.channels['A'].constant(-test_current)
|
self.status_var.set(f"Discharging to {self.discharge_cutoff.get()}V @ {test_current:.3f}A")
|
||||||
self.dev.channels['B'].mode = pysmu.Mode.HI_Z
|
|
||||||
|
|
||||||
#while self.test_running:
|
self.measuring = True
|
||||||
# if not self.voltage_data:
|
self.dev.channels['A'].mode = pysmu.Mode.SIMV
|
||||||
# time.sleep(0.1)
|
self.dev.channels['A'].constant(-test_current)
|
||||||
# continue
|
self.dev.channels['B'].mode = pysmu.Mode.HI_Z
|
||||||
|
|
||||||
# current_voltage = self.voltage_data[-1]
|
while self.test_running:
|
||||||
# current_current = abs(self.current_data[-1])
|
if not self.voltage_data:
|
||||||
# self.status_var.set(
|
time.sleep(0.1)
|
||||||
# f"Discharging: {current_voltage:.3f}V / {self.discharge_cutoff.get()}V | "
|
continue
|
||||||
# f"Current: {current_current:.3f}A | "
|
|
||||||
# f"Time: {self.format_time(self.time_data[-1])}"
|
|
||||||
# )
|
|
||||||
|
|
||||||
# if current_voltage <= self.discharge_cutoff.get():
|
current_voltage = self.voltage_data[-1]
|
||||||
# break
|
current_current = abs(self.current_data[-1])
|
||||||
# time.sleep(0.5)
|
self.status_var.set(
|
||||||
|
f"Discharging: {current_voltage:.3f}V / {self.discharge_cutoff.get()}V | "
|
||||||
|
f"Current: {current_current:.3f}A | "
|
||||||
|
f"Time: {self.format_time(self.time_data[-1])}"
|
||||||
|
)
|
||||||
|
|
||||||
#if not self.test_running:
|
if current_voltage <= self.discharge_cutoff.get():
|
||||||
# return
|
break
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
# 2. Rest period after initial discharge
|
if not self.test_running:
|
||||||
#self.test_phase.set("Resting (Post-Discharge)")
|
return
|
||||||
#self.measuring = False
|
|
||||||
#self.dev.channels['A'].mode = pysmu.Mode.HI_Z
|
|
||||||
#self.dev.channels['A'].constant(0)
|
|
||||||
|
|
||||||
#rest_end_time = time.time() + (self.rest_time.get() * 3600)
|
# 2. Rest period after initial discharge
|
||||||
#while time.time() < rest_end_time and self.test_running:
|
self.test_phase.set("Resting (Post-Discharge)")
|
||||||
# time_left = max(0, rest_end_time - time.time())
|
self.measuring = False
|
||||||
# self.status_var.set(
|
self.dev.channels['A'].mode = pysmu.Mode.HI_Z
|
||||||
# f"Resting after discharge | "
|
self.dev.channels['A'].constant(0)
|
||||||
# f"Time left: {self.format_time(time_left)} | "
|
|
||||||
# f"Next: Charging to {self.charge_cutoff.get()}V"
|
|
||||||
# )
|
|
||||||
# time.sleep(1)
|
|
||||||
|
|
||||||
#if not self.test_running:
|
rest_end_time = time.time() + (self.rest_time.get() * 3600)
|
||||||
# return
|
while time.time() < rest_end_time and self.test_running:
|
||||||
|
time_left = max(0, rest_end_time - time.time())
|
||||||
|
self.status_var.set(
|
||||||
|
f"Resting after discharge | "
|
||||||
|
f"Time left: {self.format_time(time_left)} | "
|
||||||
|
f"Next: Charging to {self.charge_cutoff.get()}V"
|
||||||
|
)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
# 3. Charge (constant current)
|
if not self.test_running:
|
||||||
self.test_phase.set("Charge")
|
return
|
||||||
self.status_var.set(f"Charging to {self.charge_cutoff.get()}V @ {test_current:.3f}A")
|
|
||||||
|
|
||||||
self.measuring = True
|
# 3. Charge (constant current)
|
||||||
self.dev.channels['A'].mode = pysmu.Mode.SIMV
|
self.test_phase.set("Charge")
|
||||||
self.dev.channels['A'].constant(test_current)
|
self.status_var.set(f"Charging to {self.charge_cutoff.get()}V @ {test_current:.3f}A")
|
||||||
self.charge_capacity.set(0.0)
|
|
||||||
target_voltage = self.charge_cutoff.get()
|
|
||||||
self.last_update_time = time.time()
|
|
||||||
|
|
||||||
while self.test_running:
|
self.measuring = True
|
||||||
if not self.voltage_data:
|
self.dev.channels['A'].mode = pysmu.Mode.SIMV
|
||||||
time.sleep(0.1)
|
self.dev.channels['A'].constant(test_current)
|
||||||
continue
|
self.charge_capacity.set(0.0)
|
||||||
|
target_voltage = self.charge_cutoff.get()
|
||||||
|
self.last_update_time = time.time()
|
||||||
|
|
||||||
current_voltage = self.voltage_data[-1]
|
while self.test_running:
|
||||||
measured_current = abs(self.current_data[-1])
|
if not self.voltage_data:
|
||||||
time_elapsed = time.time() - self.last_update_time
|
time.sleep(0.1)
|
||||||
|
continue
|
||||||
|
|
||||||
# Update charge capacity
|
current_voltage = self.voltage_data[-1]
|
||||||
now = time.time()
|
measured_current = abs(self.current_data[-1])
|
||||||
delta_t = now - self.last_update_time
|
time_elapsed = time.time() - self.last_update_time
|
||||||
self.last_update_time = now
|
|
||||||
self.charge_capacity.set(self.charge_capacity.get() + measured_current * delta_t / 3600)
|
|
||||||
|
|
||||||
|
# Update charge capacity
|
||||||
|
now = time.time()
|
||||||
|
delta_t = now - self.last_update_time
|
||||||
|
self.last_update_time = now
|
||||||
|
self.charge_capacity.set(self.charge_capacity.get() + measured_current * delta_t / 3600)
|
||||||
|
|
||||||
|
self.status_var.set(
|
||||||
|
f"Charging: {current_voltage:.3f}V / {target_voltage}V | "
|
||||||
|
f"Current: {measured_current:.3f}A | "
|
||||||
|
f"Capacity: {self.charge_capacity.get():.4f}Ah | "
|
||||||
|
f"Time: {self.time_data[-1]:.1f}s"
|
||||||
|
)
|
||||||
|
|
||||||
|
if current_voltage >= target_voltage:
|
||||||
|
break
|
||||||
|
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
if not self.test_running:
|
||||||
|
return
|
||||||
|
|
||||||
|
# 4. Rest period after charge
|
||||||
|
self.test_phase.set("Resting (Post-Charge)")
|
||||||
|
self.measuring = False
|
||||||
|
self.dev.channels['A'].mode = pysmu.Mode.HI_Z
|
||||||
|
self.dev.channels['A'].constant(0)
|
||||||
|
|
||||||
|
rest_end_time = time.time() + (self.rest_time.get() * 3600)
|
||||||
|
while time.time() < rest_end_time and self.test_running:
|
||||||
|
time_left = max(0, rest_end_time - time.time())
|
||||||
|
self.status_var.set(
|
||||||
|
f"Resting after charge | "
|
||||||
|
f"Time left: {time_left/60:.1f} min | "
|
||||||
|
f"Next: Final discharge to {self.discharge_cutoff.get()}V"
|
||||||
|
)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
if not self.test_running:
|
||||||
|
return
|
||||||
|
|
||||||
|
# 5. Final Discharge (capacity measurement)
|
||||||
|
self.test_phase.set("Final Discharge")
|
||||||
|
self.status_var.set(f"Final discharge to {self.discharge_cutoff.get()}V @ {test_current:.3f}A")
|
||||||
|
|
||||||
|
self.measuring = True
|
||||||
|
self.dev.channels['A'].mode = pysmu.Mode.SIMV
|
||||||
|
self.dev.channels['A'].constant(-test_current)
|
||||||
|
self.capacity_ah.set(0.0)
|
||||||
|
self.last_update_time = time.time()
|
||||||
|
|
||||||
|
while self.test_running:
|
||||||
|
if not self.current_data:
|
||||||
|
time.sleep(0.1)
|
||||||
|
continue
|
||||||
|
|
||||||
|
current_voltage = self.voltage_data[-1]
|
||||||
|
current_current = abs(self.current_data[-1])
|
||||||
|
|
||||||
|
# Calculate discharged capacity
|
||||||
|
now = time.time()
|
||||||
|
delta_t = now - self.last_update_time
|
||||||
|
self.last_update_time = now
|
||||||
|
self.capacity_ah.set(self.capacity_ah.get() + current_current * delta_t / 3600)
|
||||||
|
|
||||||
|
self.status_var.set(
|
||||||
|
f"Discharging: {current_voltage:.3f}V / {self.discharge_cutoff.get()}V | "
|
||||||
|
f"Current: {current_current:.3f}A | "
|
||||||
|
f"Capacity: {self.capacity_ah.get():.4f}Ah | "
|
||||||
|
f"Time: {self.time_data[-1]:.1f}s"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check for discharge completion
|
||||||
|
if current_voltage <= self.discharge_cutoff.get():
|
||||||
|
break
|
||||||
|
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
# Calculate Coulomb efficiency
|
||||||
|
if self.charge_capacity.get() > 0:
|
||||||
|
efficiency = (self.capacity_ah.get() / self.charge_capacity.get()) * 100
|
||||||
|
self.coulomb_efficiency.set(efficiency)
|
||||||
|
|
||||||
|
# Update GUI and show results
|
||||||
|
self.test_phase.set("Cycle Complete")
|
||||||
self.status_var.set(
|
self.status_var.set(
|
||||||
f"Charging: {current_voltage:.3f}V / {target_voltage}V | "
|
f"Cycle {self.cycle_count.get()} complete | "
|
||||||
f"Current: {measured_current:.3f}A | "
|
f"Discharge Capacity: {self.capacity_ah.get():.3f}Ah | "
|
||||||
f"Capacity: {self.charge_capacity.get():.4f}Ah | "
|
f"Charge Capacity: {self.charge_capacity.get():.3f}Ah | "
|
||||||
f"Time: {self.time_data[-1]:.1f}s"
|
f"Efficiency: {self.coulomb_efficiency.get():.1f}%"
|
||||||
)
|
)
|
||||||
|
|
||||||
if current_voltage >= target_voltage:
|
# Show summary dialog only for the first cycle or when stopping
|
||||||
break
|
if not self.continuous_mode or not self.test_running:
|
||||||
|
self.root.after(0, lambda: messagebox.showinfo("Cycle Complete",
|
||||||
|
f"Cycle {self.cycle_count.get()} complete\n\n"
|
||||||
|
f"Discharge Capacity: {self.capacity_ah.get():.3f}Ah\n"
|
||||||
|
f"Charge Capacity: {self.charge_capacity.get():.3f}Ah\n"
|
||||||
|
f"Coulomb Efficiency: {self.coulomb_efficiency.get():.1f}%\n\n"
|
||||||
|
f"({self.capacity_ah.get()/self.capacity.get()*100:.1f}% of rated capacity)"))
|
||||||
|
|
||||||
time.sleep(0.5)
|
# Write cycle summary to log file
|
||||||
|
self.write_cycle_summary()
|
||||||
|
|
||||||
if not self.test_running:
|
# Reset capacities for next cycle
|
||||||
return
|
self.capacity_ah.set(0.0)
|
||||||
|
self.charge_capacity.set(0.0)
|
||||||
|
|
||||||
# 4. Rest period after charge
|
# Check if we should continue with another cycle
|
||||||
self.test_phase.set("Resting (Post-Charge)")
|
if self.continuous_mode and self.test_running:
|
||||||
self.measuring = False
|
# Short rest between cycles
|
||||||
self.dev.channels['A'].mode = pysmu.Mode.HI_Z
|
rest_end_time = time.time() + (self.rest_time.get() * 3600)
|
||||||
self.dev.channels['A'].constant(0)
|
while time.time() < rest_end_time and self.test_running:
|
||||||
|
time_left = max(0, rest_end_time - time.time())
|
||||||
|
self.test_phase.set("Resting Between Cycles")
|
||||||
|
self.status_var.set(
|
||||||
|
f"Resting between cycles | "
|
||||||
|
f"Time left: {time_left/60:.1f} min | "
|
||||||
|
f"Next cycle will start soon"
|
||||||
|
)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
rest_end_time = time.time() + (self.rest_time.get() * 3600)
|
# Automatically stop the test after completion if not in continuous mode
|
||||||
while time.time() < rest_end_time and self.test_running:
|
if not self.continuous_mode:
|
||||||
time_left = max(0, rest_end_time - time.time())
|
self.root.after(0, self.stop_test)
|
||||||
self.status_var.set(
|
|
||||||
f"Resting after charge | "
|
|
||||||
f"Time left: {time_left/60:.1f} min | "
|
|
||||||
f"Next: Final discharge to {self.discharge_cutoff.get()}V"
|
|
||||||
)
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
if not self.test_running:
|
|
||||||
return
|
|
||||||
|
|
||||||
# 5. Final Discharge (capacity measurement)
|
|
||||||
self.test_phase.set("Final Discharge")
|
|
||||||
self.status_var.set(f"Final discharge to {self.discharge_cutoff.get()}V @ {test_current:.3f}A")
|
|
||||||
|
|
||||||
self.measuring = True
|
|
||||||
self.dev.channels['A'].mode = pysmu.Mode.SIMV
|
|
||||||
self.dev.channels['A'].constant(-test_current)
|
|
||||||
self.capacity_ah.set(0.0)
|
|
||||||
self.last_update_time = time.time()
|
|
||||||
|
|
||||||
while self.test_running:
|
|
||||||
if not self.current_data:
|
|
||||||
time.sleep(0.1)
|
|
||||||
continue
|
|
||||||
|
|
||||||
current_voltage = self.voltage_data[-1]
|
|
||||||
current_current = abs(self.current_data[-1])
|
|
||||||
|
|
||||||
# Calculate discharged capacity
|
|
||||||
now = time.time()
|
|
||||||
delta_t = now - self.last_update_time
|
|
||||||
self.last_update_time = now
|
|
||||||
self.capacity_ah.set(self.capacity_ah.get() + measured_current * delta_t / 3600)
|
|
||||||
|
|
||||||
self.status_var.set(
|
|
||||||
f"Discharging: {current_voltage:.3f}V / {self.discharge_cutoff.get()}V | "
|
|
||||||
f"Current: {current_current:.3f}A | "
|
|
||||||
f"Capacity: {self.capacity_ah.get():.4f}Ah | "
|
|
||||||
f"Time: {self.time_data[-1]:.1f}s"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check for discharge completion
|
|
||||||
if current_voltage <= self.discharge_cutoff.get():
|
|
||||||
break
|
|
||||||
|
|
||||||
time.sleep(0.5)
|
|
||||||
|
|
||||||
# Calculate Coulomb efficiency
|
|
||||||
if self.charge_capacity.get() > 0:
|
|
||||||
efficiency = (self.capacity_ah.get() / self.charge_capacity.get()) * 100
|
|
||||||
self.coulomb_efficiency.set(efficiency)
|
|
||||||
|
|
||||||
# Update GUI and show results
|
|
||||||
self.test_phase.set("Test Complete")
|
|
||||||
self.status_var.set(
|
|
||||||
f"Test complete | "
|
|
||||||
f"Discharge Capacity: {self.capacity_ah.get():.3f}Ah | "
|
|
||||||
f"Charge Capacity: {self.charge_capacity.get():.3f}Ah | "
|
|
||||||
f"Efficiency: {self.coulomb_efficiency.get():.1f}%"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Show summary dialog
|
|
||||||
self.root.after(0, lambda: messagebox.showinfo("Test Complete",
|
|
||||||
f"Test complete\n\n"
|
|
||||||
f"Discharge Capacity: {self.capacity_ah.get():.3f}Ah\n"
|
|
||||||
f"Charge Capacity: {self.charge_capacity.get():.3f}Ah\n"
|
|
||||||
f"Coulomb Efficiency: {self.coulomb_efficiency.get():.1f}%\n\n"
|
|
||||||
f"({self.capacity_ah.get()/self.capacity.get()*100:.1f}% of rated capacity)"))
|
|
||||||
|
|
||||||
# Write final summary to log file
|
|
||||||
self.write_cycle_summary()
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error_msg = str(e)
|
error_msg = str(e)
|
||||||
if self.root.winfo_exists():
|
if self.root.winfo_exists():
|
||||||
self.root.after(0, lambda msg=error_msg: messagebox.showerror("Test Error", msg))
|
self.root.after(0, lambda msg=error_msg: messagebox.showerror("Test Error", msg))
|
||||||
finally:
|
|
||||||
# Automatically stop the test after completion
|
|
||||||
self.root.after(0, self.stop_test)
|
self.root.after(0, self.stop_test)
|
||||||
|
|
||||||
def update_measurement_display(self, voltage, current, current_time):
|
def update_measurement_display(self, voltage, current, current_time):
|
||||||
@ -625,6 +666,7 @@ class BatteryTester:
|
|||||||
self.capacity_label.config(text=f"{self.capacity_ah.get():.4f}")
|
self.capacity_label.config(text=f"{self.capacity_ah.get():.4f}")
|
||||||
self.charge_capacity_label.config(text=f"{self.charge_capacity.get():.4f}")
|
self.charge_capacity_label.config(text=f"{self.charge_capacity.get():.4f}")
|
||||||
self.efficiency_label.config(text=f"{self.coulomb_efficiency.get():.1f}")
|
self.efficiency_label.config(text=f"{self.coulomb_efficiency.get():.1f}")
|
||||||
|
self.cycle_label.config(text=str(self.cycle_count.get()))
|
||||||
|
|
||||||
# Update plot with proper scaling
|
# Update plot with proper scaling
|
||||||
self.update_plot()
|
self.update_plot()
|
||||||
@ -637,6 +679,7 @@ class BatteryTester:
|
|||||||
return
|
return
|
||||||
|
|
||||||
summary_line = (
|
summary_line = (
|
||||||
|
f"Cycle {self.cycle_count.get()} - "
|
||||||
f"Discharge={self.capacity_ah.get():.4f}Ah, "
|
f"Discharge={self.capacity_ah.get():.4f}Ah, "
|
||||||
f"Charge={self.charge_capacity.get():.4f}Ah, "
|
f"Charge={self.charge_capacity.get():.4f}Ah, "
|
||||||
f"Efficiency={self.coulomb_efficiency.get():.1f}%"
|
f"Efficiency={self.coulomb_efficiency.get():.1f}%"
|
||||||
@ -690,6 +733,7 @@ class BatteryTester:
|
|||||||
|
|
||||||
self.session_active = False
|
self.session_active = False
|
||||||
self.test_running = False
|
self.test_running = False
|
||||||
|
self.continuous_mode = False
|
||||||
self.measuring = False
|
self.measuring = False
|
||||||
if hasattr(self, 'start_button'):
|
if hasattr(self, 'start_button'):
|
||||||
self.start_button.config(state=tk.DISABLED)
|
self.start_button.config(state=tk.DISABLED)
|
||||||
@ -732,6 +776,7 @@ class BatteryTester:
|
|||||||
"""Reconnect the device"""
|
"""Reconnect the device"""
|
||||||
self.status_var.set("Attempting to reconnect...")
|
self.status_var.set("Attempting to reconnect...")
|
||||||
self.test_running = False
|
self.test_running = False
|
||||||
|
self.continuous_mode = False
|
||||||
self.measuring = False
|
self.measuring = False
|
||||||
if hasattr(self, 'measurement_event'):
|
if hasattr(self, 'measurement_event'):
|
||||||
self.measurement_event.clear()
|
self.measurement_event.clear()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user