forked from zietzm/Helmholtz_Test_Bench
code cleanup
This commit is contained in:
@@ -1,29 +0,0 @@
|
||||
import time
|
||||
|
||||
from Arduino import Arduino
|
||||
|
||||
print("Searching for Arduino...")
|
||||
board = Arduino()
|
||||
print("Arduino found.")
|
||||
board.pinMode(15, "Output")
|
||||
board.pinMode(16, "Output")
|
||||
board.pinMode(17, "Output")
|
||||
board.digitalWrite(15, "LOW")
|
||||
board.digitalWrite(16, "LOW")
|
||||
board.digitalWrite(17, "LOW")
|
||||
|
||||
|
||||
i = 0
|
||||
while i <= 1:
|
||||
print("running: ", i)
|
||||
for var in [15,16,17]:
|
||||
board.digitalWrite(var, "HIGH")
|
||||
time.sleep(0.5)
|
||||
time.sleep(5)
|
||||
for var in [15,16,17]:
|
||||
board.digitalWrite(var, "LOW")
|
||||
time.sleep(0.5)
|
||||
time.sleep(2)
|
||||
i = i + 1
|
||||
|
||||
board.close()
|
||||
@@ -1,72 +0,0 @@
|
||||
# import platform
|
||||
import time as t
|
||||
import numpy as np
|
||||
import globals as g
|
||||
import cage_func as func
|
||||
from pyps2000b import PS2000B
|
||||
|
||||
# User Inputs/Configuration----------------------------------
|
||||
Test1 = 0
|
||||
Test2 = 1
|
||||
Test3 = 0
|
||||
Test4 = 0
|
||||
|
||||
# Constants:
|
||||
g.COIL_CONST = np.array([38.6, 38.45, 37.9]) * 1e-9 # Coil constants [x,y,z] in T/A
|
||||
g.AMBIENT_FIELD = np.array([80]) * 1e-6 # ambient magnetic field in measurement area, to be cancelled out
|
||||
g.RESISTANCES = np.array([3.9, 3.9, 1]) # resistance of [x,y,z] circuits
|
||||
g.MAX_WATTS = np.array([8, 8, 0]) # max. allowed power for [x,y,z] circuits
|
||||
|
||||
# COM-Ports for power supply units:
|
||||
XY_PORT = "COM7"
|
||||
g.XY_DEVICE = PS2000B.PS2000B(XY_PORT)
|
||||
|
||||
g.MAX_AMPS = np.sqrt(g.MAX_WATTS / g.RESISTANCES)
|
||||
#print(g.MAX_AMPS)
|
||||
|
||||
|
||||
'''def print_status():
|
||||
print("Output 1:")
|
||||
func.print_status(g.X_AXIS)
|
||||
print("Output 2:")
|
||||
func.print_status(g.Y_AXIS)'''
|
||||
|
||||
|
||||
func.set_to_zero(g.XY_DEVICE)
|
||||
#print_status()
|
||||
t.sleep(3)
|
||||
|
||||
if Test1 == 1:
|
||||
print("setting")
|
||||
g.XY_DEVICE.voltage1 = 5
|
||||
g.XY_DEVICE.current1 = 1
|
||||
g.XY_DEVICE.enable_all()
|
||||
t.sleep(1)
|
||||
#print_status()
|
||||
t.sleep(5)
|
||||
print("setting to zero")
|
||||
func.set_to_zero(g.XY_DEVICE)
|
||||
|
||||
if Test2 == 1:
|
||||
print("setting current")
|
||||
g.XY_DEVICE.set_current(0.2, 0)
|
||||
g.XY_DEVICE.set_voltage(5, 0)
|
||||
g.XY_DEVICE.enable_all()
|
||||
t.sleep(1)
|
||||
#print_status()
|
||||
t.sleep(5)
|
||||
func.set_to_zero(g.XY_DEVICE)
|
||||
|
||||
if Test4 == 1:
|
||||
func.set_axis_current(g.XY_DEVICE, 0.2)
|
||||
t.sleep(1)
|
||||
print_status()
|
||||
t.sleep(10)
|
||||
func.set_to_zero(g.XY_DEVICE)
|
||||
t.sleep(1)
|
||||
|
||||
#print_status()
|
||||
|
||||
g.XY_DEVICE.disable_all()
|
||||
|
||||
#print_status()
|
||||
+26
-20
@@ -21,7 +21,7 @@ class HelmholtzGUI(Tk):
|
||||
|
||||
self.Menu = TopMenu(self) # displays menu bar at the top
|
||||
|
||||
mainArea = Frame(self)
|
||||
mainArea = Frame(self, padx=20, pady=20)
|
||||
mainArea.pack(side="top", fill="both", expand=False)
|
||||
|
||||
mainArea.grid_rowconfigure(0, weight=1)
|
||||
@@ -163,7 +163,7 @@ class ManualMode(Frame):
|
||||
execute_button.grid(row=row_counter, column=0, padx=5)
|
||||
|
||||
# add button for reinitialization
|
||||
reinit_button = Button(self.buttons_frame, text="Reinitialize", command=func.setup_axes,
|
||||
reinit_button = Button(self.buttons_frame, text="Reinitialize", command=func.setup_all,
|
||||
pady=5, padx=5, font=BIG_BUTTON_FONT)
|
||||
reinit_button.grid(row=row_counter, column=1, padx=5)
|
||||
|
||||
@@ -179,6 +179,7 @@ class ManualMode(Frame):
|
||||
def page_switch(self): # function that is called when switching to this page in the UI
|
||||
self.modes[self.input_mode.get()][2]() # update max values, e.g. calls update_max_fields function
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
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, e.g. calls update_max_fields function
|
||||
@@ -287,10 +288,13 @@ class Configuration(Frame):
|
||||
# {Key: [[x-value,y-value,z-value], unit, description, config file key, unit conversion factor]}
|
||||
self.entries = {
|
||||
"Coil Constants:": [[DoubleVar() for _ in range(3)], "\u03BCT/A", "", "coil_const", 1e6],
|
||||
"Ambient Field:": [[DoubleVar() for _ in range(3)], "\u03BCT/A", "Field to be compensated", "ambient_field", 1e6],
|
||||
"Resistances:": [[DoubleVar() for _ in range(3)], "\u03A9", "Resistance of coils + equipment", "resistance", 1],
|
||||
"Ambient Field:": [[DoubleVar() for _ in range(3)], "\u03BCT/A",
|
||||
"Field to be compensated", "ambient_field", 1e6],
|
||||
"Resistances:": [[DoubleVar() for _ in range(3)], "\u03A9",
|
||||
"Resistance of coils + equipment", "resistance", 1],
|
||||
"Max. Power:": [[DoubleVar() for _ in range(3)], "W", "Max. allowed power", "max_watts", 1],
|
||||
"Max. Voltage:": [[DoubleVar() for _ in range(3)], "V", "Max. allowed voltage, must not exceed 16V!", "max_volts", 1],
|
||||
"Max. Voltage:": [[DoubleVar() for _ in range(3)], "V",
|
||||
"Max. allowed voltage, must not exceed 16V!", "max_volts", 1],
|
||||
"Arduino Pins:": [[IntVar() for _ in range(3)], "-", "Should be 15, 16, 17", "relay_pin", 1]
|
||||
}
|
||||
|
||||
@@ -320,8 +324,6 @@ class Configuration(Frame):
|
||||
|
||||
row_counter += 1
|
||||
|
||||
print(self.fields)
|
||||
|
||||
self.update_fields() # set current values from config file
|
||||
|
||||
Label(self, text="", pady=10).grid(row=row_counter, column=0) # add spacer
|
||||
@@ -335,7 +337,7 @@ class Configuration(Frame):
|
||||
self.buttons_frame.grid(row=row_counter, column=0, sticky=W, padx=20)
|
||||
|
||||
# Create and place buttons
|
||||
implement_button = Button(self.buttons_frame, text="Update and Reconnect", command=self.implement,
|
||||
implement_button = Button(self.buttons_frame, text="Update and Reinitialize", command=self.implement,
|
||||
pady=5, padx=5, font=BIG_BUTTON_FONT)
|
||||
implement_button.grid(row=0, column=0, padx=5)
|
||||
restore_button = Button(self.buttons_frame, text="Restore Defaults", command=self.restore_defaults,
|
||||
@@ -348,9 +350,9 @@ class Configuration(Frame):
|
||||
def page_switch(self): # function that is called when switching to this window
|
||||
self.update_fields()
|
||||
|
||||
def restore_defaults(self):
|
||||
def restore_defaults(self): # restore all default settings
|
||||
func.create_default_config(g.CONFIG_FILE) # overwrite config file with default
|
||||
func.setup_axes() # setup everything with the defaults ToDo: take out?
|
||||
func.setup_all() # setup everything with the defaults
|
||||
self.update_fields() # update fields in config window
|
||||
|
||||
def update_fields(self):
|
||||
@@ -366,11 +368,12 @@ class Configuration(Frame):
|
||||
factor = self.entries[key][4] # get unit conversion factor
|
||||
self.entries[key][0][i].set(round(type_value * factor, 3)) # set value with correct unit conversion
|
||||
|
||||
# check if values are within safe limits:
|
||||
value_check = func.value_in_limits(g.AXIS_NAMES[i], self.entries[key][3], value)
|
||||
if value_check == 'OK':
|
||||
self.fields[key][i].config(background="White")
|
||||
else:
|
||||
self.fields[key][i].config(background="Red")
|
||||
if value_check == 'OK': # value is acceptable
|
||||
self.fields[key][i].config(background="White") # set colour of this entry to white
|
||||
else: # value exceeds limits
|
||||
self.fields[key][i].config(background="Red") # set colour of this entry to red to show problem
|
||||
|
||||
def implement(self): # update config file with user inputs into entry fields and reinitialize
|
||||
|
||||
@@ -395,6 +398,7 @@ class Configuration(Frame):
|
||||
config_key = self.entries[key][3] # handle by which value is indexed in config file
|
||||
value_ok = func.value_in_limits(g.AXIS_NAMES[i], config_key, value)
|
||||
unit = self.entries[key][1] # get unit string for error messages
|
||||
axis = g.AXIS_NAMES[i] # get axis name for error messages
|
||||
|
||||
if value_ok == 'OK':
|
||||
func.edit_config(g.AXIS_NAMES[i], config_key, value) # write new value to config file
|
||||
@@ -402,15 +406,17 @@ class Configuration(Frame):
|
||||
if value_ok == 'HIGH':
|
||||
max_value = g.default_arrays[config_key][1][i] # get max value
|
||||
message = "Attempted to set too high value for {s} {k}\n" \
|
||||
"{v} {unit}, max. {mv} {unit} allowed. Excessive values may damage equipment!\n" \
|
||||
"{v} {unit}, max. {mv} {unit} allowed.\n" \
|
||||
"Excessive values may damage equipment!\n" \
|
||||
"Do you really want to use this value?"\
|
||||
.format(s=g.AXIS_NAMES[i], k=key, v=value*factor, mv=round(max_value*factor, 1), unit=unit)
|
||||
.format(s=axis, k=key, v=value*factor, mv=round(max_value*factor, 1), unit=unit)
|
||||
elif value_ok == 'LOW':
|
||||
min_value = g.default_arrays[config_key][2][i] # get min value
|
||||
message = "Attempted to set too low value for {s} {k}\n" \
|
||||
"{v} {unit}, min. {mv} {unit} allowed. Excessive values may damage equipment!\n" \
|
||||
"{v} {unit}, min. {mv} {unit} allowed.\n" \
|
||||
"Excessive values may damage equipment!\n" \
|
||||
"Do you really want to use this value?"\
|
||||
.format(s=g.AXIS_NAMES[i], k=key, v=value*factor, mv=round(min_value*factor, 1), unit=unit)
|
||||
.format(s=axis, k=key, v=value*factor, mv=round(min_value*factor, 1), unit=unit)
|
||||
else: message = "Unknown case, this should not happen."
|
||||
|
||||
# display pop-up message to ask user if he really wants the value
|
||||
@@ -421,7 +427,7 @@ class Configuration(Frame):
|
||||
func.edit_config(g.AXIS_NAMES[i], config_key, value, True)
|
||||
# if user chooses 'no' nothing happens, old value is kept
|
||||
|
||||
func.setup_axes() # reinitialize devices and program with new values
|
||||
func.setup_all() # reinitialize devices and program with new values
|
||||
self.update_fields() # update entry fields to show new values
|
||||
|
||||
|
||||
@@ -498,7 +504,7 @@ class StatusDisplay(Frame):
|
||||
controller.after(500, lambda: self.update_labels(controller))
|
||||
|
||||
|
||||
class OutputConsole(Frame): # console to print stuff in
|
||||
class OutputConsole(Frame): # console to print stuff in, similar to standard python output
|
||||
|
||||
def __init__(self, parent):
|
||||
Frame.__init__(self, parent, relief=SUNKEN, bd=1)
|
||||
|
||||
+36
-49
@@ -6,6 +6,7 @@ import time
|
||||
import numpy as np
|
||||
import serial
|
||||
import traceback
|
||||
# noinspection PyPep8Naming
|
||||
import User_Interface as ui
|
||||
from tkinter import *
|
||||
from tkinter import messagebox
|
||||
@@ -140,7 +141,7 @@ class ArduinoCtrl(Arduino):
|
||||
def __init__(self):
|
||||
self.connected = "Unknown"
|
||||
self.pins = [0, 0, 0]
|
||||
for i in range(3):
|
||||
for i in range(3): # get correct pins from config file
|
||||
self.pins[i] = int(read_config(g.AXIS_NAMES[i], "relay_pin"))
|
||||
ui_print("\nConnecting to Arduino...")
|
||||
try:
|
||||
@@ -177,24 +178,11 @@ class ArduinoCtrl(Arduino):
|
||||
|
||||
|
||||
def read_config(section, key): # read specific value from config file
|
||||
# ToDo (optional): better error handling
|
||||
|
||||
config_object = ConfigParser() # initialize config parser
|
||||
try:
|
||||
config_object.read(g.CONFIG_FILE) # open config file
|
||||
section_obj = config_object[section] # get relevant section
|
||||
value = section_obj[key] # get relevant value in the section
|
||||
|
||||
# Value checking: ToDo: decide if we want this
|
||||
'''if section in g.AXIS_NAMES: # only check numerical values
|
||||
max_value = g.default_arrays[key][1][g.AXIS_NAMES.index(section)] # get max value
|
||||
min_value = g.default_arrays[key][2][g.AXIS_NAMES.index(section)]
|
||||
if float(value) > float(max_value):
|
||||
ui_print("\nWARNING: Too high value for", section, key, "read from config file:",
|
||||
value, "max.", max_value, "allowed. Excessive values may damage equipment!\n")
|
||||
elif float(value) < float(min_value):
|
||||
ui_print("\nWARNING: Too low value for", section, key, "read from config file:",
|
||||
value, "max.", max_value, "allowed. Excessive values may damage equipment!\n")'''
|
||||
return value
|
||||
except KeyError as e:
|
||||
ui_print("Error while reading config file:", e)
|
||||
@@ -204,32 +192,30 @@ def read_config(section, key): # read specific value from config file
|
||||
def edit_config(section, key, value, override=False): # edit specific value in config file
|
||||
config_object = ConfigParser() # initialize config parser
|
||||
|
||||
# Check if value is within acceptable limits (set in globals.py)
|
||||
# Check if value to write is within acceptable limits (set in globals.py)
|
||||
try:
|
||||
value_ok = True
|
||||
value_ok = 'OK'
|
||||
if section in g.AXIS_NAMES and not override: # only check numerical values and not if overridden by user
|
||||
value_ok = False
|
||||
value_ok = value_in_limits(section, key, value) # check if value is ok, too high or too low
|
||||
max_value = g.default_arrays[key][1][g.AXIS_NAMES.index(section)] # get max value
|
||||
min_value = g.default_arrays[key][2][g.AXIS_NAMES.index(section)] # get min value
|
||||
if value > max_value:
|
||||
if value_ok == 'HIGH':
|
||||
message = "Prevented writing too high value for {s} {k} to config file:\n" \
|
||||
"{v}, max. {mv} allowed. Erroneous values may damage equipment!" \
|
||||
.format(s=section, k=key, v=value, mv=max_value)
|
||||
raise ValueError(message)
|
||||
elif value < min_value:
|
||||
elif value_ok == 'LOW':
|
||||
message = "Prevented writing too low value for {s} {k} to config file:\n" \
|
||||
"{v}, max. {mv} allowed. Erroneous values may damage equipment!" \
|
||||
.format(s=section, k=key, v=value, mv=min_value)
|
||||
raise ValueError(message)
|
||||
else:
|
||||
value_ok = True
|
||||
|
||||
if value_ok or override:
|
||||
if value_ok == 'OK' or override: # value is within limits or user has overridden
|
||||
config_object.read(g.CONFIG_FILE) # open config file
|
||||
section_obj = config_object[section] # get relevant section
|
||||
section_obj[key] = str(value) # get relevant value in the section
|
||||
|
||||
with open(g.CONFIG_FILE, 'w') as conf: # Write changes back to file
|
||||
with open(g.CONFIG_FILE, 'w') as conf: # Write changes to config file
|
||||
config_object.write(conf)
|
||||
|
||||
except KeyError as e:
|
||||
@@ -237,31 +223,32 @@ def edit_config(section, key, value, override=False): # edit specific value in
|
||||
raise KeyError("Could not find key", key, "in config file.")
|
||||
|
||||
|
||||
def check_config():
|
||||
def check_config(): # check all numeric values in the config file and see if they are within safe limits
|
||||
ui_print("Checking config file for values exceeding limits:")
|
||||
i = 0
|
||||
concerns = {}
|
||||
concerns = {} # initialize dictionary for found problems
|
||||
problem_counter = 0
|
||||
for axis in g.AXIS_NAMES:
|
||||
concerns[axis] = []
|
||||
for key in g.default_arrays.keys():
|
||||
value = float(read_config(axis, key))
|
||||
concerns[axis] = [] # create dictionary entry for this axis
|
||||
for key in g.default_arrays.keys(): # go over entries in this axis
|
||||
value = float(read_config(axis, key)) # read value to check from config file
|
||||
max_value = g.default_arrays[key][1][i] # get max value
|
||||
min_value = g.default_arrays[key][2][i] # get min value
|
||||
|
||||
if not min_value <= value <= max_value:
|
||||
concerns[axis].append(key)
|
||||
if not min_value <= value <= max_value: # value is not in safe limits
|
||||
concerns[axis].append(key) # add this entry to the problem dictionary
|
||||
problem_counter += 1
|
||||
|
||||
if len(concerns[axis]) == 0:
|
||||
concerns[axis].append("No problems detected.")
|
||||
|
||||
ui_print(axis, ":", *concerns[axis])
|
||||
ui_print(axis, ":", *concerns[axis]) # print out results for this axis
|
||||
i += 1
|
||||
if problem_counter > 0:
|
||||
messagebox.showwarning("Warning!", "Found values exceeding limits in config file. Check values in "
|
||||
"configuration page to avoid equipment damage!")
|
||||
g.app.show_frame(ui.Configuration)
|
||||
if problem_counter > 0: # some values are not ok
|
||||
# shop pup-up warning message:
|
||||
messagebox.showwarning("Warning!", "Found values exceeding limits in config file. Check values "
|
||||
"to ensure correct operation and avoid equipment damage!")
|
||||
g.app.show_frame(ui.Configuration) # open configuration window so user can check values
|
||||
|
||||
|
||||
def create_default_config(file): # create config file from default values (stored in globals.py)
|
||||
@@ -307,7 +294,7 @@ def value_in_limits(axis, key, value): # Check if value is within safe limits (
|
||||
return 'OK'
|
||||
|
||||
|
||||
def setup_axes(): # creates device objects for all PSUs and sets their values
|
||||
def setup_all(): # main initialization function, creates device objects for all PSUs and Arduino and sets their values
|
||||
# Connect to Arduino:
|
||||
try:
|
||||
if g.ARDUINO is not None:
|
||||
@@ -336,7 +323,7 @@ def setup_axes(): # creates device objects for all PSUs and sets their values
|
||||
ui_print("\nConnecting to XY Device on %s..." % g.XY_PORT)
|
||||
try:
|
||||
if g.XY_DEVICE is not None:
|
||||
ui_print("closing serial connection on XY device")
|
||||
ui_print("Closing serial connection on XY device")
|
||||
g.XY_DEVICE.serial.close()
|
||||
g.XY_DEVICE = None
|
||||
g.XY_DEVICE = PS2000B.PS2000B(g.XY_PORT) # setup PSU
|
||||
@@ -350,6 +337,10 @@ def setup_axes(): # creates device objects for all PSUs and sets their values
|
||||
|
||||
ui_print("Connecting to Z Device on %s..." % g.Z_PORT)
|
||||
try:
|
||||
if g.Z_DEVICE is not None:
|
||||
ui_print("Closing serial connection on Z device")
|
||||
g.Z_DEVICE.serial.close()
|
||||
g.Z_DEVICE = None
|
||||
g.Z_DEVICE = PS2000B.PS2000B(g.Z_PORT)
|
||||
ui_print("Connection established.")
|
||||
g.Z_AXIS = Axis(2, g.Z_DEVICE, 0, g.ARDUINO.pins[2])
|
||||
@@ -454,25 +445,21 @@ def set_current_vec(vector): # sets needed currents on each axis for given vect
|
||||
i = i + 1
|
||||
|
||||
|
||||
def execute_csv(filepath, printing=0): # runs through csv file containing times and desired field vectors
|
||||
def execute_csv(filepath): # runs through csv file containing times and desired field vectors
|
||||
# csv format: time (s); xField (T); yField (T); zField (T)
|
||||
# decimal commas
|
||||
ui_print("Reading File:", filepath)
|
||||
file = pandas.read_csv(filepath, sep=';', decimal=',', header=0) # read csv file
|
||||
array = file.to_numpy() # convert csv to array
|
||||
t_zero = time.time()
|
||||
t_ref = t_zero
|
||||
t_zero = time.time() # set reference time for start of run
|
||||
i = 0
|
||||
ui_print("Starting Execution...")
|
||||
ui_print("Starting File Execution...")
|
||||
while i < len(array):
|
||||
t = time.time() - t_zero
|
||||
if t >= array[i, 0]:
|
||||
field_vec = array[i, 1:4]
|
||||
ui_print("t = %0.2f s, target field vector = " % (array[i, 0]), field_vec)
|
||||
set_field(field_vec)
|
||||
i = i + 1
|
||||
if t - t_ref >= 1 and printing == 1: # print status every second
|
||||
print_status_3()
|
||||
t_ref = t
|
||||
if t >= array[i, 0]: # time for this row has come
|
||||
field_vec = array[i, 1:4] # extract desired field vector
|
||||
# ui_print("t = %0.2f s, target field vector = " % (array[i, 0]), field_vec)
|
||||
set_field(field_vec) # send field vector to test stand
|
||||
i = i + 1 # next row
|
||||
ui_print("File executed, powering down channels.")
|
||||
power_down_all() # set currents and voltages to 0, set arduino pins to low
|
||||
|
||||
@@ -13,7 +13,7 @@ try: # start normal operations
|
||||
func.create_default_config(g.CONFIG_FILE)
|
||||
|
||||
print("Starting setup...")
|
||||
func.setup_axes() # initiate communication, set handles
|
||||
func.setup_all() # initiate communication, set handles
|
||||
|
||||
print("\nOpening User Interface...")
|
||||
|
||||
@@ -22,7 +22,7 @@ try: # start normal operations
|
||||
func.check_config() # check config file for values exceeding limits
|
||||
|
||||
func.ui_print("\nStarting setup...") # do it again, so it is printed in the UI console ToDo: do it only once
|
||||
func.setup_axes() # initiate communication, set handles
|
||||
func.setup_all() # initiate communication, set handles
|
||||
g.app.mainloop()
|
||||
g.app = None # reset to None so nothing tries to print in the UI output
|
||||
|
||||
|
||||
Reference in New Issue
Block a user