MainCode/adalm1000_logger.py aktualisiert
Der Stop-Button setzt nur ein Flag (request_stop) statt sofort zu stoppen
Die Entladephase überprüft dieses Flag und bricht ab, wenn es gesetzt ist
Nach der Entladephase wird der Test nur beendet, wenn request_stop True ist
Neue finalize_test Methode für konsistente Aufräumarbeiten
Klare Statusmeldungen, die den Stop-Request anzeigen
(Deepseek)
This commit is contained in:
parent
a82cc2c981
commit
06c99bae38
@ -37,8 +37,9 @@ 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.continuous_mode = False
|
||||||
self.interval = 0.1 # Measurement interval
|
self.request_stop = False
|
||||||
|
self.interval = 0.1
|
||||||
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)
|
||||||
|
|
||||||
@ -52,9 +53,9 @@ class BatteryTester:
|
|||||||
# Test progress tracking
|
# Test progress tracking
|
||||||
self.test_phase = tk.StringVar(value="Idle")
|
self.test_phase = tk.StringVar(value="Idle")
|
||||||
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) # capacity tracking
|
||||||
self.coulomb_efficiency = tk.DoubleVar(value=0.0) # Added for efficiency calculation
|
self.coulomb_efficiency = tk.DoubleVar(value=0.0) # efficiency calculation
|
||||||
self.cycle_count = tk.IntVar(value=0) # Added for cycle counting
|
self.cycle_count = tk.IntVar(value=0) # cycle counting
|
||||||
|
|
||||||
# Data buffers
|
# Data buffers
|
||||||
self.time_data = deque()
|
self.time_data = deque()
|
||||||
@ -418,21 +419,13 @@ class BatteryTester:
|
|||||||
return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
|
return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
|
||||||
|
|
||||||
def stop_test(self):
|
def stop_test(self):
|
||||||
"""Stop the current test"""
|
"""Request stop after current discharge phase completes"""
|
||||||
self.test_running = False
|
if not self.test_running:
|
||||||
self.continuous_mode = False
|
return
|
||||||
self.measuring = False
|
|
||||||
if hasattr(self, 'dev'):
|
|
||||||
self.dev.channels['A'].constant(0)
|
|
||||||
|
|
||||||
# Update status message
|
self.request_stop = True
|
||||||
if hasattr(self, 'filename'):
|
self.status_var.set("Stop requested - will complete after current discharge phase")
|
||||||
self.status_var.set(
|
self.stop_button.config(state=tk.DISABLED)
|
||||||
f"Test interrupted after cycle {self.cycle_count.get()} | "
|
|
||||||
f"Results saved to: {os.path.basename(self.filename)}"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
self.status_var.set("Test interrupted - no data saved")
|
|
||||||
|
|
||||||
def center_window(self, window):
|
def center_window(self, window):
|
||||||
"""Center a window on screen"""
|
"""Center a window on screen"""
|
||||||
@ -444,20 +437,12 @@ 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) in a loop"""
|
|
||||||
try:
|
try:
|
||||||
# Calculate target current
|
|
||||||
test_current = self.c_rate.get() * self.capacity.get()
|
test_current = self.c_rate.get() * self.capacity.get()
|
||||||
|
|
||||||
while self.test_running and (self.continuous_mode or self.cycle_count.get() == 0):
|
while self.test_running and (self.continuous_mode or self.cycle_count.get() == 0):
|
||||||
# Increment cycle count
|
# Zurücksetzen des Stop-Requests zu Beginn jedes Zyklus
|
||||||
self.cycle_count.set(self.cycle_count.get() + 1)
|
self.request_stop = False
|
||||||
self.root.after(0, lambda: self.cycle_label.config(text=str(self.cycle_count.get())))
|
|
||||||
|
|
||||||
# Check for Interrupt
|
|
||||||
if not self.test_running:
|
|
||||||
self.status_var.set("Test interrupted - finishing current cycle")
|
|
||||||
break
|
|
||||||
|
|
||||||
# 1. Charge (constant current)
|
# 1. Charge (constant current)
|
||||||
self.test_phase.set("Charge")
|
self.test_phase.set("Charge")
|
||||||
@ -520,9 +505,9 @@ class BatteryTester:
|
|||||||
if not self.test_running:
|
if not self.test_running:
|
||||||
return
|
return
|
||||||
|
|
||||||
# 3. Final Discharge (capacity measurement)
|
# 3. Discharge (capacity measurement)
|
||||||
self.test_phase.set("Final Discharge")
|
self.test_phase.set("Discharge")
|
||||||
self.status_var.set(f"Final discharge to {self.discharge_cutoff.get()}V @ {test_current:.3f}A")
|
self.status_var.set(f"discharge to {self.discharge_cutoff.get()}V @ {test_current:.3f}A")
|
||||||
|
|
||||||
self.measuring = True
|
self.measuring = True
|
||||||
self.dev.channels['A'].mode = pysmu.Mode.SIMV
|
self.dev.channels['A'].mode = pysmu.Mode.SIMV
|
||||||
@ -538,26 +523,34 @@ class BatteryTester:
|
|||||||
current_voltage = self.voltage_data[-1]
|
current_voltage = self.voltage_data[-1]
|
||||||
current_current = abs(self.current_data[-1])
|
current_current = abs(self.current_data[-1])
|
||||||
|
|
||||||
# Calculate discharged capacity
|
# Kapazitätsberechnung
|
||||||
now = time.time()
|
now = time.time()
|
||||||
delta_t = now - self.last_update_time
|
delta_t = now - self.last_update_time
|
||||||
self.last_update_time = now
|
self.last_update_time = now
|
||||||
self.capacity_ah.set(self.capacity_ah.get() + current_current * delta_t / 3600)
|
self.capacity_ah.set(self.capacity_ah.get() + current_current * delta_t / 3600)
|
||||||
|
|
||||||
self.status_var.set(
|
# Statusupdate
|
||||||
|
status_msg = (
|
||||||
f"Discharging: {current_voltage:.3f}V / {self.discharge_cutoff.get()}V | "
|
f"Discharging: {current_voltage:.3f}V / {self.discharge_cutoff.get()}V | "
|
||||||
f"Current: {current_current:.3f}A | "
|
f"Current: {current_current:.3f}A | "
|
||||||
f"Capacity: {self.capacity_ah.get():.4f}Ah | "
|
f"Capacity: {self.capacity_ah.get():.4f}Ah"
|
||||||
f"Time: {self.time_data[-1]:.1f}s"
|
|
||||||
)
|
)
|
||||||
|
if self.request_stop:
|
||||||
|
status_msg += " | FINALIZING - completing discharge..."
|
||||||
|
self.status_var.set(status_msg)
|
||||||
|
|
||||||
# Check for discharge completion
|
if current_voltage <= self.discharge_cutoff.get() or self.request_stop:
|
||||||
if current_voltage <= self.discharge_cutoff.get():
|
|
||||||
break
|
break
|
||||||
|
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
if self.request_stop:
|
||||||
|
time.sleep(0.5)
|
||||||
|
self.test_running = False
|
||||||
|
self.root.after(0, self.finalize_test)
|
||||||
|
return
|
||||||
|
|
||||||
# 4. Rest period after charge
|
# 4. Rest period after charge
|
||||||
|
if self.test_running:
|
||||||
self.test_phase.set("Resting (Post-Discharge)")
|
self.test_phase.set("Resting (Post-Discharge)")
|
||||||
self.measuring = False
|
self.measuring = False
|
||||||
self.dev.channels['A'].mode = pysmu.Mode.HI_Z
|
self.dev.channels['A'].mode = pysmu.Mode.HI_Z
|
||||||
@ -566,17 +559,10 @@ class BatteryTester:
|
|||||||
rest_end_time = time.time() + (self.rest_time.get() * 3600)
|
rest_end_time = time.time() + (self.rest_time.get() * 3600)
|
||||||
while time.time() < rest_end_time and self.test_running:
|
while time.time() < rest_end_time and self.test_running:
|
||||||
time_left = max(0, rest_end_time - time.time())
|
time_left = max(0, rest_end_time - time.time())
|
||||||
|
|
||||||
# Angepasste Statusmeldung mit Interrupt-Info
|
|
||||||
if self.test_running and self.continuous_mode:
|
|
||||||
next_action = f"Next: Charge to {self.charge_cutoff.get()}V"
|
|
||||||
else:
|
|
||||||
next_action = "Waiting for interrupt or completion"
|
|
||||||
|
|
||||||
self.status_var.set(
|
self.status_var.set(
|
||||||
f"Resting after discharge | "
|
f"Resting after discharge | "
|
||||||
f"Time left: {time_left/60:.1f} min | "
|
f"Time left: {time_left/60:.1f} min | "
|
||||||
f"{next_action}"
|
f"Next: Charge to {self.charge_cutoff.get()}V"
|
||||||
)
|
)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
@ -637,6 +623,35 @@ class BatteryTester:
|
|||||||
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))
|
||||||
self.root.after(0, self.stop_test)
|
self.root.after(0, self.stop_test)
|
||||||
|
|
||||||
|
def finalize_test(self):
|
||||||
|
"""Final cleanup after test completes or is stopped"""
|
||||||
|
self.measuring = False
|
||||||
|
if hasattr(self, 'dev'):
|
||||||
|
self.dev.channels['A'].constant(0)
|
||||||
|
|
||||||
|
if hasattr(self, 'filename'):
|
||||||
|
self.write_cycle_summary()
|
||||||
|
|
||||||
|
self.start_button.config(state=tk.NORMAL)
|
||||||
|
self.stop_button.config(state=tk.DISABLED)
|
||||||
|
self.request_stop = False
|
||||||
|
|
||||||
|
# Erfolgsmeldung mit mehr Details
|
||||||
|
message = (
|
||||||
|
f"Test safely stopped after discharge phase | "
|
||||||
|
f"Cycle {self.cycle_count.get()} completed | "
|
||||||
|
f"Final capacity: {self.capacity_ah.get():.3f}Ah"
|
||||||
|
)
|
||||||
|
self.status_var.set(message)
|
||||||
|
|
||||||
|
# Optional: Messagebox anzeigen
|
||||||
|
self.root.after(0, lambda: messagebox.showinfo(
|
||||||
|
"Test Completed",
|
||||||
|
f"Test was safely stopped after discharge phase.\n\n"
|
||||||
|
f"Final discharge capacity: {self.capacity_ah.get():.3f}Ah\n"
|
||||||
|
f"Total cycles completed: {self.cycle_count.get()}"
|
||||||
|
))
|
||||||
|
|
||||||
def update_measurement_display(self, voltage, current, current_time):
|
def update_measurement_display(self, voltage, current, current_time):
|
||||||
"""Update display with current measurements"""
|
"""Update display with current measurements"""
|
||||||
try:
|
try:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user