diff --git a/MainCode/adalm1000_logger.py b/MainCode/adalm1000_logger.py index 1398fd8..1b3092e 100644 --- a/MainCode/adalm1000_logger.py +++ b/MainCode/adalm1000_logger.py @@ -596,67 +596,114 @@ class BatteryTester(QMainWindow): def execute_charge_phase(self, current, target_voltage): """Führt die Ladephase durch""" + if not hasattr(self, 'dev') or not self.session_active: + self.error_signal.emit("Device not connected") + return self.test_phase = "Laden" self.phase_label.setText(self.test_phase) self.status_bar.setText(f"Laden auf {target_voltage}V @ {current:.3f}A") self.measuring = True - self.dev.channels['A'].mode = pysmu.Mode.SIMV - self.dev.channels['A'].constant(current) - self.charge_capacity = 0.0 - self.charge_capacity_label.setText("0.000") - last_update = time.time() - - while self.test_running and not self.request_stop: - if not self.voltage_data: - time.sleep(0.1) - continue - - now = time.time() - delta_t = now - last_update - last_update = now - - measured_current = abs(self.current_data[-1]) - self.charge_capacity += measured_current * delta_t / 3600 - self.charge_capacity_label.setText(f"{self.charge_capacity:.4f}") - - current_voltage = self.voltage_data[-1] - if current_voltage >= target_voltage or self.request_stop: - break - + try: + # Reset channel first + self.dev.channels['A'].mode = pysmu.Mode.HI_Z time.sleep(0.1) + + # Configure for current sourcing + self.dev.channels['A'].mode = pysmu.Mode.SIMV + time.sleep(0.05) + self.dev.channels['A'].constant(current) + time.sleep(0.1) # Allow settling time + actual_current = self.dev.channels['A'].current + if abs(actual_current - current) > 0.01: # 10mA tolerance + self.error_signal.emit(f"Current mismatch: {actual_current:.3f}A vs {current:.3f}A") + + self.charge_capacity = 0.0 + self.charge_capacity_label.setText("0.000") + last_update = time.time() + + while self.test_running and not self.request_stop: + if not self.voltage_data: + time.sleep(0.1) + continue + + now = time.time() + delta_t = now - last_update + last_update = now + + measured_current = abs(self.current_data[-1]) + self.charge_capacity += measured_current * delta_t / 3600 + self.charge_capacity_label.setText(f"{self.charge_capacity:.4f}") + + current_voltage = self.voltage_data[-1] + if current_voltage >= target_voltage or self.request_stop: + break + + time.sleep(0.1) + + except Exception as e: + self.error_signal.emit(f"Charge error: {str(e)}") def execute_discharge_phase(self, current, target_voltage): """Führt die Entladephase durch""" + if not hasattr(self, 'dev') or not self.session_active: + self.error_signal.emit("Device not connected") + return + self.test_phase = "Entladen" self.phase_label.setText(self.test_phase) self.status_bar.setText(f"Entladen auf {target_voltage}V @ {current:.3f}A") self.measuring = True - self.dev.channels['A'].mode = pysmu.Mode.SIMV - self.dev.channels['A'].constant(-current) - self.capacity_ah = 0.0 - self.capacity_label.setText("0.000") - last_update = time.time() - - while self.test_running and not self.request_stop: - if not self.current_data: - time.sleep(0.1) - continue - - now = time.time() - delta_t = now - last_update - last_update = now - - measured_current = abs(self.current_data[-1]) - self.capacity_ah += measured_current * delta_t / 3600 - self.capacity_label.setText(f"{self.capacity_ah:.4f}") - - current_voltage = self.voltage_data[-1] - if current_voltage <= target_voltage or self.request_stop: - break - + try: + # Reset channel first + self.dev.channels['A'].mode = pysmu.Mode.HI_Z time.sleep(0.1) + + # Configure for current sinking + self.dev.channels['A'].mode = pysmu.Mode.SIMV + time.sleep(0.05) + self.dev.channels['A'].constant(-current) + time.sleep(0.1) + + # Current verification + samples = self.dev.read(5) + measured_current = -np.mean([s[0][1] for s in samples]) + if abs(measured_current - current) > 0.02: + self.error_signal.emit(f"Entladestrom Abweichung: {measured_current:.3f}A vs {current:.3f}A") + + self.capacity_ah = 0.0 + self.capacity_label.setText("0.000") + last_update = time.time() + + while self.test_running and not self.request_stop: + if not self.current_data: + time.sleep(0.1) + continue + + now = time.time() + delta_t = now - last_update + last_update = now + + measured_current = abs(self.current_data[-1]) + self.capacity_ah += measured_current * delta_t / 3600 + self.capacity_label.setText(f"{self.capacity_ah:.4f}") + + current_voltage = self.voltage_data[-1] + if current_voltage <= target_voltage or self.request_stop: + break + + time.sleep(0.1) + + except Exception as e: + self.error_signal.emit(f"Discharge error: {str(e)}") + finally: + # Sicherstellen, dass der Kanal zurückgesetzt wird + try: + self.dev.channels['A'].mode = pysmu.Mode.HI_Z + self.dev.channels['A'].constant(0) + except Exception as e: + print(f"Error resetting channel: {e}") def execute_rest_phase(self, phase_name): """Führt eine Ruhephase durch""" @@ -742,10 +789,9 @@ class BatteryTester(QMainWindow): self.stop_button.setEnabled(False) self.start_button.setEnabled(True) - # Testdaten finalisieren - QTimer.singleShot(100, self.finalize_test) + self.finalize_test(show_message=False) - def finalize_test(self): + def finalize_test(self, show_message=True): """Finale Bereinigung nach Testende mit verbessertem Fenster-Handling""" try: # 1. Protokolldaten schreiben (mit zusätzlichem Lock) @@ -767,31 +813,15 @@ class BatteryTester(QMainWindow): print(f"Fehler beim Schließen der Protokolldatei: {e}") # 3. Benachrichtigung anzeigen (mit Fokus-Sicherung) - msg_box = QMessageBox(self) # Expliziter Parent - msg_box.setWindowFlags(msg_box.windowFlags() | - Qt.WindowStaysOnTopHint | # Immer im Vordergrund - Qt.MSWindowsFixedSizeDialogHint) # Besseres Verhalten unter Windows + if show_message: # Only show if explicitly requested + msg_box = QMessageBox(self) + msg_box.setWindowFlags(msg_box.windowFlags() | + Qt.WindowStaysOnTopHint) + msg_box.setIcon(QMessageBox.Information) + msg_box.setWindowTitle("Test abgeschlossen") + msg_box.setText(f"Test beendet\nZyklen: {self.cycle_count}") + msg_box.exec_() - msg_box.setIcon(QMessageBox.Information) - msg_box.setWindowTitle("Test abgeschlossen") - msg_box.setText( - f"Test wurde sicher beendet.\n\n" - f"Entladekapazität: {self.capacity_ah:.3f}Ah\n" - f"Abgeschlossene Zyklen: {self.cycle_count}" - ) - - # Sicherstellen, dass das Fenster sichtbar wird - msg_box.raise_() - msg_box.activateWindow() - - # Non-blocking anzeigen und Fokus erzwingen - QTimer.singleShot(100, lambda: ( - msg_box.show(), - msg_box.raise_(), - msg_box.activateWindow() - )) - msg_box.exec_() - except Exception as e: print(f"Kritischer Fehler in finalize_test: {e}") finally: