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:
parent
725bc83ab6
commit
44baefa581
@ -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,27 +81,25 @@ 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:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
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,33 +908,55 @@ 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()
|
||||||
del self.session
|
del self.session
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Hardware reset delay
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
self.session = pysmu.Session(ignore_dataflow=True, queue_size=10000)
|
try:
|
||||||
if not self.session.devices:
|
self.session = pysmu.Session(ignore_dataflow=True, queue_size=10000)
|
||||||
raise Exception("No ADALM1000 detected - check connections")
|
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]
|
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)
|
||||||
|
|
||||||
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.session.start(0)
|
||||||
self.connection_label.setText("Connected")
|
|
||||||
self.status_bar.showMessage("Device connected | Ready to measure")
|
# 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.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):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user