MainCode/adalm1000_logger.py aktualisiert

Alle Spannungswerte korrekt gemessen werden

    Das Programm stabil bleibt, auch ohne angeschlossene Batterie

    Der Benutzer klare Rückmeldungen über den Systemzustand erhält

    Die Hardware in einem sicheren Zustand bleibt
(D)
This commit is contained in:
Jan 2025-07-14 13:16:44 +02:00
parent 725bc83ab6
commit 44baefa581

View File

@ -38,21 +38,39 @@ class MeasurementThread(QThread):
self.current_direction = 1 # 1 for source, -1 for sink self.current_direction = 1 # 1 for source, -1 for sink
def run(self): def run(self):
"""Continuous measurement loop""" """Continuous measurement with proper validation"""
self._running = True self._running = True
consecutive_errors = 0
while self._running: while self._running:
try: try:
samples = self.device.read(self.filter_window_size, 500, True) samples = self.device.read(self.filter_window_size, 500, True)
# Check for device disconnection
if not samples: 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 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 # Strict voltage validation (0-5V range)
raw_voltage = np.mean([s[1][0] for s in samples]) # Channel B voltage if raw_voltage < 0 or raw_voltage > 5.0:
raw_current = np.mean([s[0][1] for s in samples]) * self.current_direction # Channel A current with direction 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.voltage_window.append(raw_voltage)
self.current_window.append(raw_current) self.current_window.append(raw_current)
@ -63,16 +81,10 @@ class MeasurementThread(QThread):
voltage = np.mean(self.voltage_window) voltage = np.mean(self.voltage_window)
current = np.mean(self.current_window) current = np.mean(self.current_window)
# Validate measurements # Emit 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
self.update_signal.emit(voltage, current, current_time) self.update_signal.emit(voltage, current, current_time)
# Store measurement # Store in queue
try: try:
self.measurement_queue.put_nowait((voltage, current)) self.measurement_queue.put_nowait((voltage, current))
except Full: except Full:
@ -80,10 +92,14 @@ class MeasurementThread(QThread):
time.sleep(max(0.05, self.interval)) time.sleep(max(0.05, self.interval))
except Exception as e: except DeviceDisconnectedError as e:
self.error_signal.emit(f"Read error: {str(e)}") self.error_signal.emit(f"Gerätefehler: {str(e)}")
time.sleep(1) time.sleep(1)
continue continue
except Exception as e:
self.error_signal.emit(f"Messfehler: {str(e)}")
time.sleep(0.5)
continue
def set_direction(self, direction): def set_direction(self, direction):
"""Set current direction (1 for source, -1 for sink)""" """Set current direction (1 for source, -1 for sink)"""
@ -892,9 +908,9 @@ class BatteryTester(QMainWindow):
self.main_layout.addWidget(self.canvas, 1) self.main_layout.addWidget(self.canvas, 1)
def init_device(self): def init_device(self):
"""Initialize the ADALM1000 device with continuous measurement""" """Initialize the ADALM1000 with proper connection checks"""
try: try:
# Clean up any existing session # Cleanup previous session
if hasattr(self, 'session'): if hasattr(self, 'session'):
try: try:
self.session.end() self.session.end()
@ -902,23 +918,45 @@ class BatteryTester(QMainWindow):
except: except:
pass pass
# Hardware reset delay
time.sleep(1) time.sleep(1)
try:
self.session = pysmu.Session(ignore_dataflow=True, queue_size=10000) self.session = pysmu.Session(ignore_dataflow=True, queue_size=10000)
if not self.session.devices: if not self.session.devices:
raise Exception("No ADALM1000 detected - check connections") 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] self.dev = self.session.devices[0]
# Set safe defaults
self.dev.channels['A'].mode = pysmu.Mode.HI_Z self.dev.channels['A'].mode = pysmu.Mode.HI_Z
self.dev.channels['B'].mode = pysmu.Mode.HI_Z self.dev.channels['B'].mode = pysmu.Mode.HI_Z
self.dev.channels['A'].constant(0) self.dev.channels['A'].constant(0)
self.dev.channels['B'].constant(0) self.dev.channels['B'].constant(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.session.start(0) self.session.start(0)
self.status_light.setStyleSheet(f"background-color: green; border-radius: 10px;") # Update UI
self.connection_label.setText("Connected") self.status_light.setStyleSheet("background-color: green; border-radius: 10px;")
self.status_bar.showMessage("Device connected | Ready to measure") self.connection_label.setText("Verbunden")
self.status_bar.showMessage("Gerät bereit - Batterie anschließen um zu messen")
self.session_active = True self.session_active = True
self.start_button.setEnabled(True) self.start_button.setEnabled(True)
@ -1852,33 +1890,39 @@ class BatteryTester(QMainWindow):
@pyqtSlot(str) @pyqtSlot(str)
def handle_device_error(self, error): def handle_device_error(self, error):
"""Handle device connection errors""" """Handle errors with proper state management"""
error_msg = str(error) 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'): if hasattr(self, 'session'):
try: try:
if self.session_active: if self.session_active:
self.session.end() self.session.end()
del self.session del self.session
except Exception as e: except:
print(f"Error cleaning up session: {e}") 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.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.session_active = False
self.test_running = False self.test_running = False
self.continuous_mode = False
self.measuring = False
self.start_button.setEnabled(False) self.start_button.setEnabled(False)
self.stop_button.setEnabled(False) self.stop_button.setEnabled(False)
self.time_data.clear() # Attempt recovery for certain errors
self.voltage_data.clear() if "no samples" in error_msg.lower() or "resource busy" in error_msg.lower():
self.current_data.clear() QTimer.singleShot(3000, self.reconnect_device)
@pyqtSlot(str) @pyqtSlot(str)
def update_test_phase(self, phase_text): def update_test_phase(self, phase_text):