diff --git a/MainCode/adalm1000_logger.py b/MainCode/adalm1000_logger.py index a8234d0..20d2999 100644 --- a/MainCode/adalm1000_logger.py +++ b/MainCode/adalm1000_logger.py @@ -38,21 +38,39 @@ class MeasurementThread(QThread): self.current_direction = 1 # 1 for source, -1 for sink def run(self): - """Continuous measurement loop""" + """Continuous measurement with proper validation""" self._running = True + consecutive_errors = 0 + while self._running: try: samples = self.device.read(self.filter_window_size, 500, True) + + # Check for device disconnection if not samples: - raise DeviceDisconnectedError("No samples received") + consecutive_errors += 1 + if consecutive_errors > 3: + raise DeviceDisconnectedError("Keine Messwerte empfangen") + time.sleep(0.1) + continue + + consecutive_errors = 0 # Reset counter on successful read current_time = time.time() - self.start_time + raw_voltage = np.mean([s[1][0] for s in samples]) # Channel B - # Get voltage from Channel B (HI_Z mode) and current from Channel A - raw_voltage = np.mean([s[1][0] for s in samples]) # Channel B voltage - raw_current = np.mean([s[0][1] for s in samples]) * self.current_direction # Channel A current with direction + # Strict voltage validation (0-5V range) + if raw_voltage < 0 or raw_voltage > 5.0: + raise ValueError(f"Ungültige Spannung: {raw_voltage}V (außerhalb 0-5V Bereich)") - # Update filter windows + # Current measurement with direction + raw_current = np.mean([s[0][1] for s in samples]) * self.current_direction + + # Current validation (-200mA to +200mA) + if not (-0.25 <= raw_current <= 0.25): + raise ValueError(f"Ungültiger Strom: {raw_current}A (außerhalb ±200mA Bereich)") + + # Apply filtering self.voltage_window.append(raw_voltage) self.current_window.append(raw_current) @@ -63,27 +81,25 @@ class MeasurementThread(QThread): voltage = np.mean(self.voltage_window) current = np.mean(self.current_window) - # Validate measurements - if not (0 <= voltage <= 5.0): - raise ValueError(f"Invalid voltage: {voltage}V") - if not (-0.25 <= current <= 0.25): - raise ValueError(f"Invalid current: {current}A") - - # Emit update + # Emit measurements self.update_signal.emit(voltage, current, current_time) - # Store measurement + # Store in queue try: self.measurement_queue.put_nowait((voltage, current)) except Full: pass - + time.sleep(max(0.05, self.interval)) - except Exception as e: - self.error_signal.emit(f"Read error: {str(e)}") + except DeviceDisconnectedError as e: + self.error_signal.emit(f"Gerätefehler: {str(e)}") time.sleep(1) continue + except Exception as e: + self.error_signal.emit(f"Messfehler: {str(e)}") + time.sleep(0.5) + continue def set_direction(self, direction): """Set current direction (1 for source, -1 for sink)""" @@ -892,33 +908,55 @@ class BatteryTester(QMainWindow): self.main_layout.addWidget(self.canvas, 1) def init_device(self): - """Initialize the ADALM1000 device with continuous measurement""" + """Initialize the ADALM1000 with proper connection checks""" try: - # Clean up any existing session + # Cleanup previous session if hasattr(self, 'session'): try: self.session.end() del self.session except: pass - + + # Hardware reset delay time.sleep(1) - - self.session = pysmu.Session(ignore_dataflow=True, queue_size=10000) - if not self.session.devices: - raise Exception("No ADALM1000 detected - check connections") + + try: + self.session = pysmu.Session(ignore_dataflow=True, queue_size=10000) + if not self.session.devices: + raise Exception("Kein ADALM1000 erkannt - Verbindung prüfen") + except Exception as e: + if "resource busy" in str(e).lower(): + raise Exception("ADALM1000 wird bereits von einem anderen Programm verwendet") + raise self.dev = self.session.devices[0] + + # Set safe defaults self.dev.channels['A'].mode = pysmu.Mode.HI_Z self.dev.channels['B'].mode = pysmu.Mode.HI_Z self.dev.channels['A'].constant(0) self.dev.channels['B'].constant(0) - self.session.start(0) + # Connection test with actual measurement + try: + samples = self.dev.read(5, 500, True) # 5 samples for stability + if not samples: + raise DeviceDisconnectedError("Keine Messwerte empfangen") + + # Check if we're getting valid data (not just noise) + voltages = [s[1][0] for s in samples] # Channel B voltages + if all(abs(v) < 0.0001 for v in voltages): # 100µV threshold + self.status_bar.showMessage("Gerät verbunden, aber keine Batterie angeschlossen") + except Exception as e: + raise DeviceDisconnectedError(f"Verbindungstest fehlgeschlagen: {str(e)}") - self.status_light.setStyleSheet(f"background-color: green; border-radius: 10px;") - self.connection_label.setText("Connected") - self.status_bar.showMessage("Device connected | Ready to measure") + self.session.start(0) + + # Update UI + self.status_light.setStyleSheet("background-color: green; border-radius: 10px;") + self.connection_label.setText("Verbunden") + self.status_bar.showMessage("Gerät bereit - Batterie anschließen um zu messen") self.session_active = True self.start_button.setEnabled(True) @@ -1852,33 +1890,39 @@ class BatteryTester(QMainWindow): @pyqtSlot(str) def handle_device_error(self, error): - """Handle device connection errors""" + """Handle errors with proper state management""" error_msg = str(error) - print(f"Device error: {error_msg}") + print(f"Fehler: {error_msg}") + # Special cases + if "resource busy" in error_msg.lower(): + error_msg = "ADALM1000 is already in use" + elif "no samples" in error_msg.lower(): + error_msg = "No measurments - Check connection" + + # Cleanup if hasattr(self, 'session'): try: if self.session_active: self.session.end() del self.session - except Exception as e: - print(f"Error cleaning up session: {e}") + except: + pass - self.status_light.setStyleSheet(f"background-color: red; border-radius: 10px;") + # Update UI + self.status_light.setStyleSheet("background-color: red; border-radius: 10px;") self.connection_label.setText("Disconnected") - self.status_bar.showMessage(f"Device error: {error_msg}") - + self.status_bar.showMessage(f"Error: {error_msg}") + + # Disable controls self.session_active = False self.test_running = False - self.continuous_mode = False - self.measuring = False - self.start_button.setEnabled(False) self.stop_button.setEnabled(False) - self.time_data.clear() - self.voltage_data.clear() - self.current_data.clear() + # Attempt recovery for certain errors + if "no samples" in error_msg.lower() or "resource busy" in error_msg.lower(): + QTimer.singleShot(3000, self.reconnect_device) @pyqtSlot(str) def update_test_phase(self, phase_text):