forked from zietzm/Helmholtz_Test_Bench
code cleanup and comments
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
# This file enables control of a connected Arduino microcontroller.
|
||||
#!/usr/bin/env python
|
||||
import logging
|
||||
import itertools
|
||||
|
||||
+3
-1
@@ -1,19 +1,21 @@
|
||||
# This file contains classes to build all elements of the graphical user interface.
|
||||
# These classes also contain the methods that are executed when UI elements are activated.
|
||||
|
||||
# import packages for user interface:
|
||||
from tkinter import *
|
||||
from tkinter import ttk
|
||||
from tkinter import messagebox
|
||||
from tkinter import filedialog
|
||||
|
||||
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
||||
|
||||
# import general packages:
|
||||
import numpy as np
|
||||
import os
|
||||
from os.path import exists
|
||||
import threading
|
||||
from datetime import datetime
|
||||
|
||||
# import other project files:
|
||||
import globals as g
|
||||
import cage_func as func
|
||||
import csv_threading as csv
|
||||
|
||||
+2
-1
@@ -1,13 +1,14 @@
|
||||
# tThis file contains code for executing a sequence of magnetic fields from a csv file.
|
||||
# To do this without crashing the UI it has to run in a separate thread using the threading module.
|
||||
|
||||
# import packages:
|
||||
import time
|
||||
import pandas
|
||||
from threading import *
|
||||
from tkinter import messagebox
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
# import other project files:
|
||||
import User_Interface as ui
|
||||
import cage_func as func
|
||||
import globals as g
|
||||
|
||||
+25
-19
@@ -1,43 +1,49 @@
|
||||
# This file is used to hold global variables that are used by more than one file of the program.
|
||||
# Instead of always passing all variables to functions, this file can simply be imported to get them.
|
||||
|
||||
import numpy as np
|
||||
|
||||
# global variables set in other files
|
||||
XY_DEVICE = None
|
||||
Z_DEVICE = None
|
||||
ARDUINO = None
|
||||
XY_DEVICE = None # XY PSU object will be stored here (class PS2000B)
|
||||
Z_DEVICE = None # Z PSU object will be stored here (class PS2000B)
|
||||
ARDUINO = None # Arduino object will be stored here (class ArduinoCtrl)
|
||||
|
||||
# Axis objects will be stored here (class Axis)
|
||||
X_AXIS = None
|
||||
Y_AXIS = None
|
||||
Z_AXIS = None
|
||||
|
||||
AXES = None # list containing [X_AXIS, Y_AXIS, Z_AXIS]
|
||||
|
||||
app = None
|
||||
app = None # Main Tkinter application object will be stored here (class HelmholtzGUI)
|
||||
|
||||
AXIS_NAMES = ["X-Axis", "Y-Axis", "Z-Axis"]
|
||||
AXIS_NAMES = ["X-Axis", "Y-Axis", "Z-Axis"] # list with the names of each axis, used mainly for printing functions
|
||||
|
||||
global XY_PORT
|
||||
global Z_PORT
|
||||
global XY_PORT # serial port for XY PSU will be stored here (string)
|
||||
global Z_PORT # serial port for Z PSU will be stored here (string)
|
||||
|
||||
global PORTS
|
||||
global PORTS # list containing [XY_PORT, XY_PORT, Z_PORT], used in loops where info on each axis is needed
|
||||
|
||||
global threadLock
|
||||
global threadLock # thread locking object, used to force threads to perform actions in a certain order (threading.Lock)
|
||||
|
||||
exitFlag = True # False when main window is open, false otherwise
|
||||
exitFlag = True # False when main window is open, True otherwise
|
||||
|
||||
# Default Constants and maximum/minimum values (warning messages will be generated if these are exceeded)
|
||||
# format: [[default values], [maximum values], [minimum values]]
|
||||
# ToDo: check actual maximum ratings
|
||||
# ToDo: Add maximum current: 5A (BA Blessing page 30), remove max_watts (there for testing with resistors)
|
||||
# Create dictionaries with default Constants and maximum/minimum values
|
||||
# Used to create default configs and to check if user inputs are within safe limits
|
||||
# ToDo: check actual maximum ratings (or refine after testing)
|
||||
# ToDo: put this into a config file
|
||||
|
||||
# Dictionary for numerical values:
|
||||
# format: key: [default values], [maximum values], [minimum values]
|
||||
default_arrays = {
|
||||
"coil_const": np.array([[38.6, 38.45, 37.9], [50, 50, 50], [0, 0, 0]]) * 1e-6, # Coil constants [x,y,z] [T/A]
|
||||
"ambient_field": np.array([[30, 30, 30], [200, 200, 200], [-200, -200, -200]]) * 1e-6, # background magnetic field [T]
|
||||
"ambient_field": np.array([[30, 30, 30], [200, 200, 200], [-200, -200, -200]]) * 1e-6, # ambient magnetic field [T]
|
||||
"resistance": np.array([[1.7, 1.7, 1.7], [5, 5, 5], [1, 1, 1]], dtype=float), # resistance of circuits [Ohm]
|
||||
"max_volts": np.array([[14, 14, 14], [16, 16, 16], [0, 0, 0]], dtype=float), # max. allowed voltage, limited to 16V by used diodes! [V]
|
||||
"max_volts": np.array([[14, 14, 14], [16, 16, 16], [0, 0, 0]], dtype=float), # max. voltage, limited to 16V by used diodes! [V]
|
||||
"max_amps": np.array([[4.5, 4.5, 4.5], [6, 6, 6], [0, 0, 0]], dtype=float), # max. allowed current (A)
|
||||
"relay_pin": [[15, 16, 17], [15, 16, 17], [15, 16, 17]] # pins on the arduino for reversing [x,y,z] polarity
|
||||
}
|
||||
# Dictionary for PSU serial ports:
|
||||
default_ports = {
|
||||
"xy_port": "COM1", # Serial port where PSU for X- and Y-Axes is connected
|
||||
"z_port": "COM2", # Serial port where PSU for Z-Axis is connected
|
||||
"xy_port": "COM1", # Default serial port where PSU for X- and Y-Axes is connected
|
||||
"z_port": "COM2", # Default serial port where PSU for Z-Axis is connected
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
# Main file of the program. Run this file to start the application.
|
||||
|
||||
# import packages:
|
||||
from os.path import exists
|
||||
import traceback
|
||||
from tkinter import messagebox
|
||||
|
||||
# import other project files:
|
||||
import cage_func as func
|
||||
from User_Interface import HelmholtzGUI
|
||||
from User_Interface import ui_print
|
||||
@@ -12,64 +16,63 @@ import csv_logging as log
|
||||
|
||||
|
||||
def program_end(): # called on exception or when user closes application
|
||||
# safely shuts everything down and saves any unsaved data
|
||||
|
||||
g.exitFlag = True # tell everything else the application has been closed
|
||||
if g.app is not None:
|
||||
if g.app.pages[ui.ExecuteCSVMode].csv_thread is not None: # end possible csv execution thread
|
||||
g.app.pages[ui.ExecuteCSVMode].csv_thread.stop() # stop thread
|
||||
if g.app is not None: # the main Tkinter app object has been initialized before
|
||||
if g.app.pages[ui.ExecuteCSVMode].csv_thread is not None: # check if a thread for executing CSVs exists
|
||||
g.app.pages[ui.ExecuteCSVMode].csv_thread.stop() # stop the thread
|
||||
|
||||
func.shut_down_all() # shut down devices
|
||||
|
||||
if log.unsaved_data: # There is logged data that has not been saved yet
|
||||
if log.unsaved_data: # Check if there is logged data that has not been saved yet
|
||||
# open pop-up to ask user if he wants to save the data:
|
||||
save_log = messagebox.askquestion("Save log data?", "There seems to be unsaved logging data. "
|
||||
"Do you wish to write it to a file now?")
|
||||
if save_log == 'yes': # user has chosen yes
|
||||
filepath = log.select_file() # let user select a file to write to
|
||||
log.write_to_file(log.log_data, filepath) # write the data to the chosen file
|
||||
|
||||
if g.app is not None:
|
||||
g.app.destroy() # close application
|
||||
|
||||
|
||||
try: # start normal operations
|
||||
|
||||
config.CONFIG_FILE = 'config.ini'
|
||||
config.CONFIG_FILE = 'config.ini' # set the config file path
|
||||
# ToDo: remember what the last config file was
|
||||
if not exists(config.CONFIG_FILE):
|
||||
if not exists(config.CONFIG_FILE): # config file does not exist yet
|
||||
print("Config file not found, creating new from defaults.")
|
||||
config.reset_config_to_default()
|
||||
config.write_config_to_file(config.CONFIG_OBJECT)
|
||||
config.reset_config_to_default() # create configuration object from defaults
|
||||
config.write_config_to_file(config.CONFIG_OBJECT) # write the configuration object to a new file
|
||||
|
||||
config.CONFIG_OBJECT = config.get_config_from_file(config.CONFIG_FILE)
|
||||
config.CONFIG_OBJECT = config.get_config_from_file(config.CONFIG_FILE) # read configuration data from config file
|
||||
|
||||
print("Starting setup...")
|
||||
func.setup_all() # initiate communication, set handles
|
||||
func.setup_all() # initiate communication with devices and initialize all major program objects
|
||||
|
||||
print("\nOpening User Interface...")
|
||||
|
||||
g.app = HelmholtzGUI()
|
||||
g.exitFlag = False
|
||||
g.app.state('zoomed') # open maximized
|
||||
g.app = HelmholtzGUI() # initialize user interface
|
||||
g.exitFlag = False # tell all functions that the user interface is now running
|
||||
g.app.state('zoomed') # open UI in maximized window
|
||||
g.app.StatusDisplay.continuous_label_update(g.app, 500) # initiate regular Status Display updates (ms)
|
||||
ui_print("Program Initialized")
|
||||
config.check_config(config.CONFIG_OBJECT) # check config for values exceeding limits
|
||||
|
||||
ui_print("\nStarting setup...") # do it again, so it is printed in the UI console ToDo: do it only once
|
||||
func.setup_all() # initiate communication, set handles
|
||||
ui_print("\nStarting setup...") # do setup again, so it is printed in the UI console ToDo: do it only once
|
||||
func.setup_all() # initiate communication with devices and initialize all major program objects
|
||||
|
||||
g.app.protocol("WM_DELETE_WINDOW", program_end) # call program_end function if user closes the application
|
||||
|
||||
g.app.mainloop()
|
||||
g.app.mainloop() # start main program loop
|
||||
|
||||
|
||||
except Exception as e: # if there is an error, print what happened
|
||||
except Exception as e: # An error has occurred somewhere in the program
|
||||
print("\nAn error occurred, Shutting down.")
|
||||
# shop pup-up error message:
|
||||
message = "%s.\nSee python console traceback for more details. " \
|
||||
"\nShutting down devices, check equipment to confirm." % e
|
||||
messagebox.showerror("Error!", message)
|
||||
print(traceback.print_exc())
|
||||
print(traceback.print_exc()) # print error traceback in the python console
|
||||
program_end() # safely close everything and shut down devices
|
||||
|
||||
# ToDo: rework window closing code https://bytes.com/topic/python/answers/431323-detect-tkinter-window-being-closed
|
||||
# https://stackoverflow.com/questions/14694408/runtimeerror-main-thread-is-not-in-main-loop
|
||||
|
||||
# ToDo: logging
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# This file enables communication with PS2000B Power Supply Units.
|
||||
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
# Python access to Elektro Automatik PS 2000 B devices via USB/serial
|
||||
|
||||
Reference in New Issue
Block a user