Updates
This commit is contained in:
149
main.py
149
main.py
@@ -5,16 +5,18 @@ AUTOMOTIVE POWER SIMULATOR APP - MAIN.PY
|
||||
|
||||
VERSION: 1.0
|
||||
|
||||
AUTHOR: D. RICE 14/11/2025
|
||||
© 2025 ARRIVE
|
||||
AUTHOR: D. RICE 06/01/2026
|
||||
© 2026 ARRIVE
|
||||
"""
|
||||
|
||||
# Imports
|
||||
import sys
|
||||
from PySide6.QtWidgets import (QApplication, QDialog, QMainWindow)
|
||||
from PySide6.QtCore import (QThread, QObject, Signal, Slot)
|
||||
from PySide6.QtSerialPort import (QserialPort, QSerialPortInfo)
|
||||
|
||||
import time
|
||||
import struct
|
||||
|
||||
from ui_mainwindow import Ui_MainWindow
|
||||
from ui_scanning import Ui_scanningDialog
|
||||
@@ -73,16 +75,16 @@ class MainWindow(QMainWindow):
|
||||
self.ui.connButton.clicked.connect(self.conn_button_press)
|
||||
|
||||
# Set initial size
|
||||
initial_width = 1024
|
||||
initial_height = 768
|
||||
initial_width = 1000
|
||||
initial_height = 600
|
||||
|
||||
# Lock the window size by setting min/max to the same values
|
||||
self.setMinimumSize(initial_width, initial_height)
|
||||
self.setMaximumSize(initial_width, initial_height)
|
||||
|
||||
self.setGeometry(0, 0, 1024, 768)
|
||||
self.setGeometry(0, 0, 1000, 600)
|
||||
|
||||
self.setFixedSize(1024, 768)
|
||||
self.setFixedSize(1000, 600)
|
||||
|
||||
self.show()
|
||||
|
||||
@@ -100,8 +102,16 @@ class MainWindow(QMainWindow):
|
||||
|
||||
QApplication.processEvents()
|
||||
|
||||
# Run Connection actions here
|
||||
#self.start_worker()
|
||||
# Setup serial port
|
||||
|
||||
ser = self.serial.Serial(port="/dev/ttyACM0", baudrate=921600)
|
||||
|
||||
|
||||
command = 73 #0x49 'I' ASCII
|
||||
state = 0
|
||||
data = (command, state)
|
||||
byte_data = self.pack_integers_to_bytes(*data)
|
||||
|
||||
|
||||
while ((IDN_Response_flag == False) and (Error_flag == False)):
|
||||
QApplication.processEvents()
|
||||
@@ -138,100 +148,39 @@ class MainWindow(QMainWindow):
|
||||
|
||||
QApplication.processEvents()
|
||||
|
||||
def pack_integers_to_bytes(self, *integers: int) -> bytes:
|
||||
# Setup header
|
||||
sync_bytes = [0x41, 0x52]
|
||||
|
||||
# Process data
|
||||
# Mask each input to 8-bits to prevent packing errors
|
||||
data_bytes = [i & 0xFF for i in integers]
|
||||
|
||||
# Get length
|
||||
data_length = [len(data_bytes) & 0xFF]
|
||||
|
||||
# Calculate checksum
|
||||
# Summingall data bytes, then applying bitwise NOT
|
||||
total_sum = sum(data_bytes)
|
||||
rx_checksum = ~total_sum
|
||||
|
||||
rx_checksum_h = (rx_checksum >> 8) & 0xFF
|
||||
rx_checksum_l = rx_checksum & 0xFF
|
||||
checksum_bytes = [rx_checksum_h,rx_checksum_l]
|
||||
|
||||
# Combine all components
|
||||
full_packet = sync_bytes + data_length + data_bytes + checksum_bytes
|
||||
|
||||
# Dymanically create format string
|
||||
# '!' = Network order, 'B' = unsigned char
|
||||
# We need as many 'B's as there are elements in the full packet
|
||||
format_string = f"!{len(full_packet)}B"
|
||||
|
||||
return struct.pack(format_string, *full_packet)
|
||||
|
||||
def run_scope_setup (self):
|
||||
self.worker.run_setup()
|
||||
|
||||
@Slot()
|
||||
def start_worker(self):
|
||||
# Create a QThread
|
||||
self.worker_thread = QThread()
|
||||
|
||||
#nCreate the worker QObject (Now created directly, no import needed)
|
||||
self.worker = ScopeWorker()
|
||||
|
||||
# Move the worker object to the thread
|
||||
self.worker.moveToThread(self.worker_thread)
|
||||
|
||||
# Connect Signals
|
||||
self.worker_thread.started.connect(self.worker.run)
|
||||
|
||||
self.worker.idn_signal.connect(self.handle_idn)
|
||||
self.worker.data_ready_signal.connect(self.handle_data_ready)
|
||||
self.worker.error_signal.connect(self.handle_error)
|
||||
|
||||
# Clean-up connections
|
||||
self.worker.finished_signal.connect(self.worker_thread.quit)
|
||||
self.worker.finished_signal.connect(self.worker.deleteLater)
|
||||
self.worker_thread.finished.connect(self.worker_thread.deleteLater)
|
||||
|
||||
# Start the QThread, which triggers worker.run
|
||||
self.worker_thread.start()
|
||||
|
||||
@Slot()
|
||||
def signal_acquisition(self):
|
||||
"""Sends the signal to the worker to start pulling data."""
|
||||
if self.worker:
|
||||
self.log_text.append("Main: Sending START_ACQUISITION signal.")
|
||||
self.status_label.setText("Status: Acquiring data...")
|
||||
# This is safe because start_acquisition only sets a flag
|
||||
self.worker.start_acquisition()
|
||||
|
||||
# --- SLOTS: Receive data safely from the worker thread ---
|
||||
|
||||
@Slot(str)
|
||||
def handle_idn(self, idn_string):
|
||||
global IDN_Response_flag
|
||||
global Error_flag
|
||||
|
||||
# Received the initial IDN from the worker
|
||||
IDN_Response_flag = True
|
||||
|
||||
# Split the string by the comma delimiter
|
||||
components = idn_string.strip().split(',')
|
||||
|
||||
# Split the string by the comma delimiter
|
||||
components = idn_string.strip().split(',')
|
||||
|
||||
if len(components) == 4:
|
||||
# Assign the components to meaningful keys in a dictionary
|
||||
parsed_data = {
|
||||
"manufacturer": components[0],
|
||||
"model": components[1],
|
||||
"serial_number": components[2],
|
||||
"firmware_version": components[3]
|
||||
}
|
||||
|
||||
self.ui.manu.setText(parsed_data.get("manufacturer"))
|
||||
self.ui.model.setText(parsed_data.get("model"))
|
||||
self.ui.sn.setText(parsed_data.get("serial_number"))
|
||||
self.ui.fw.setText(parsed_data.get("firmware_version"))
|
||||
|
||||
else:
|
||||
Error_flag = True
|
||||
|
||||
self.ui.manu.setText("---")
|
||||
self.ui.model.setText("---")
|
||||
self.ui.sn.setText("---")
|
||||
self.ui.fw.setText("---")
|
||||
|
||||
@Slot(str)
|
||||
def handle_data_ready(self, data_snippet):
|
||||
"""Received the acquired data from the worker."""
|
||||
self.status_label.setText("Status: Data Ready. Waiting for next command.")
|
||||
self.log_text.append(f"Main: Received Waveform Data Snippet:\n{data_snippet}")
|
||||
|
||||
@Slot(str)
|
||||
def handle_error(self, message):
|
||||
global Error_flag
|
||||
|
||||
Error_flag = True
|
||||
|
||||
def closeEvent(self):
|
||||
"""Handle application close to stop the thread gracefully."""
|
||||
if self.worker_thread and self.worker_thread.isRunning():
|
||||
self.worker.stop()
|
||||
# Wait a moment for the thread to clean up
|
||||
self.worker_thread.wait(500)
|
||||
|
||||
|
||||
# Run main
|
||||
if __name__ == '__main__':
|
||||
|
||||
Reference in New Issue
Block a user