forked from zietzm/Helmholtz_Test_Bench
Added user interface elements for magnetometer calibration
This commit is contained in:
@@ -81,6 +81,9 @@ class HelmholtzCageDevice:
|
||||
# The axes talks to the HW objects (Arduino, PSU) referenced in this object
|
||||
self.axes.append(Axis(i, self))
|
||||
|
||||
# Zero and activate channels. This is a sort of "armed" state so that we can send commands later
|
||||
self.idle()
|
||||
|
||||
# --- HW COMMUNICATION THREAD ---
|
||||
self._cmd_exec_thread = Thread(target=self._cmd_exec_thread_method)
|
||||
self._cmd_exec_thread.start()
|
||||
@@ -92,6 +95,7 @@ class HelmholtzCageDevice:
|
||||
def reconnect_hardware(self):
|
||||
self.shutdown()
|
||||
self.connect_hardware()
|
||||
self.idle()
|
||||
|
||||
# TODO: Move to proxy
|
||||
def connect_hardware(self):
|
||||
@@ -133,9 +137,6 @@ class HelmholtzCageDevice:
|
||||
self.psu2 = None
|
||||
ui_print("Error creating PSU device:\n{}".format(e))
|
||||
|
||||
# Zero and activate channels. This is a sort of "armed" state so that we can send commands later
|
||||
self.idle()
|
||||
|
||||
def idle(self):
|
||||
""" Zero and activate channels """
|
||||
if self.psu1 is not None:
|
||||
@@ -144,6 +145,9 @@ class HelmholtzCageDevice:
|
||||
self.psu2.idle()
|
||||
if self.arduino is not None:
|
||||
self.arduino.idle()
|
||||
# Since these actions are not handled by the axes objects, also make sure to update their target field status
|
||||
for axis in self.axes:
|
||||
axis.target_current = 0
|
||||
|
||||
def request_proxy(self):
|
||||
"""Returns a new HelmholtzCageProxy or None, depending on if access is available"""
|
||||
@@ -222,7 +226,6 @@ class HelmholtzCageDevice:
|
||||
else:
|
||||
raise Exception("Command unknown!")
|
||||
|
||||
|
||||
def _hw_poll_thread_method(self):
|
||||
"""This method forms the main thread for hardware command execution."""
|
||||
while True:
|
||||
|
||||
+26
-23
@@ -74,29 +74,32 @@ class ClientConnectionThread(Thread):
|
||||
def run(self):
|
||||
msg = ''
|
||||
while True:
|
||||
raw_msg = self.client_socket.recv(2048).decode()
|
||||
# Check for end of stream
|
||||
if raw_msg == "":
|
||||
self.client_socket.close()
|
||||
if self._cage_dev:
|
||||
self._cage_dev.close()
|
||||
g.MAGNETOMETER.connected = False
|
||||
return
|
||||
# Process message
|
||||
for char in raw_msg:
|
||||
if char == '\n':
|
||||
msg = msg.rstrip() # Some systems will try to send \r characters... looking at you windows O_O
|
||||
try:
|
||||
response = self.handle_msg(msg)
|
||||
except Exception as e:
|
||||
ui_print("An error occurred while processing a client message")
|
||||
ui_print("Msg: {}".format(msg))
|
||||
ui_print(e)
|
||||
response = "err"
|
||||
self.client_socket.sendall((response + '\n').encode('utf-8'))
|
||||
msg = ''
|
||||
else:
|
||||
msg += char
|
||||
try:
|
||||
raw_msg = self.client_socket.recv(2048).decode()
|
||||
# Check for end of stream
|
||||
if raw_msg == "":
|
||||
self.client_socket.close()
|
||||
if self._cage_dev:
|
||||
self._cage_dev.close()
|
||||
g.MAGNETOMETER.connected = False
|
||||
return
|
||||
# Process message
|
||||
for char in raw_msg:
|
||||
if char == '\n':
|
||||
msg = msg.rstrip() # Some systems will try to send \r characters... looking at you windows O_O
|
||||
try:
|
||||
response = self.handle_msg(msg)
|
||||
except Exception as e:
|
||||
ui_print("An error occurred while processing a client message")
|
||||
ui_print("Msg: {}".format(msg))
|
||||
ui_print(e)
|
||||
response = "err"
|
||||
self.client_socket.sendall((response + '\n').encode('utf-8'))
|
||||
msg = ''
|
||||
else:
|
||||
msg += char
|
||||
except ConnectionResetError:
|
||||
ui_print("A connection was closed by the client.")
|
||||
|
||||
def handle_msg(self, message):
|
||||
""" Executes command logic and returns string response (for client). """
|
||||
|
||||
+65
-1
@@ -17,6 +17,7 @@ import os
|
||||
from os.path import exists
|
||||
import threading
|
||||
from datetime import datetime
|
||||
from math import pi
|
||||
|
||||
# import other project files:
|
||||
import src.globals as g
|
||||
@@ -822,6 +823,11 @@ class CalibrateMagnetometer(Frame):
|
||||
# Calibration parameters
|
||||
self.calibration_points_var = IntVar(value=8)
|
||||
self.calibration_interval_var = DoubleVar(value=5)
|
||||
# Calibration results
|
||||
self.sensitivity_result_vars = [StringVar(), StringVar(), StringVar()]
|
||||
self.angle_to_plane_result_vars = [StringVar(), StringVar(), StringVar()]
|
||||
self.angle_in_plane_result_vars = [StringVar(), StringVar(), StringVar()]
|
||||
self.residual_result_vars = [StringVar(), StringVar(), StringVar()]
|
||||
|
||||
# UI Elements
|
||||
row_counter = 0
|
||||
@@ -888,6 +894,60 @@ class CalibrateMagnetometer(Frame):
|
||||
calibration_procedure_progress.grid(row=0, column=1, padx=10, pady=10, sticky="we")
|
||||
row_counter += 1
|
||||
|
||||
# RIGHT COLUMN
|
||||
# Magnetometer calibration results
|
||||
row_counter = 0
|
||||
calibration_results_frame = LabelFrame(self.right_column, text="Ambient Field Results")
|
||||
calibration_results_frame.grid(row=row_counter, column=1, padx=(100, 0), pady=20, sticky="nw")
|
||||
for i, label in enumerate(['X', 'Y', 'Z']):
|
||||
axis_label = Label(calibration_results_frame, text=label)
|
||||
axis_label.grid(row=0, column=i + 1, padx=5, pady=5, sticky="nw")
|
||||
# Axis sensitivities
|
||||
sensitivity_results_label = Label(calibration_results_frame, text="Sensitivity:")
|
||||
sensitivity_results_label.grid(row=1, column=0, padx=5, pady=5, sticky="nw")
|
||||
for i in range(3):
|
||||
axis_data = Entry(calibration_results_frame,
|
||||
textvariable=self.sensitivity_result_vars[i],
|
||||
width=15,
|
||||
state='readonly')
|
||||
axis_data.grid(row=1, column=i + 1, padx=5, pady=5, sticky="nw")
|
||||
sensitivity_results_unit = Label(calibration_results_frame, text="-")
|
||||
sensitivity_results_unit.grid(row=1, column=4, padx=5, pady=5, sticky="nw")
|
||||
# Angle to XY coil plane
|
||||
angle_to_plane_label = Label(calibration_results_frame, text="Angle to XY plane:")
|
||||
angle_to_plane_label.grid(row=2, column=0, padx=5, pady=5, sticky="nw")
|
||||
for i in range(3):
|
||||
axis_data = Entry(calibration_results_frame,
|
||||
textvariable=self.angle_to_plane_result_vars[i],
|
||||
width=15,
|
||||
state='readonly')
|
||||
axis_data.grid(row=2, column=i + 1, padx=5, pady=5, sticky="nw")
|
||||
angle_to_plane_unit = Label(calibration_results_frame, text="°")
|
||||
angle_to_plane_unit.grid(row=2, column=4, padx=5, pady=5, sticky="nw")
|
||||
# Angle in XY coil plane
|
||||
angle_in_plane_label = Label(calibration_results_frame, text="Angle in XY plane:")
|
||||
angle_in_plane_label.grid(row=3, column=0, padx=5, pady=5, sticky="nw")
|
||||
for i in range(3):
|
||||
axis_data = Entry(calibration_results_frame,
|
||||
textvariable=self.angle_in_plane_result_vars[i],
|
||||
width=15,
|
||||
state='readonly')
|
||||
axis_data.grid(row=3, column=i + 1, padx=5, pady=5, sticky="nw")
|
||||
angle_in_plane_unit = Label(calibration_results_frame, text="°")
|
||||
angle_in_plane_unit.grid(row=3, column=4, padx=5, pady=5, sticky="nw")
|
||||
# Residual in system of equations
|
||||
residual_label = Label(calibration_results_frame, text="Residual:")
|
||||
residual_label.grid(row=4, column=0, padx=5, pady=5, sticky="nw")
|
||||
for i in range(3):
|
||||
axis_data = Entry(calibration_results_frame,
|
||||
textvariable=self.residual_result_vars[i],
|
||||
width=15,
|
||||
state='readonly')
|
||||
axis_data.grid(row=4, column=i + 1, padx=5, pady=5, sticky="nw")
|
||||
residual_unit = Label(calibration_results_frame, text="\u03BCT")
|
||||
residual_unit.grid(row=4, column=4, padx=5, pady=5, sticky="nw")
|
||||
row_counter += 1
|
||||
|
||||
# This starts an endless polling loop
|
||||
self.update_view()
|
||||
|
||||
@@ -940,7 +1000,11 @@ class CalibrateMagnetometer(Frame):
|
||||
self.start_calibration_button.configure(text="Running...", state=DISABLED)
|
||||
|
||||
def display_calibration_results(self, results):
|
||||
pass
|
||||
for i in range(3):
|
||||
self.sensitivity_result_vars[i].set("{:.3f}".format(results[i]['sensitivity']))
|
||||
self.angle_to_plane_result_vars[i].set("{:.3f}".format(results[i]['alpha'] * 180/pi))
|
||||
self.angle_in_plane_result_vars[i].set("{:.3f}".format(results[i]['beta'] * 180/pi))
|
||||
self.residual_result_vars[i].set("{:.3f}".format(results[i]['residual'] * 1e6))
|
||||
|
||||
def start_calibration_procedure(self):
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user