diff --git a/MainCode/adalm1000_logger.py b/MainCode/adalm1000_logger.py index 2301995..d3d4606 100644 --- a/MainCode/adalm1000_logger.py +++ b/MainCode/adalm1000_logger.py @@ -88,6 +88,10 @@ class DeviceManager: self.start_time = None self.last_measurement_time = None + def start_measurement(self): + if not self.measurement_thread.isRunning(): + self.measurement_thread.start() + def reset_data(self): """Reset all data buffers and statistics for the device""" self.time_data.clear() @@ -618,7 +622,7 @@ class BatteryTester(QMainWindow): self.downsample_factor = 1 # Initial kein Downsampling self.downsample_counter = 0 - # Initialize all measurement variables + # Initialize all measurement variables self.capacity_ah = 0.0 self.energy = 0.0 self.charge_capacity = 0.0 @@ -647,7 +651,7 @@ class BatteryTester(QMainWindow): # Status update timer self.status_timer = QTimer() self.status_timer.timeout.connect(self.update_status_and_plot) - self.status_timer.start(1000) #every second + self.status_timer.start(200) #every 200 ms def print_device_status(self): """Debug method to print current device states""" @@ -658,7 +662,7 @@ class BatteryTester(QMainWindow): print(f"Data Points: {len(device.time_data)}") print(f"Last Voltage: {device.voltage_data[-1] if device.voltage_data else 'NONE'}") print(f"Thread Running: {device.measurement_thread.isRunning() if hasattr(device, 'measurement_thread') else 'NO THREAD'}") - + def setup_ui(self): """Configure the user interface with all elements properly organized""" # Main widget and layout @@ -1325,6 +1329,10 @@ class BatteryTester(QMainWindow): first_serial = next(iter(self.devices.keys())) self.active_device = self.devices[first_serial] + if self.active_device: + if not self.active_device.measurement_thread.isRunning(): + self.active_device.measurement_thread.start() + # Update UI self.device_combo.clear() for serial in self.devices: @@ -1535,24 +1543,31 @@ class BatteryTester(QMainWindow): self.status_bar.showMessage(f"Switched to device: {serial}") self.set_connection_status(f"Connected: {serial}", self.status_colors["connected"]) + if not self.active_device.measurement_thread.isRunning(): + self.active_device.measurement_thread.start() + def update_ui_from_active_device(self): dev = self.active_device if not dev: return with self.plot_mutex: - # Kopiere aktuelle Daten + # Copy current data x = list(dev.display_time_data) y_v = list(dev.display_voltage_data) y_c = list(dev.display_current_data) - # Aktualisiere Plot + # Update plot self.line_voltage.set_data(x, y_v) self.line_current.set_data(x, y_c) - self.auto_scale_axes() + + # Fix: Pass required arguments to auto_scale_axes + if x and y_v and y_c: # Only call if data exists + self.auto_scale_axes(x, y_v, y_c) + self.canvas.draw_idle() - # Aktualisiere Labels + # Update labels if dev.voltage_data: v = dev.voltage_data[-1] i = dev.current_data[-1] @@ -1572,7 +1587,6 @@ class BatteryTester(QMainWindow): try: device = self.devices.get(serial) if not device: - logger.error(f"Device {serial} not found") return # Ensure timing is initialized @@ -1593,15 +1607,14 @@ class BatteryTester(QMainWindow): logger.warning(f"Invalid values - V: {voltage:.3f}, I: {current:.3f}") return - # Update data buffers - device.time_data.append(elapsed) - device.voltage_data.append(voltage) - device.current_data.append(current) - - # Update display buffers - device.display_time_data.append(elapsed) - device.display_voltage_data.append(voltage) - device.display_current_data.append(current) + with self.plot_mutex: + device.time_data.append(elapsed) + device.voltage_data.append(voltage) + device.current_data.append(current) + + device.display_time_data.append(elapsed) + device.display_voltage_data.append(voltage) + device.display_current_data.append(current) # Trim display buffers if needed if len(device.display_time_data) > 1000: @@ -1623,12 +1636,8 @@ class BatteryTester(QMainWindow): self.capacity_label.setText(f"{device.capacity_ah:.4f}") self.energy_label.setText(f"{device.energy:.4f}") - # Force plot update - self.update_plot() - except Exception as e: - logger.error(f"Critical error in update_measurements: {str(e)}") - traceback.print_exc() + logger.error(f"Update error: {str(e)}") def adjust_downsampling(self): current_length = len(self.time_data) @@ -2693,65 +2702,51 @@ class BatteryTester(QMainWindow): self.update_plot() def update_plot(self): - """Debugged plot update""" if not self.active_device: - logger.warning("No active device in update_plot") return - - try: - dev = self.active_device - with self.plot_mutex: - if not dev.display_time_data: - logger.warning(f"No data to plot for {dev.serial}") - return - - x_data = list(dev.display_time_data) - y1_data = list(dev.display_voltage_data) - y2_data = list(dev.display_current_data) - - self.line_voltage.set_data(x_data, y1_data) - self.line_current.set_data(x_data, y2_data) - - # Auto-scale only when significant changes occur - if len(x_data) > 1 and x_data[-1] - x_data[0] > 1.0: - self.auto_scale_axes() - - self.canvas.draw_idle() - logger.debug(f"Plot updated for {dev.serial} with {len(x_data)} points") - - except Exception as e: - logger.error(f"Plot update failed: {str(e)}") - - def auto_scale_axes(self): - """Auto-scale plot axes with appropriate padding and strict boundaries""" - if not self.active_device or not self.active_device.time_data: - return - dev = self.active_device - min_time = 0 - max_time = dev.time_data[-1] - current_xlim = self.ax.get_xlim() + + # Get minimal data under lock + with self.plot_mutex: + if not dev.display_time_data: + return + # Copy only the last 1000 points + x_data = list(dev.display_time_data)[-1000:] + y1_data = list(dev.display_voltage_data)[-1000:] + y2_data = list(dev.display_current_data)[-1000:] + + # Update plot data outside lock + self.line_voltage.set_data(x_data, y1_data) + self.line_current.set_data(x_data, y2_data) - if max_time > current_xlim[1] * 0.95: - new_max = max_time * 1.05 - self.ax.set_xlim(min_time, new_max) - self.ax2.set_xlim(min_time, new_max) + # Auto-scale only when needed + if len(x_data) > 1 and x_data[-1] - x_data[0] > 1.0: + self.auto_scale_axes(x_data, y1_data, y2_data) - voltage_padding = 0.2 - if dev.voltage_data: - min_voltage = max(0, min(dev.voltage_data) - voltage_padding) - max_voltage = min(5.0, max(dev.voltage_data) + voltage_padding) - current_ylim = self.ax.get_ylim() - if (abs(current_ylim[0] - min_voltage) > 0.1 or abs(current_ylim[1] - max_voltage) > 0.1): - self.ax.set_ylim(min_voltage, max_voltage) + self.canvas.draw_idle() + + def auto_scale_axes(self, x_data, y1_data, y2_data): + """Safe auto-scaling that handles empty data""" + if not x_data: + return - current_padding = 0.05 - if dev.current_data: - min_current = max(-0.25, min(dev.current_data) - current_padding) - max_current = min(0.25, max(dev.current_data) + current_padding) - current_ylim2 = self.ax2.get_ylim() - if (abs(current_ylim2[0] - min_current) > 0.02 or abs(current_ylim2[1] - max_current) > 0.02): - self.ax2.set_ylim(min_current, max_current) + try: + # Voltage scaling + voltage_padding = 0.2 + min_voltage = max(0, min(y1_data) - voltage_padding) + max_voltage = min(5.0, max(y1_data) + voltage_padding) + + # Current scaling + current_padding = 0.05 + min_current = max(-0.25, min(y2_data) - current_padding) + max_current = min(0.25, max(y2_data) + current_padding) + + # Apply new limits + self.ax.set_xlim(min(x_data), max(x_data) * 1.05) + self.ax.set_ylim(min_voltage, max_voltage) + self.ax2.set_ylim(min_current, max_current) + except ValueError: # Handle empty sequences + pass @pyqtSlot(str) def handle_device_error(self, error_msg):