forked from zietzm/Helmholtz_Test_Bench
Added calibration method for magnetometers.
This commit is contained in:
+168
-2
@@ -23,7 +23,7 @@ import src.globals as g
|
||||
import src.csv_threading as csv
|
||||
import src.config_handling as config
|
||||
import src.csv_logging as log
|
||||
from src.calibration import AmbientFieldCalibration, CoilConstantCalibration
|
||||
from src.calibration import AmbientFieldCalibration, CoilConstantCalibration, MagnetometerCalibration
|
||||
from src.exceptions import DeviceAccessError
|
||||
from src.utility import ui_print
|
||||
import src.helmholtz_cage_device as helmholtz_cage_device
|
||||
@@ -63,6 +63,7 @@ class HelmholtzGUI(Tk):
|
||||
for P in [ManualMode,
|
||||
HardwareConfiguration,
|
||||
CalibrateAmbientField,
|
||||
CalibrateMagnetometer,
|
||||
ExecuteCSVMode,
|
||||
ConfigureLogging]: # do this for every mode page
|
||||
page = P(main_area, self) # initialize the page with the main_area frame as the parent
|
||||
@@ -97,12 +98,13 @@ class TopMenu:
|
||||
menu = Menu(window) # initialize Menu object
|
||||
window.config(menu=menu) # put menu at the top of the window
|
||||
|
||||
mode_selector = Menu(menu) # create a submenu object
|
||||
mode_selector = Menu(menu, tearoff=0) # create a submenu object
|
||||
menu.add_cascade(label="Menu", menu=mode_selector) # add a dropdown with the submenu object
|
||||
# create the different options in the dropdown:
|
||||
mode_selector.add_command(label="Static Manual Input", command=self.manual_mode)
|
||||
mode_selector.add_command(label="Execute CSV Sequence", command=self.execute_csv_mode)
|
||||
mode_selector.add_command(label="Calibrate Ambient Field", command=self.calibrate_ambient)
|
||||
mode_selector.add_command(label="Calibrate Magnetometer", command=self.calibrate_magnetometer)
|
||||
mode_selector.add_separator()
|
||||
mode_selector.add_command(label="Configure Data Logging", command=self.logging)
|
||||
mode_selector.add_command(label="Settings...", command=self.configuration)
|
||||
@@ -116,6 +118,9 @@ class TopMenu:
|
||||
def calibrate_ambient(self):
|
||||
self.window.show_frame(CalibrateAmbientField)
|
||||
|
||||
def calibrate_magnetometer(self):
|
||||
self.window.show_frame(CalibrateMagnetometer)
|
||||
|
||||
def execute_csv_mode(self): # switch to the CSV execution page
|
||||
self.window.show_frame(ExecuteCSVMode)
|
||||
|
||||
@@ -789,6 +794,167 @@ class CalibrateAmbientField(Frame):
|
||||
messagebox.showwarning("Calibration failed", "Failed to start calibration:\n{}".format(e))
|
||||
|
||||
|
||||
class CalibrateMagnetometer(Frame):
|
||||
def __init__(self, parent, controller):
|
||||
Frame.__init__(self, parent)
|
||||
self.parent = parent
|
||||
self.controller = controller
|
||||
|
||||
# To center window
|
||||
# self.columnconfigure(0, weight=1)
|
||||
self.rowconfigure(0, weight=1)
|
||||
self.left_column = Frame(self)
|
||||
self.left_column.grid(row=0, column=0, sticky="nsew")
|
||||
self.right_column = Frame(self)
|
||||
self.right_column.grid(row=0, column=1, sticky="nsew")
|
||||
self.left_column.rowconfigure(3, weight=1)
|
||||
|
||||
# Thread variables
|
||||
self.calibration_thread = None
|
||||
self.view_mpi_queue = Queue() # Receives status information from calibration procedure threads.
|
||||
|
||||
# UI variables
|
||||
self.connected_state_var = StringVar(value="Not connected")
|
||||
self.field_value_vars = [StringVar(value="No data"),
|
||||
StringVar(value="No data"),
|
||||
StringVar(value="No data")]
|
||||
self.calibration_procedure_progress_var = IntVar(value=0)
|
||||
# Calibration parameters
|
||||
self.calibration_points_var = IntVar(value=8)
|
||||
self.calibration_interval_var = DoubleVar(value=5)
|
||||
|
||||
# UI Elements
|
||||
row_counter = 0
|
||||
|
||||
# Create headline
|
||||
header = Label(self.left_column, text="Magnetometer Calibration", font=HEADER_FONT)
|
||||
header.grid(row=row_counter, column=0, columnspan=2, padx=100, pady=20, sticky="nw")
|
||||
row_counter += 1
|
||||
|
||||
# Magnetometer connected indicator
|
||||
connected_status_frame = Frame(self.left_column)
|
||||
connected_status_frame.grid(row=row_counter, column=0, sticky="nw")
|
||||
connected_label = Label(connected_status_frame, text="Magnetometer state:", font=SUB_HEADER_FONT)
|
||||
connected_label.grid(row=0, column=0, padx=10, pady=20, sticky="nw")
|
||||
self.connected_state_label = Label(connected_status_frame, textvariable=self.connected_state_var, fg="red")
|
||||
self.connected_state_label.grid(row=0, column=1, padx=10, pady=20, sticky="nw")
|
||||
row_counter += 1
|
||||
|
||||
# Magnetometer field data grid
|
||||
field_data_frame = Frame(self.left_column)
|
||||
field_data_frame.grid(row=row_counter, column=0, sticky="nw")
|
||||
field_data_label = Label(field_data_frame, text="Field data:", font=SUB_HEADER_FONT)
|
||||
field_data_label.grid(row=0, column=0, padx=10, pady=3, sticky="nw")
|
||||
axis_labels = ['X:', 'Y:', 'Z:']
|
||||
for i in range(3):
|
||||
field_data_axis_label = Label(field_data_frame, text=axis_labels[i])
|
||||
field_data_axis_label.grid(row=i, column=1, padx=10, pady=3)
|
||||
|
||||
field_data_axis_data = Label(field_data_frame, textvariable=self.field_value_vars[i])
|
||||
field_data_axis_data.grid(row=i, column=2, padx=(20, 0), pady=3)
|
||||
|
||||
field_data_axis_units = Label(field_data_frame, text="\u03BCT")
|
||||
field_data_axis_units.grid(row=i, column=3, padx=5, pady=3)
|
||||
row_counter += 1
|
||||
|
||||
# Centered controls
|
||||
controls_frame = Frame(self.left_column)
|
||||
controls_frame.grid(row=row_counter, column=0, sticky="sw")
|
||||
# Number of calibration points
|
||||
calibration_point_nr_label = Label(controls_frame, text="# of calibration points")
|
||||
calibration_point_nr_label.grid(row=0, column=0, pady=5, sticky="w")
|
||||
calibration_point_nr_entry = Entry(controls_frame, textvariable=self.calibration_points_var)
|
||||
calibration_point_nr_entry.grid(row=0, column=1, pady=5, sticky="w")
|
||||
# Measurement interval
|
||||
calibration_point_nr_label = Label(controls_frame, text="Measurement interval [s]")
|
||||
calibration_point_nr_label.grid(row=1, column=0, pady=5, sticky="w")
|
||||
calibration_point_nr_entry = Entry(controls_frame, textvariable=self.calibration_interval_var)
|
||||
calibration_point_nr_entry.grid(row=1, column=1, pady=5, sticky="w")
|
||||
# Calibration start buttons
|
||||
start_button_frame = Frame(controls_frame)
|
||||
start_button_frame.grid(row=2, column=0, columnspan=2)
|
||||
self.start_calibration_button = Button(start_button_frame, text="Start Calibration",
|
||||
command=self.start_calibration_procedure,
|
||||
pady=5, padx=5, font=SMALL_BUTTON_FONT)
|
||||
self.start_calibration_button.grid(row=0, column=0, padx=10, pady=(30, 10))
|
||||
# Calibration progress bar
|
||||
progress_bar_frame = Frame(controls_frame)
|
||||
progress_bar_frame.grid(row=3, column=0, columnspan=2)
|
||||
calibration_procedure_progress_label = Label(progress_bar_frame, text="Progress:")
|
||||
calibration_procedure_progress_label.grid(row=0, column=0, padx=10, pady=10)
|
||||
calibration_procedure_progress = ttk.Progressbar(progress_bar_frame,
|
||||
length=240,
|
||||
variable=self.calibration_procedure_progress_var)
|
||||
calibration_procedure_progress.grid(row=0, column=1, padx=10, pady=10, sticky="we")
|
||||
row_counter += 1
|
||||
|
||||
# This starts an endless polling loop
|
||||
self.update_view()
|
||||
|
||||
def page_switch(self):
|
||||
# every class in the UI needs this, even if it doesn't do anything
|
||||
pass
|
||||
|
||||
def update_view(self):
|
||||
# Get new connected status
|
||||
if g.MAGNETOMETER.connected:
|
||||
self.connected_state_var.set("connected")
|
||||
self.connected_state_label.configure(fg="green")
|
||||
else:
|
||||
self.connected_state_var.set("Not connected")
|
||||
self.connected_state_label.configure(fg="red")
|
||||
|
||||
# Get new field data
|
||||
new_field = g.MAGNETOMETER.field
|
||||
for i in range(3):
|
||||
# Display in uT
|
||||
self.field_value_vars[i].set("{:.3f}".format(new_field[i] * 1e6))
|
||||
|
||||
# Get mpi messages from calibration procedures
|
||||
try:
|
||||
while True:
|
||||
msg = self.view_mpi_queue.get(block=False)
|
||||
cmd = msg['cmd']
|
||||
arg = msg['arg']
|
||||
if cmd == 'finished':
|
||||
self.reactivate_buttons()
|
||||
elif cmd == 'failed':
|
||||
messagebox.showerror("Calibration error", "Error occured during calibration:\n{}".format(arg))
|
||||
self.reactivate_buttons()
|
||||
elif cmd == 'progress':
|
||||
self.calibration_procedure_progress_var.set(min(int(arg*100), 100))
|
||||
elif cmd == 'calibration_data':
|
||||
self.display_calibration_results(arg)
|
||||
else:
|
||||
ui_print("Error: Unexpected mpi command '{}' in CalibrationTool".format(cmd))
|
||||
except queue.Empty:
|
||||
pass
|
||||
|
||||
self.controller.after(500, self.update_view)
|
||||
|
||||
def reactivate_buttons(self):
|
||||
self.start_calibration_button.configure(text="Start Calibration", state=NORMAL)
|
||||
self.calibration_procedure_progress_var.set(0)
|
||||
|
||||
def deactivate_buttons(self):
|
||||
self.start_calibration_button.configure(text="Running...", state=DISABLED)
|
||||
|
||||
def display_calibration_results(self, results):
|
||||
pass
|
||||
|
||||
def start_calibration_procedure(self):
|
||||
try:
|
||||
calibration_points = self.calibration_points_var.get()
|
||||
calibration_interval = self.calibration_interval_var.get()
|
||||
self.calibration_thread = MagnetometerCalibration(self.view_mpi_queue,
|
||||
calibration_points,
|
||||
calibration_interval)
|
||||
self.calibration_thread.start()
|
||||
self.deactivate_buttons()
|
||||
except (DeviceAccessError, TclError) as e:
|
||||
messagebox.showwarning("Calibration failed", "Failed to start calibration:\n{}".format(e))
|
||||
|
||||
|
||||
class HardwareConfiguration(Frame):
|
||||
"""Settings window to set program constants"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user