forked from zietzm/Helmholtz_Test_Bench
various changes
- added checkbox for ambient field compensation - moved part of axis setup to axis.__init__
This commit is contained in:
1 parent
89a8a59377
commit
5f23c71bff
4 files changed
+68
-33
No files matched your search
+50
-8
@@ -86,8 +86,8 @@ class ManualMode(Frame):
|
||||
self.input_mode = StringVar()
|
||||
# make dictionary with information on all modes.
|
||||
# content: [function to call on button press, unit text to be displayed]
|
||||
self.modes = {"Magnetic Field": [self.execute_field, "\u03BCT"],
|
||||
"Current": [self.execute_current, "A"]}
|
||||
self.modes = {"Magnetic Field": [self.execute_field, "\u03BCT", self.update_max_fields],
|
||||
"Current": [self.execute_current, "A", self.update_max_currents]}
|
||||
# "Raw Current": [self.input_raw_current, "A"]} ToDo (optional): make functions for this
|
||||
self.unit = StringVar()
|
||||
default_mode = list(self.modes.keys())[0]
|
||||
@@ -107,10 +107,12 @@ class ManualMode(Frame):
|
||||
self.entries_frame.grid_rowconfigure(ALL, weight=1)
|
||||
self.entries_frame.grid_columnconfigure(ALL, weight=1)
|
||||
self.entries_frame.grid_columnconfigure(2, weight=1, minsize=20)
|
||||
self.entries_frame.grid_columnconfigure(3, weight=1, minsize=110)
|
||||
self.entries_frame.grid(row=row_counter, column=0)
|
||||
|
||||
entry_texts = ["X-Axis:", "Y-Axis:", "Z-Axis:"]
|
||||
self.entry_vars = [StringVar() for _ in range(len(entry_texts))]
|
||||
self.entry_vars = [StringVar() for _ in range(3)]
|
||||
self.max_value_vars = [StringVar() for _ in range(3)]
|
||||
row = 0
|
||||
for text in entry_texts:
|
||||
field = ttk.Entry(self.entries_frame, textvariable=self.entry_vars[row])
|
||||
@@ -120,19 +122,33 @@ class ManualMode(Frame):
|
||||
axis_label.grid(row=row, column=0, sticky=W)
|
||||
unit_label = Label(self.entries_frame, textvariable=self.unit)
|
||||
unit_label.grid(row=row, column=2, sticky=W)
|
||||
max_value_label = Label(self.entries_frame, textvariable=self.max_value_vars[row])
|
||||
max_value_label.grid(row=row, column=3, sticky=W)
|
||||
row = row + 1
|
||||
|
||||
row_counter = row_counter + 1
|
||||
row_counter += 1
|
||||
|
||||
# Setup execute button
|
||||
# setup checkbox for compensating ambient field
|
||||
checkbox_frame = Frame(self, padx=20)
|
||||
checkbox_frame.grid(row=row_counter, column=0, sticky=W)
|
||||
|
||||
self.compensate = IntVar(value=1)
|
||||
self.compensate_checkbox = Checkbutton(checkbox_frame, text="Compensate ambient field",
|
||||
variable=self.compensate, onvalue=1, offvalue=0)
|
||||
self.compensate_checkbox.pack(side="left")
|
||||
|
||||
row_counter += 1
|
||||
|
||||
# Setup buttons
|
||||
self.buttons_frame = Frame(self)
|
||||
self.buttons_frame.grid_rowconfigure(ALL, weight=1)
|
||||
self.buttons_frame.grid_columnconfigure(ALL, weight=1)
|
||||
self.buttons_frame.grid_columnconfigure(2, weight=1, minsize=20)
|
||||
self.buttons_frame.grid(row=row_counter, column=0)
|
||||
|
||||
Label(self.buttons_frame, text="").grid(row=row_counter, column=0) # add spacer
|
||||
Label(self.buttons_frame, text="").grid(row=0, column=0) # add spacer
|
||||
|
||||
# add button for executing the current entries
|
||||
execute_button = Button(self.buttons_frame, text="Execute!", command=self.execute,
|
||||
pady=5, padx=5, font=BIG_BUTTON_FONT)
|
||||
execute_button.grid(row=row_counter, column=0)
|
||||
@@ -149,9 +165,33 @@ class ManualMode(Frame):
|
||||
|
||||
self.input_mode.trace_add('write', self.change_mode_callback) # call mode change function on dropdown change
|
||||
self.input_mode.set(default_mode) # call up default mode at the start
|
||||
self.compensate.trace_add('write', self.change_mode_callback) # call mode change function on dropdown change
|
||||
|
||||
def change_mode_callback(self, var, index, mode): # not sure what the parameters are for, but they are necessary
|
||||
self.unit.set(self.modes[self.input_mode.get()][1]) # change unit text
|
||||
self.modes[self.input_mode.get()][2]() # update max values
|
||||
|
||||
def update_max_fields(self): # update labels with maximum allowable field values
|
||||
self.compensate_checkbox.config(state=NORMAL)
|
||||
i = 0
|
||||
for val in self.max_value_vars:
|
||||
comp = self.compensate.get()
|
||||
if comp == 0:
|
||||
field = g.AXES[i].max_field * 1e6
|
||||
elif comp == 1:
|
||||
field = g.AXES[i].max_comp_field * 1e6
|
||||
else:
|
||||
field = [0, 0]
|
||||
func.ui_print("Unexpected value encountered: compensate =", comp)
|
||||
val.set("(%0.1f to %0.1f \u03BCT)" % (field[0], field[1]))
|
||||
i += 1
|
||||
|
||||
def update_max_currents(self): # update labels with maximum allowable current values
|
||||
self.compensate_checkbox.config(state=DISABLED)
|
||||
i = 0
|
||||
for val in self.max_value_vars:
|
||||
val.set("(%0.2f to %0.2f A)" % (-g.AXES[i].max_amps, g.AXES[i].max_amps))
|
||||
i += 1
|
||||
|
||||
def execute(self):
|
||||
function_to_call = self.modes[self.input_mode.get()][0] # get function of appropriate mode
|
||||
@@ -167,7 +207,7 @@ class ManualMode(Frame):
|
||||
def execute_field(vector):
|
||||
func.ui_print("field executing", vector)
|
||||
try:
|
||||
func.set_field_simple(vector*1e-6) # ToDo: change to set_field
|
||||
func.set_field_simple(vector * 1e-6) # ToDo: change to set_field
|
||||
except ValueError as e:
|
||||
func.ui_print(e)
|
||||
|
||||
@@ -253,7 +293,7 @@ class StatusDisplay(Frame):
|
||||
controller.after(500, lambda: self.update_labels(controller))
|
||||
|
||||
|
||||
class OutputConsole(Frame):
|
||||
class OutputConsole(Frame): # console to print stuff in
|
||||
|
||||
def __init__(self, parent):
|
||||
Frame.__init__(self, parent, relief=SUNKEN, bd=1)
|
||||
@@ -263,6 +303,8 @@ class OutputConsole(Frame):
|
||||
|
||||
scrollbar = Scrollbar(self)
|
||||
self.console = Text(self)
|
||||
self.console.bind("<Key>", lambda e: "break") # prevent user input into the console
|
||||
|
||||
scrollbar.grid(row=0, column=1, sticky="ns")
|
||||
self.console.grid(row=0, column=0, sticky="nesw")
|
||||
scrollbar.config(command=self.console.yview)
|
||||
|
||||
+12
-22
@@ -20,15 +20,17 @@ class Axis:
|
||||
self.name = g.AXIS_NAMES[index]
|
||||
self.port = g.ports[index]
|
||||
|
||||
self.resistance = 0 # [Ohm]
|
||||
# maximum allowable values to pass through this circuit
|
||||
self.max_watts = 0 # [W]
|
||||
self.max_amps = 0 # [A]
|
||||
self.max_volts = 0 # [V]
|
||||
self.resistance = g.RESISTANCES[index]
|
||||
self.max_watts = g.MAX_WATTS[index]
|
||||
self.max_amps = np.sqrt(self.max_watts / self.resistance)
|
||||
self.max_volts = g.MAX_VOLTS[index]
|
||||
|
||||
self.coil_constant = 0 # coil constant of this axis [T/A]
|
||||
self.ambient_field = 0 # ambient field in this axis [T]
|
||||
# ToDo: get this info from settings file
|
||||
self.coil_constant = g.COIL_CONST[index]
|
||||
self.ambient_field = g.AMBIENT_FIELD[index]
|
||||
|
||||
max_field = self.max_amps * self.coil_constant # max field reachable in this axis
|
||||
self.max_field = np.array([-max_field, max_field])
|
||||
self.max_comp_field = np.array([self.ambient_field - max_field, self.ambient_field + max_field])
|
||||
|
||||
# dynamic information
|
||||
self.connected = "Not Connected"
|
||||
@@ -142,7 +144,7 @@ class ArduinoCtrl(Arduino):
|
||||
self.pinMode(pin, "Output")
|
||||
self.digitalWrite(pin, "LOW")
|
||||
except Exception as e:
|
||||
ui_print("Connection to Arduino failed:", e)
|
||||
ui_print("Connection to Arduino failed.", e)
|
||||
self.connected = "Not Connected"
|
||||
else:
|
||||
self.connected = "Connected"
|
||||
@@ -172,7 +174,7 @@ class ArduinoCtrl(Arduino):
|
||||
def ui_print(*content): # prints text to built in console
|
||||
output = ""
|
||||
for text in content:
|
||||
output = " ".join((output, str(text)))
|
||||
output = " ".join((output, str(text))) # append content
|
||||
if g.app is not None:
|
||||
output = "".join(("\n", output)) # begin new line each time
|
||||
g.app.OutputConsole.console.insert(END, output) # print to console
|
||||
@@ -232,18 +234,6 @@ def setup_axes(): # creates device objects for all PSUs and sets their values
|
||||
g.AXES.append(g.Z_AXIS)
|
||||
|
||||
ui_print("") # new line
|
||||
i = 0
|
||||
for axis in g.AXES: # ToDo: move to axis init
|
||||
axis.resistance = g.RESISTANCES[i]
|
||||
axis.max_watts = g.MAX_WATTS[i]
|
||||
axis.max_amps = np.sqrt(axis.max_watts / axis.resistance)
|
||||
ui_print(axis.name, "max Current:", axis.max_amps)
|
||||
axis.max_volts = g.MAX_VOLTS[i]
|
||||
|
||||
axis.coil_constant = g.COIL_CONST[i]
|
||||
axis.ambient_field = g.AMBIENT_FIELD[i]
|
||||
i = i + 1
|
||||
ui_print("")
|
||||
|
||||
|
||||
def activate_all(): # enables remote control and output on all PSUs and channels
|
||||
|
||||
@@ -11,6 +11,9 @@ try: # start normal operations
|
||||
print("\nOpening User Interface...")
|
||||
|
||||
g.app = HelmholtzGUI()
|
||||
func.ui_print("Program Initialized")
|
||||
func.ui_print("Starting setup...")
|
||||
func.setup_axes() # initiate communication, set handles
|
||||
g.app.mainloop()
|
||||
g.app = None # reset to None so nothing tries to print in the UI output
|
||||
|
||||
|
||||
+3
-3
@@ -11,9 +11,9 @@ AXES = None # list containing [X_AXIS, Y_AXIS, Z_AXIS]
|
||||
|
||||
# Constants:
|
||||
COIL_CONST = np.array([38.6, 38.45, 37.9]) * 1e-6 # Coil constants [x,y,z] in T/A
|
||||
AMBIENT_FIELD = np.array([80, 80, 80]) * 1e-6 # ambient magnetic field in measurement area, to be cancelled out
|
||||
RESISTANCES = np.array([4.5, 8, 4]) # resistance of [x,y,z] circuits
|
||||
MAX_WATTS = np.array([8, 25, 8]) # max. allowed power for [x,y,z] circuits
|
||||
AMBIENT_FIELD = np.array([30, 30, 30]) * 1e-6 # ambient magnetic field in measurement area, to be cancelled out
|
||||
RESISTANCES = np.array([1.7, 1.7, 1.7]) # resistance of [x,y,z] circuits
|
||||
MAX_WATTS = np.array([15, 15, 15]) # max. allowed power for [x,y,z] circuits
|
||||
MAX_VOLTS = [16, 16, 16] # max. allowed voltage, limited to 16V by used diodes!
|
||||
|
||||
# COM-Ports for power supply units:
|
||||
|
||||
Reference in new issue
Block a user