forked from zietzm/Helmholtz_Test_Bench
Implemented coil constant calibration
This commit is contained in:
+47
-1
@@ -1,3 +1,4 @@
|
||||
import math
|
||||
import time
|
||||
from datetime import datetime
|
||||
from threading import Thread
|
||||
@@ -103,6 +104,10 @@ class AmbientFieldCalibration(Thread):
|
||||
|
||||
|
||||
class CoilConstantCalibration(Thread):
|
||||
MEASUREMENT_RANGE = 3 # A. Will extend into negative and positive sign
|
||||
MEASUREMENT_POINTS = 6 # Excludes zero. eg 0.5, 1, 1.5, 2
|
||||
SETTLE_TIME = 0.5 # Time until new measurement is ready after setting current
|
||||
|
||||
def __init__(self, view_queue):
|
||||
Thread.__init__(self)
|
||||
self.view_queue = view_queue
|
||||
@@ -135,8 +140,49 @@ class CoilConstantCalibration(Thread):
|
||||
# All generated fields will be compared to this using a simple difference method
|
||||
ambient_field = g.MAGNETOMETER.field
|
||||
# The coil constant must be determined for every axis
|
||||
currents = np.linspace(-self.MEASUREMENT_RANGE, self.MEASUREMENT_RANGE, self.MEASUREMENT_POINTS * 2 + 1)
|
||||
currents = np.delete(currents, self.MEASUREMENT_POINTS)
|
||||
coil_constants = np.zeros(3)
|
||||
k_deviations = np.zeros(3)
|
||||
for i in range(3):
|
||||
pass
|
||||
k_samples = []
|
||||
for c_idx, c in enumerate(currents):
|
||||
# Set new progress indicator for UI
|
||||
self.put_message('progress', ((c_idx / (self.MEASUREMENT_POINTS * 2)) + i) / 3)
|
||||
|
||||
# Set current
|
||||
c_vec = [0, 0, 0]
|
||||
c_vec[i] = c
|
||||
self.cage_dev.set_signed_currents(c_vec)
|
||||
time.sleep(self.SETTLE_TIME)
|
||||
|
||||
# Get coil constant
|
||||
field_diff_mag = np.linalg.norm(g.MAGNETOMETER.field - ambient_field)
|
||||
k_samples.append(field_diff_mag / c)
|
||||
|
||||
# Average samples for axis
|
||||
coil_constants[i] = np.average(k_samples)
|
||||
k_deviations[i], _ = self.calculate_standard_deviation(k_samples)
|
||||
|
||||
# Put device into an off and ready state
|
||||
self.cage_dev.idle()
|
||||
|
||||
self.put_message('coil_constant_results', {'k': coil_constants,
|
||||
'k_dev': k_deviations})
|
||||
|
||||
@staticmethod
|
||||
def calculate_standard_deviation(data):
|
||||
n = len(data)
|
||||
average = 0
|
||||
for datapoint in data:
|
||||
average += datapoint / n
|
||||
std_dev = 0
|
||||
deviations = []
|
||||
for datapoint in data:
|
||||
std_dev += (datapoint - average) ** 2
|
||||
deviations.append(datapoint - average)
|
||||
std_dev = math.sqrt(std_dev / n)
|
||||
return std_dev, deviations
|
||||
|
||||
def put_message(self, command, arg):
|
||||
self.view_queue.put({'cmd': command, 'arg': arg})
|
||||
+44
-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
|
||||
from src.calibration import AmbientFieldCalibration, CoilConstantCalibration
|
||||
from src.exceptions import DeviceAccessError
|
||||
from src.utility import ui_print
|
||||
import src.helmholtz_cage_device as helmholtz_cage_device
|
||||
@@ -547,9 +547,13 @@ class CalibrateAmbientField(Frame):
|
||||
StringVar(value="No data"),
|
||||
StringVar(value="No data")]
|
||||
self.calibration_procedure_progress_var = IntVar(value=0)
|
||||
# Contains results for ambient field calibration
|
||||
self.ambient_field_result_vars = [StringVar(), StringVar(), StringVar()]
|
||||
self.ambient_field_ut_result_vars = [StringVar(), StringVar(), StringVar()]
|
||||
self.ambient_field_residual_vars = [StringVar(), StringVar(), StringVar()]
|
||||
# Contains results for coil constant calibration
|
||||
self.coil_constant_vars = [StringVar(), StringVar(), StringVar()]
|
||||
self.coil_constant_dev_vars = [StringVar(), StringVar(), StringVar()]
|
||||
|
||||
row_counter = 0
|
||||
|
||||
@@ -648,6 +652,36 @@ class CalibrateAmbientField(Frame):
|
||||
axis_data.grid(row=3, column=i+1, padx=5, pady=5, sticky="nw")
|
||||
ambient_field_residual_unit = Label(ambient_field_results_frame, text="\u03BCT")
|
||||
ambient_field_residual_unit.grid(row=3, column=4, padx=5, pady=5, sticky="nw")
|
||||
row_counter += 1
|
||||
|
||||
# Coil constant results
|
||||
coil_constants_results_frame = LabelFrame(self.right_column, text="Coil Constants")
|
||||
coil_constants_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(coil_constants_results_frame, text=label)
|
||||
axis_label.grid(row=0, column=i + 1, padx=5, pady=5, sticky="nw")
|
||||
# Coil constants
|
||||
coil_constants_results_label = Label(coil_constants_results_frame, text="K:")
|
||||
coil_constants_results_label.grid(row=1, column=0, padx=5, pady=5, sticky="nw")
|
||||
for i in range(3):
|
||||
axis_data = Entry(coil_constants_results_frame,
|
||||
textvariable=self.coil_constant_vars[i],
|
||||
width=15,
|
||||
state='readonly')
|
||||
axis_data.grid(row=1, column=i + 1, padx=5, pady=5, sticky="nw")
|
||||
coil_constants_results_unit = Label(coil_constants_results_frame, text="\u03BCT/A")
|
||||
coil_constants_results_unit.grid(row=1, column=4, padx=5, pady=5, sticky="nw")
|
||||
# Standard deviation of coil constants
|
||||
coil_constants_dev_results_label = Label(coil_constants_results_frame, text="K Std. Dev.:")
|
||||
coil_constants_dev_results_label.grid(row=2, column=0, padx=5, pady=5, sticky="nw")
|
||||
for i in range(3):
|
||||
axis_data = Entry(coil_constants_results_frame,
|
||||
textvariable=self.coil_constant_dev_vars[i],
|
||||
width=15,
|
||||
state='readonly')
|
||||
axis_data.grid(row=2, column=i + 1, padx=5, pady=5, sticky="nw")
|
||||
coil_constants_dev_results_unit = Label(coil_constants_results_frame, text="\u03BCT/A")
|
||||
coil_constants_dev_results_unit.grid(row=2, column=4, padx=5, pady=5, sticky="nw")
|
||||
|
||||
# This starts an endless polling loop
|
||||
self.update_view()
|
||||
@@ -686,6 +720,8 @@ class CalibrateAmbientField(Frame):
|
||||
self.calibration_procedure_progress_var.set(min(int(arg*100), 100))
|
||||
elif cmd == 'ambient_data':
|
||||
self.update_ambient_calibration_results(arg)
|
||||
elif cmd == 'coil_constant_results':
|
||||
self.update_coil_constant_results(arg)
|
||||
else:
|
||||
ui_print("Error: Unexpected mpi command '{}' in CalibrationTool".format(cmd))
|
||||
except queue.Empty:
|
||||
@@ -708,6 +744,12 @@ class CalibrateAmbientField(Frame):
|
||||
self.ambient_field_ut_result_vars[i].set("{:.3f}".format(results['ambient_ut'][i]))
|
||||
self.ambient_field_residual_vars[i].set("{:.3f}".format(results['residual'][i] * 1e6))
|
||||
|
||||
def update_coil_constant_results(self, results):
|
||||
for i in range(3):
|
||||
# Remember to convert from T/A to microT/A
|
||||
self.coil_constant_vars[i].set("{:.3f}".format(results['k'][i] * 1e6))
|
||||
self.coil_constant_dev_vars[i].set("{:.3f}".format(results['k_dev'][i] * 1e6))
|
||||
|
||||
def calibration_procedure_ambient(self):
|
||||
try:
|
||||
self.calibration_ambient_thread = AmbientFieldCalibration(self.view_mpi_queue)
|
||||
@@ -719,7 +761,7 @@ class CalibrateAmbientField(Frame):
|
||||
|
||||
def calibration_procedure_coil_constants(self):
|
||||
try:
|
||||
self.calibration_coil_constants_thread = AmbientFieldCalibration(self.view_mpi_queue)
|
||||
self.calibration_coil_constants_thread = CoilConstantCalibration(self.view_mpi_queue)
|
||||
self.calibration_coil_constants_thread.start()
|
||||
self.start_k_calibration_button.configure(text="Running")
|
||||
self.deactivate_buttons()
|
||||
|
||||
Reference in New Issue
Block a user