diff --git a/User_Interface.py b/User_Interface.py index 04b7855..5e68e77 100644 --- a/User_Interface.py +++ b/User_Interface.py @@ -110,7 +110,7 @@ class TopMenu: class ManualMode(Frame): - # Mode for manually setting currents and fields on the test stand. + # Mode for manually setting currents and fields on the test bench. # Inherits the Frame object from Tkinter and is placed in the mainArea of the application window. def __init__(self, parent, controller): Frame.__init__(self, parent) # initialize the frame object @@ -267,7 +267,7 @@ class ManualMode(Frame): # log change to the log file if user has selected event logging in the Configure Logging window logger = self.controller.pages[ConfigureLogging] # get object of logging configurator - if logger.event_logging: # data should be logged when test stand is commanded + if logger.event_logging: # data should be logged when test bench is commanded logger.log_datapoint() # log data def power_down(self): # called on "power down" button press @@ -275,13 +275,13 @@ class ManualMode(Frame): # log change to the log file if user has selected event logging in the Configure Logging window logger = self.controller.pages[ConfigureLogging] # get object of logging configurator - if logger.event_logging: # data should be logged when test stand is commanded + if logger.event_logging: # data should be logged when test bench is commanded logger.log_datapoint() # log data def execute(self): # called on "Execute!" button press - # reads values from the entry fields and commands the test stand accordingly + # reads values from the entry fields and commands the test bench accordingly - vector = np.array([0, 0, 0], dtype=float) # initialize vector to later send to test stand + vector = np.array([0, 0, 0], dtype=float) # initialize vector to later send to test bench i = 0 try: # try to read values from the entry fields for var in self.entry_vars: @@ -296,24 +296,24 @@ class ManualMode(Frame): # log change to the log file if user has selected event logging in the Configure Logging window logger = self.controller.pages[ConfigureLogging] # get object of logging configurator - if logger.event_logging: # data should be logged when test stand is commanded + if logger.event_logging: # data should be logged when test bench is commanded logger.log_datapoint() # log data - def execute_field(self, vector): # convert magnetic field vector and send to test stand + def execute_field(self, vector): # convert magnetic field vector and send to test bench ui_print("Field executing:", vector, "\u03BCT") compensate = self.compensate.get() # read out if compensate ambient field checkbox is ticked if compensate: # ambient field should be compensated - func.set_field(vector * 1e-6) # convert to Tesla and send to test stand + func.set_field(vector * 1e-6) # convert to Tesla and send to test bench elif not compensate: # ambient field should not be compensated - func.set_field_simple(vector * 1e-6) # convert to Tesla and send to test stand + func.set_field_simple(vector * 1e-6) # convert to Tesla and send to test bench else: # this really should never happen ui_print("Unexpected value encountered: compensate =", compensate) messagebox.showerror("Unexpected Value!", ("Unexpected value encountered: compensate =", compensate)) @staticmethod - def execute_current(vector): # send current vector to the test stand + def execute_current(vector): # send current vector to the test bench ui_print("Current executing:", vector, "A") - func.set_current_vec(vector) # command test stand + func.set_current_vec(vector) # command test bench class ExecuteCSVMode(Frame): @@ -468,7 +468,7 @@ class ExecuteCSVMode(Frame): # log change to the log file if user has selected event logging in the Configure Logging window logger = self.controller.pages[ConfigureLogging] # get object of logging configurator - if logger.event_logging: # data should be logged when test stand is commanded + if logger.event_logging: # data should be logged when test bench is commanded logger.log_datapoint() # log data def reinitialize(self): # called on "Reinitialize devices" button press @@ -476,7 +476,7 @@ class ExecuteCSVMode(Frame): # log change to the log file if user has selected event logging in the Configure Logging window logger = self.controller.pages[ConfigureLogging] # get object of logging configurator - if logger.event_logging: # data should be logged when test stand is commanded + if logger.event_logging: # data should be logged when test bench is commanded logger.log_datapoint() # log data def display_plot(self): # generate and display a plot of the data loaded from a csv file @@ -625,7 +625,7 @@ class Configuration(Frame): self.buttons_frame.grid(row=row_counter, column=0, sticky=W, padx=20) # Create and place buttons - # button to read the values from all fields, update the config and reinitialize the test stand + # button to read the values from all fields, update the config and reinitialize the test bench 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) @@ -785,9 +785,9 @@ class ConfigureLogging(Frame): self.log_file = None # string containing path of log file self.regular_logging = False # True if data should be logged regularly - self.event_logging = False # True if data should be logged every time a command is sent to the test stand - # log_datapoint() has to be called wherever a command is sent to the test stand and data should be logged - # it does not happen automatically whenever something is sent to the test stand + self.event_logging = False # True if data should be logged every time a command is sent to the test bench + # log_datapoint() has to be called wherever a command is sent to the test bench and data should be logged + # it does not happen automatically whenever something is sent to the test bench # It is done mainly in the functions for UI buttons, but rather inconsistently ToDo(optional): make consistent self.grid_rowconfigure(ALL, weight=1) @@ -853,14 +853,14 @@ class ConfigureLogging(Frame): # create checkbox variable for logging in regular time intervals self.regular_logging_var = BooleanVar(value=True) - # create checkbox variable for logging whenever test stand is commanded + # create checkbox variable for logging whenever test bench is commanded self.event_logging_var = BooleanVar(value=True) self.log_interval = DoubleVar(value=1) # create variable for logging interval entry field # create checkboxes for regular and event logging: self.regular_logging_checkbox = Checkbutton(self.settings_frame, text="Log in regular intervals", variable=self.regular_logging_var, onvalue=True, offvalue=False) - self.event_logging_checkbox = Checkbutton(self.settings_frame, text="Log whenever test stand is commanded", + self.event_logging_checkbox = Checkbutton(self.settings_frame, text="Log whenever test bench is commanded", variable=self.event_logging_var, onvalue=True, offvalue=False) self.regular_logging_checkbox.grid(row=0, column=0, sticky=W) self.event_logging_checkbox.grid(row=1, column=0, sticky=W, columnspan=3) @@ -943,7 +943,7 @@ class ConfigureLogging(Frame): def stop_logging(self): # stop the data logging, called by "Stop Logging" button ui_print("Stopped data logging. Remember to save data to file!") self.regular_logging = False # tell everything its time to stop periodic logging - self.event_logging = False # tell everything its time to stop logging on test stand commands + self.event_logging = False # tell everything its time to stop logging on test bench commands self.write_to_file_button["state"] = "normal" # enable write to file button self.stop_logging_button["state"] = "disabled" # disable stop logging button self.start_logging_button["state"] = "normal" # enable start logging button @@ -1015,7 +1015,7 @@ class ConfigureLogging(Frame): class StatusDisplay(Frame): - # status display to show information on test stand status in real time + # status display to show information on test bench status in real time # noinspection PyUnusedLocal def __init__(self, parent, controller): diff --git a/cage_func.py b/cage_func.py index b89ba29..5a886e8 100644 --- a/cage_func.py +++ b/cage_func.py @@ -1,4 +1,4 @@ -# This file contains all classes and functions directly related to the operation of the helmholtz test stand. +# This file contains all classes and functions directly related to the operation of the helmholtz test bench. # The two main classes are Axis and ArduinoCtrl, see their definitions for details. # import packages: @@ -16,7 +16,7 @@ import globals as g class Axis: - # Main class representing an axis (x,y,z) of the test stand + # Main class representing an axis (x,y,z) of the test bench # contains static and dynamic status information about this axis and methods to control it def __init__(self, index, device, PSU_channel, arduino_pin): @@ -117,7 +117,7 @@ class Axis: messagebox.showerror("PSU Error!", "Error while powering down %s: \n%s" % (self.name, e)) def set_signed_current(self, value): - # sets current with correct polarity on this axis, this is the primary way to control the test stand + # sets current with correct polarity on this axis, this is the primary way to control the test bench # ui_print("Attempting to set current", value, "A") self.target_current = value # show target value in object attribute for status display, logging etc. @@ -146,14 +146,14 @@ class Axis: self.target_field = value # update object attribute for display self.target_field_comp = value # same as above, bc no compensation current = value / self.coil_constant # calculate needed current - self.set_signed_current(current) # command the test stand + self.set_signed_current(current) # command the test bench def set_field(self, value): # forms magnetic field as specified by value, corrected for ambient field self.target_field = value # update object attribute for display field = value - self.ambient_field # calculate needed field after compensation self.target_field_comp = field # update object attribute for display current = field / self.coil_constant # calculate needed current - self.set_signed_current(current) # command the test stand + self.set_signed_current(current) # command the test bench class ArduinoCtrl(Arduino): @@ -216,7 +216,7 @@ def value_in_limits(axis, key, value): # Check if value is within safe limits ( return 'OK' -def setup_all(): # main test stand initialization function +def setup_all(): # main test bench initialization function # creates device objects for all PSUs and Arduino and sets their values # initializes an object of class Axis for all three axes (x,y,z) @@ -386,7 +386,7 @@ def set_current_vec(vector): # sets currents on each axis according to given ve axis.target_field = 0 # set target field attribute to 0 to show that current, not field is controlled atm axis.target_field_comp = 0 # as above - axis.set_signed_current(vector[i]) # command test stand to set the current + axis.set_signed_current(vector[i]) # command test bench to set the current except ValueError as e: # current was too high ui_print(e) # print out the error message i += 1 diff --git a/csv_threading.py b/csv_threading.py index d394705..3abd05b 100644 --- a/csv_threading.py +++ b/csv_threading.py @@ -47,7 +47,7 @@ class ExecCSVThread(Thread): def execute_sequence(self, array, delay, parent, controller): # main execution method of the class - # runs through array with times and desired fields and commands test stand accordingly + # runs through array with times and desired fields and commands test bench accordingly # array format: [time (s), xField (T), yField (T), zField (T)] func.power_down_all() # sets outputs on PSUs to 0 and Arduino pins to LOW before starting @@ -73,12 +73,12 @@ class ExecCSVThread(Thread): field_vec = array[i, 1:4] # extract desired field vector ui.ui_print("%0.5f s: t = %0.2f s, target field vector =" % (time.time() - t_zero, array[i, 0]), field_vec * 1e6, "\u03BCT") - func.set_field(field_vec) # send field vector to test stand + func.set_field(field_vec) # send field vector to test bench controller.StatusDisplay.update_labels() # update status display after change # log change to the log file if user has selected event logging in the Configure Logging window logger = controller.pages[ui.ConfigureLogging] # get object of logging configurator - if logger.event_logging: # data should be logged when test stand is commanded + if logger.event_logging: # data should be logged when test bench is commanded logger.log_datapoint() # log data i = i + 1 # next row @@ -115,17 +115,17 @@ def read_csv_to_array(filepath): # convert a given csv file to a numpy array def check_array_ok(array): - # check if any magnetic fields in an array exceed the test stand limits and if so display a warning message + # check if any magnetic fields in an array exceed the test bench limits and if so display a warning message values_ok = True for i in [0, 1, 2]: # go through axes/columns - max_val = g.AXES[i].max_comp_field[1] # get limits the test stand can do + max_val = g.AXES[i].max_comp_field[1] # get limits the test bench can do min_val = g.AXES[i].max_comp_field[0] data = array[:, i + 1] # extract data for this axis from array # noinspection PyTypeChecker if any(data > max_val) or any(data < min_val): # if any datapoint is out of bounds values_ok = False if not values_ok: # show warning pop-up if values are exceeding limits - messagebox.showwarning("Value Limits Warning!", "Found field values exceeding limits of test stand." + messagebox.showwarning("Value Limits Warning!", "Found field values exceeding limits of test bench." "\nSee plot and check values in csv.") @@ -140,7 +140,7 @@ def plot_field_sequence(array, width, height): # create plot of fixed size (pix figure.suptitle("Magnetic Field Sequence") # set figure title - # modify data to show instantaneous jumps in field to reflect test stand operation + # modify data to show instantaneous jumps in field to reflect test bench operation new_array = np.array([[0, 0, 0, 0]], dtype=float) # initialize modified array, zeros to show start from no fields last_vals = [0, 0, 0] # [x,y,z] field values from last data point (zero here), used to create step in data diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..f367119 --- /dev/null +++ b/readme.md @@ -0,0 +1,22 @@ +# Helmholtz Cage Control Software + +This software is used to control the magnetic field test bench at the Institute for Space Systems (IRS) at +the University of Stuttgart. The test bench consists of three Helmholtz coil pairs, one in each spatial axis. +The amount of current flowing through these coils is controlled by two PS2000B power supply units. +The polarity is switched by a set of relays that are controller by an Arduino Uno. + +This repository contains the source code and is used to develop and modify the program. Releases are distributed +in a [separate repository](https://egit.irs.uni-stuttgart.de/zietzm/Helmholtz_Test_Bench_Releases/releases). + +## Installation +1. Download latest release from +[distribution repository](https://egit.irs.uni-stuttgart.de/zietzm/Helmholtz_Test_Bench_Releases/releases) +2. Unpack ZIP-Folder +3. Run `Helmholtz Cage Control.exe` + +Alternatively use the `Helmholtz Cage Control.exe` from the `Release` folder in this repository. + +## Users Guide +For detailed instructions please refer to `Users Guide.pdf`. + +## diff --git a/readme.pdf b/readme.pdf deleted file mode 100644 index 7dc030e..0000000 Binary files a/readme.pdf and /dev/null differ