Implemented coil constant calibration

This commit is contained in:
2021-08-04 17:48:58 +02:00
parent 3596733843
commit 89ed805411
2 changed files with 91 additions and 3 deletions
+47 -1
View File
@@ -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
View File
@@ -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()