Corrections: data acquisition, cleaning buffer. New features: Results saved on a excel file using template, load presets from config buttons. Tested and deployed version
This commit is contained in:
parent
e8bb105d61
commit
1d0942b57c
2
.gitignore
vendored
2
.gitignore
vendored
@ -23,7 +23,7 @@ env/
|
|||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
*.log
|
*.log
|
||||||
Data_log
|
Data_log/
|
||||||
|
|
||||||
# OS generated files
|
# OS generated files
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import serial
|
import serial
|
||||||
@ -12,6 +13,7 @@ from PyQt6.QtCore import QTimer
|
|||||||
from PyQt6.QtGui import QIcon
|
from PyQt6.QtGui import QIcon
|
||||||
from PyQt6.QtCore import QSettings
|
from PyQt6.QtCore import QSettings
|
||||||
from openpyxl import load_workbook
|
from openpyxl import load_workbook
|
||||||
|
from collections import deque
|
||||||
|
|
||||||
# -------------------------- Get resource path --------------------------
|
# -------------------------- Get resource path --------------------------
|
||||||
def resource_path(relative_path):
|
def resource_path(relative_path):
|
||||||
@ -36,7 +38,16 @@ def find_arduino():
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
arduino_port = find_arduino()
|
arduino_port = find_arduino()
|
||||||
ser = serial.Serial(arduino_port, 9600, timeout=10) if arduino_port else None
|
ser = None
|
||||||
|
if arduino_port:
|
||||||
|
ser = serial.Serial(
|
||||||
|
arduino_port,
|
||||||
|
9600,
|
||||||
|
timeout=0, # Non-blocking
|
||||||
|
write_timeout=0
|
||||||
|
)
|
||||||
|
ser.reset_input_buffer()
|
||||||
|
ser.reset_output_buffer()
|
||||||
|
|
||||||
# --------------------------- Config JSON helpers ---------------------------
|
# --------------------------- Config JSON helpers ---------------------------
|
||||||
def get_presets_path():
|
def get_presets_path():
|
||||||
@ -102,9 +113,10 @@ class HMI(QWidget):
|
|||||||
|
|
||||||
# -------------------------- Data Storage --------------------------
|
# -------------------------- Data Storage --------------------------
|
||||||
self.start_time = time.time()
|
self.start_time = time.time()
|
||||||
self.time_data = []
|
|
||||||
self.pressure_data = []
|
|
||||||
self.marker_items = []
|
self.marker_items = []
|
||||||
|
self.time_data = deque(maxlen=5000)
|
||||||
|
self.pressure_data = deque(maxlen=5000)
|
||||||
|
self.serial_buffer = bytearray()
|
||||||
|
|
||||||
# -------------------------- Default / Saved Configurations --------------------------
|
# -------------------------- Default / Saved Configurations --------------------------
|
||||||
self.setpoint_start = float(self.settings.value("setpoint_start", 25))
|
self.setpoint_start = float(self.settings.value("setpoint_start", 25))
|
||||||
@ -299,31 +311,65 @@ class HMI(QWidget):
|
|||||||
self.marker_input.setText("")
|
self.marker_input.setText("")
|
||||||
|
|
||||||
# -------------------------- Plot & Cursor Methods --------------------------
|
# -------------------------- Plot & Cursor Methods --------------------------
|
||||||
|
def moving_average_fast(self, window=5):
|
||||||
|
data = list(self.pressure_data)
|
||||||
|
if len(data) < window:
|
||||||
|
return data
|
||||||
|
|
||||||
|
result = []
|
||||||
|
running_sum = 0
|
||||||
|
|
||||||
|
for i in range(len(data)):
|
||||||
|
running_sum += data[i]
|
||||||
|
|
||||||
|
if i >= window:
|
||||||
|
running_sum -= data[i - window]
|
||||||
|
|
||||||
|
if i >= window - 1:
|
||||||
|
result.append(running_sum / window)
|
||||||
|
else:
|
||||||
|
result.append(data[i])
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
def update_plot(self):
|
def update_plot(self):
|
||||||
if ser and ser.in_waiting > 0:
|
if not ser or not ser.is_open:
|
||||||
data = ser.read(2)
|
return
|
||||||
if len(data) < 2:
|
try:
|
||||||
return
|
# Read ALL available bytes
|
||||||
try:
|
bytes_available = ser.in_waiting
|
||||||
raw_pressure = struct.unpack('<H', data)[0]
|
if bytes_available:
|
||||||
|
new_data = ser.read(bytes_available)
|
||||||
|
self.serial_buffer.extend(new_data)
|
||||||
|
|
||||||
|
# Process complete 2-byte packets
|
||||||
|
while len(self.serial_buffer) >= 2:
|
||||||
|
packet = self.serial_buffer[:2]
|
||||||
|
del self.serial_buffer[:2]
|
||||||
|
|
||||||
|
raw_pressure = struct.unpack('<H', packet)[0]
|
||||||
eng_pressure = raw_pressure * 1.219 - 246.676
|
eng_pressure = raw_pressure * 1.219 - 246.676
|
||||||
|
|
||||||
elapsed_time = time.time() - self.start_time
|
elapsed_time = time.time() - self.start_time
|
||||||
|
|
||||||
self.time_data.append(elapsed_time)
|
self.time_data.append(elapsed_time)
|
||||||
self.pressure_data.append(eng_pressure)
|
self.pressure_data.append(eng_pressure)
|
||||||
|
|
||||||
if len(self.time_data) > 100000:
|
# Update plot only if new data exists
|
||||||
self.time_data.pop(0)
|
if self.time_data:
|
||||||
self.pressure_data.pop(0)
|
smoothed = self.moving_average_fast()
|
||||||
|
self.plot.setData(list(self.time_data), smoothed)
|
||||||
|
|
||||||
self.plot.setData([t for t in self.time_data],
|
self.actual_value_label.setText(
|
||||||
[self.moving_average(self.pressure_data[:i + 1]) for i in range(len(self.pressure_data))])
|
f"{self.pressure_data[-1]:.2f} kPa"
|
||||||
|
)
|
||||||
|
self.actual_value_label.setPos(
|
||||||
|
self.time_data[-1],
|
||||||
|
self.pressure_data[-1]
|
||||||
|
)
|
||||||
|
|
||||||
if self.time_data and self.pressure_data:
|
except Exception as e:
|
||||||
self.actual_value_label.setText(f"{eng_pressure:.2f} kPa")
|
print("Serial read error:", e)
|
||||||
self.actual_value_label.setPos(self.time_data[-1], self.pressure_data[-1])
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def sync_cursors(self, moved_cursor, other_cursor):
|
def sync_cursors(self, moved_cursor, other_cursor):
|
||||||
new_pos = moved_cursor.value() + self.setwindow if moved_cursor is self.cursor_start else moved_cursor.value() - self.setwindow
|
new_pos = moved_cursor.value() + self.setwindow if moved_cursor is self.cursor_start else moved_cursor.value() - self.setwindow
|
||||||
@ -372,8 +418,6 @@ class HMI(QWidget):
|
|||||||
self.update_marker_interval()
|
self.update_marker_interval()
|
||||||
self.reset_hmi()
|
self.reset_hmi()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def save_configuration(self):
|
def save_configuration(self):
|
||||||
try:
|
try:
|
||||||
if self.current_preset is None:
|
if self.current_preset is None:
|
||||||
Loading…
x
Reference in New Issue
Block a user