diff --git a/MainCode/adalm1000_logger.py b/MainCode/adalm1000_logger.py index 4c6bf82..a33b193 100644 --- a/MainCode/adalm1000_logger.py +++ b/MainCode/adalm1000_logger.py @@ -37,8 +37,9 @@ class BatteryTester: self.session_active = False self.measuring = False self.test_running = False - self.continuous_mode = False # New flag for continuous cycling - self.interval = 0.1 # Measurement interval + self.continuous_mode = False + self.request_stop = False + self.interval = 0.1 self.log_dir = os.path.expanduser("~/adalm1000/logs") os.makedirs(self.log_dir, exist_ok=True) @@ -52,9 +53,9 @@ class BatteryTester: # Test progress tracking self.test_phase = tk.StringVar(value="Idle") self.capacity_ah = tk.DoubleVar(value=0.0) - 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.cycle_count = tk.IntVar(value=0) # Added for cycle counting + self.charge_capacity = tk.DoubleVar(value=0.0) # capacity tracking + self.coulomb_efficiency = tk.DoubleVar(value=0.0) # efficiency calculation + self.cycle_count = tk.IntVar(value=0) # cycle counting # Data buffers self.time_data = deque() @@ -418,21 +419,13 @@ class BatteryTester: return f"{hours:02d}:{minutes:02d}:{seconds:02d}" def stop_test(self): - """Stop the current test""" - self.test_running = False - self.continuous_mode = False - self.measuring = False - if hasattr(self, 'dev'): - self.dev.channels['A'].constant(0) - - # Update status message - if hasattr(self, 'filename'): - self.status_var.set( - 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") + """Request stop after current discharge phase completes""" + if not self.test_running: + return + + self.request_stop = True + self.status_var.set("Stop requested - will complete after current discharge phase") + self.stop_button.config(state=tk.DISABLED) def center_window(self, window): """Center a window on screen""" @@ -444,20 +437,12 @@ class BatteryTester: window.geometry(f'{width}x{height}+{x}+{y}') def run_test_sequence(self): - """Run the complete test sequence (discharge-rest-charge-rest-discharge) in a loop""" try: - # Calculate target current test_current = self.c_rate.get() * self.capacity.get() while self.test_running and (self.continuous_mode or self.cycle_count.get() == 0): - # Increment cycle count - self.cycle_count.set(self.cycle_count.get() + 1) - 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 + # Zurücksetzen des Stop-Requests zu Beginn jedes Zyklus + self.request_stop = False # 1. Charge (constant current) self.test_phase.set("Charge") @@ -520,9 +505,9 @@ class BatteryTester: if not self.test_running: return - # 3. 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") + # 3. Discharge (capacity measurement) + self.test_phase.set("Discharge") + self.status_var.set(f"discharge to {self.discharge_cutoff.get()}V @ {test_current:.3f}A") self.measuring = True self.dev.channels['A'].mode = pysmu.Mode.SIMV @@ -538,47 +523,48 @@ class BatteryTester: current_voltage = self.voltage_data[-1] current_current = abs(self.current_data[-1]) - # Calculate discharged capacity + # Kapazitätsberechnung 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( + # Statusupdate + status_msg = ( 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" + f"Capacity: {self.capacity_ah.get():.4f}Ah" ) + 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(): + if current_voltage <= self.discharge_cutoff.get() or self.request_stop: break - 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 - self.test_phase.set("Resting (Post-Discharge)") - 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()) + if self.test_running: + self.test_phase.set("Resting (Post-Discharge)") + self.measuring = False + self.dev.channels['A'].mode = pysmu.Mode.HI_Z + self.dev.channels['A'].constant(0) - # 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( - f"Resting after discharge | " - f"Time left: {time_left/60:.1f} min | " - f"{next_action}" - ) - time.sleep(1) + 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 discharge | " + f"Time left: {time_left/60:.1f} min | " + f"Next: Charge to {self.charge_cutoff.get()}V" + ) + time.sleep(1) if not self.test_running: return @@ -637,6 +623,35 @@ class BatteryTester: self.root.after(0, lambda msg=error_msg: messagebox.showerror("Test Error", msg)) 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): """Update display with current measurements""" try: