From 12ec34182bdc6ed5da583e22b23e383ca8dda084 Mon Sep 17 00:00:00 2001 From: Martin Zietz Date: Thu, 10 Dec 2020 12:44:30 +0100 Subject: [PATCH] Implemented Arduino-based polarity control into main script --- One_Unit_Test.py | 47 +++++++++++++++++++------------- cage_func.py | 70 ++++++++++++++++++++++++++++-------------------- example2.py | 54 ++++++++++++++++++------------------- globals.py | 19 +++++++++++-- main.py | 20 ++++++++++---- 5 files changed, 129 insertions(+), 81 deletions(-) diff --git a/One_Unit_Test.py b/One_Unit_Test.py index e6a1c6d..ebd2afa 100644 --- a/One_Unit_Test.py +++ b/One_Unit_Test.py @@ -14,42 +14,53 @@ 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.ambientField = np.array([80])*1e-6 # ambient magnetic field in measurement area, to be cancelled out +g.resistances = np.array([3.9, 1, 1]) # resistance of [x,y,z] circuits +g.maxWatts = np.array([8, 0, 0]) # max. allowed power for [x,y,z] circuits # COM-Ports for power supply units: -xPort = "COM7" # placeholder -g.xDevice = PS2000B.PS2000B(xPort) +xyPort = "COM7" +g.xyDevice = PS2000B.PS2000B(xyPort) -func.print_status(g.xDevice) -t.sleep(3) +g.maxAmps = np.sqrt(g.maxWatts/g.resistances) +print(g.maxAmps) -g.xDevice.enable_all() -func.print_status(g.xDevice) + +def print_status(): + print("Output 1:") + func.print_status(g.xAxis) + print("Output 2:") + func.print_status(g.yAxis) + + +g.xyDevice.enable_all() +func.set_to_zero(g.xyDevice) +print_status() t.sleep(3) if Test1 == 1: - g.xDevice.voltage1 = 5 + g.xyDevice.voltage1 = 5 t.sleep(1) - func.print_status(g.xDevice) + print_status() t.sleep(5) - func.set_to_zero(g.xDevice) + func.set_to_zero(g.xyDevice) if Test2 == 1: - g.xDevice.current1 = 0.2 + g.xyDevice.current1 = 0.2 t.sleep(1) - func.print_status(g.xDevice) + print_status() t.sleep(5) - func.set_to_zero(g.xDevice) + func.set_to_zero(g.xyDevice) if Test4 == 1: - func.set_axis_current(g.xDevice, 0.2) + func.set_axis_current(g.xyDevice, 0.2) t.sleep(1) - func.print_status(g.xDevice) + print_status() t.sleep(10) - func.set_to_zero(g.xDevice) + func.set_to_zero(g.xyDevice) t.sleep(1) -func.print_status(g.xDevice) +print_status() -g.xDevice.disable_all() +g.xyDevice.disable_all() -func.print_status(g.xDevice) +print_status() diff --git a/cage_func.py b/cage_func.py index 7231700..3ccbb51 100644 --- a/cage_func.py +++ b/cage_func.py @@ -4,36 +4,44 @@ from pyps2000b import PS2000B import globals as g -def set_devices(xPort, yPort, zPort): # creates device objects for all PSUs - g.xDevice = PS2000B.PS2000B(xPort) - g.yDevice = PS2000B.PS2000B(yPort) - g.zDevice = PS2000B.PS2000B(zPort) +def set_devices(): # creates device objects for all PSUs + g.xyDevice = PS2000B.PS2000B(g.xyPort) + g.zDevice = PS2000B.PS2000B(g.zPort) + g.xAxis = (g.xyDevice, 0, g.relayPins[0], 0) # (device, channel, arduino pin, axis index) + g.yAxis = (g.xyDevice, 1, g.relayPins[1], 1) + g.zAxis = (g.zDevice, 0, g.relayPins[2], 2) def activate_all(): # enables remote control and output on all PSUs and channels - g.xDevice.enable_all() - g.yDevice.enable_all() + g.xyDevice.enable_all() g.zDevice.enable_all() def deactivate_all(): # disables remote control and output on all PSUs and channels - g.xDevice.disable_all() - g.yDevice.disable_all() + g.xyDevice.disable_all() g.zDevice.disable_all() -def print_status(device): - print("Channel 1: %s, %0.2f V, %0.2f A" % (device.get_device_status_information(0), device.voltage1, device.current1)) - print("Channel 2: %s, %0.2f V, %0.2f A" % (device.get_device_status_information(1), device.voltage1, device.current1)) +def safe_arduino(): # sets output pins to low and closes serial connection + for pin in g.relayPins: + g.arduino.digitalWrite(pin, "LOW") + g.arduino.close() + + +def print_status(axis): # axis as (device, channel), e.g. g.xAxis + device = axis[0] # PSU + channel = axis[1] # output channel on the PSU + print("%s, %0.2f V, %0.2f A" + % (device.get_device_status_information(channel), device.get_voltage(channel), device.get_current(channel))) def print_status_3(): print("X-Axis:") - print_status(g.xDevice) + print_status(g.xAxis) print("Y-Axis:") - print_status(g.yDevice) + print_status(g.yAxis) print("Z-Axis:") - print_status(g.zDevice) + print_status(g.zAxis) def set_to_zero(device): @@ -55,22 +63,26 @@ def set_field(vector): # forms magnetic field as specified by vector, corrected def set_current_vec(i_vec): # sets needed currents on each axis for given vector - set_axis_current(g.xDevice, i_vec[0]) - set_axis_current(g.yDevice, i_vec[1]) - set_axis_current(g.zDevice, i_vec[2]) + set_axis_current(g.xAxis, i_vec[0]) + set_axis_current(g.yAxis, i_vec[1]) + set_axis_current(g.zAxis, i_vec[2]) -def set_axis_current(device, value): # sets current with correct polarity on one axis - # ToDo: Check behaviour with only current or only voltage set - # ToDo: Check behaviour when trying to set too high currents - if value > 0: - device.current1 = value - device.voltage2 = 0 +def set_axis_current(axis, value): # sets current with correct polarity on one axis + device = axis[0] + channel = axis[1] + ardPin = axis[2] + axisIndex = axis[3] + if abs(value) > g.maxAmps[axisIndex]: # prevent excessive currents + set_to_zero(device) # set currents and voltages to 0 + device.disable_all() # disable outputs on PSU + safe_arduino() # set arduino pins to low and close serial link + raise ValueError("Invalid current value. Tried %0.2fA, max. %0.2fA allowed" % (value, g.maxAmps[axisIndex])) + elif value >= 0: # switch polarity as needed + g.arduino.digitalWrite(ardPin, "LOW") elif value < 0: - device.voltage1 = 0 - device.current2 = -value - elif value == 0: - device.voltage1 = 0 - device.voltage2 = 0 + g.arduino.digitalWrite(ardPin, "HIGH") else: - raise ValueError("Invalid current value. (This should be impossible.)") + raise Exception("This should be impossible.") + device.set_current(abs(value), channel) + device.set_voltage(1.1 * g.maxAmps[axisIndex] * g.resistances[axisIndex]) # set max voltage high enough diff --git a/example2.py b/example2.py index e004f49..009b52d 100644 --- a/example2.py +++ b/example2.py @@ -10,55 +10,55 @@ DEVICE = "COM7" if platform.system() == "Windows" else "/dev/ttyACM0" # connection to the device is automatically opened print("Connecting to device at %s..." % DEVICE) -device1 = PS2000B.PS2000B(DEVICE) # create Object of class PS2000B, pass COM-port and channel to functions inside +xyDevice = PS2000B.PS2000B(DEVICE) # create Object of class PS2000B, pass COM-port and channel to functions inside # static device information can be read -print("Connection open: %s" % device1.is_open()) -print("Device: %s" % device1.get_device_information()) +print("Connection open: %s" % xyDevice.is_open()) +print("Device: %s" % xyDevice.get_device_information()) # dynamic device status information can be read -device_status_info1 = device1.get_device_status_information(0) -device_status_info2 = device1.get_device_status_information(1) -print("Device status 1: %s" % device1.get_device_status_information(0)) -print("Device status 2: %s" % device1.get_device_status_information(1)) -print("Current output 1: %0.2f V , %0.2f A" % (device1.voltage1, device1.current1)) -print("Current output 2: %0.2f V , %0.2f A" % (device1.voltage2, device1.current2)) +device_status_info1 = xyDevice.get_device_status_information(0) +device_status_info2 = xyDevice.get_device_status_information(1) +print("Device status 1: %s" % xyDevice.get_device_status_information(0)) +print("Device status 2: %s" % xyDevice.get_device_status_information(1)) +print("Current output 1: %0.2f V , %0.2f A" % (xyDevice.voltage1, xyDevice.current1)) +print("Current output 2: %0.2f V , %0.2f A" % (xyDevice.voltage2, xyDevice.current2)) # device can be controlled if not device_status_info1.remote_control_active: print("...will enable remote control...") - device1.enable_remote_control(0) + xyDevice.enable_remote_control(0) if not device_status_info2.remote_control_active: print("...will enable remote control...") - device1.enable_remote_control(1) + xyDevice.enable_remote_control(1) print("...set voltage 1 to 12V and max current to 1A...") -device1.voltage1 = 12 -device1.current1 = 1 +xyDevice.voltage1 = 12 +xyDevice.current1 = 1 time.sleep(2) print("...now enabling the power output control 1...") -device1.enable_output(0) +xyDevice.enable_output(0) time.sleep(2) print("... set voltage 2 to 5V and max current to 1A...") -device1.voltage2 = 5 -device1.current2 = 1 +xyDevice.voltage2 = 5 +xyDevice.current2 = 1 time.sleep(2) print("...now enabling the power output control 2...") -device1.enable_output(1) +xyDevice.enable_output(1) time.sleep(5) -print("Device status 1: %s" % device1.get_device_status_information(0)) -print("Device status 2: %s" % device1.get_device_status_information(1)) -print("Output 1: %0.2f V , %0.2f A" % (device1.voltage1, device1.current1)) -print("Output 2: %0.2f V , %0.2f A" % (device1.voltage2, device1.current2)) +print("Device status 1: %s" % xyDevice.get_device_status_information(0)) +print("Device status 2: %s" % xyDevice.get_device_status_information(1)) +print("Output 1: %0.2f V , %0.2f A" % (xyDevice.voltage1, xyDevice.current1)) +print("Output 2: %0.2f V , %0.2f A" % (xyDevice.voltage2, xyDevice.current2)) time.sleep(5) -device1.disable_output(0) -device1.disable_output(1) +xyDevice.disable_output(0) +xyDevice.disable_output(1) print("...and disabling remote control again.") -device1.disable_remote_control(0) -device1.disable_remote_control(1) +xyDevice.disable_remote_control(0) +xyDevice.disable_remote_control(1) -print("Device status 1: %s" % device1.get_device_status_information(0)) -print("Device status 2: %s" % device1.get_device_status_information(1)) +print("Device status 1: %s" % xyDevice.get_device_status_information(0)) +print("Device status 2: %s" % xyDevice.get_device_status_information(1)) diff --git a/globals.py b/globals.py index 091f2be..8d67e02 100644 --- a/globals.py +++ b/globals.py @@ -1,6 +1,21 @@ global Coil_const global ambientField -global xDevice -global yDevice +global xyPort +global zPort + +global xyDevice global zDevice + +global xAxis +global yAxis +global zAxis + +global resistances +global maxAmps +global maxWatts + +global arduino + +relayPins = [1, 2, 3] # digital pin on the Arduino for switching relay of each axis [x,y,z] + diff --git a/main.py b/main.py index 3961e0a..b63a8b8 100644 --- a/main.py +++ b/main.py @@ -4,6 +4,7 @@ import numpy as np import globals as g import cage_func as func # from pyps2000b import PS2000B +from Arduino import Arduino # User Inputs/Configuration---------------------------------- # Desired output: @@ -12,14 +13,23 @@ mag_vec1 = np.array([10, 10, 5])*1e-6 # Constants: g.Coil_const = np.array([38.6, 38.45, 37.9])*1e-9 # Coil constants [x,y,z] in T/A g.ambientField = np.array([80])*1e-6 # ambient magnetic field in measurement area, to be cancelled out +g.resistances = np.array([3.9, 1, 1]) # resistance of [x,y,z] circuits +g.maxWatts = np.array([8, 0, 0]) # max. allowed power for [x,y,z] circuits # COM-Ports for power supply units: -xPort = "COM1" # placeholders -yPort = "COM3" -zPort = "COM5" +g.xyPort = "COM1" # placeholders +g.zPort = "COM1" -func.set_devices(xPort, yPort, zPort) # initiate communication, set handles -func.activate_all() # activate remote control and outputs +# Code starts here------------------------------------------ +g.maxAmps = np.sqrt(g.maxWatts/g.resistances) # calculate maximum currents in each axis + +print("Connecting to PSUs...") +func.set_devices() # initiate communication, set handles +print("Connecting to Arduino...") +g.arduino = Arduino() # search for connected arduino and set handle +print("Arduino found.") +print("Activating PSU outputs...") +func.activate_all() # activate remote control and outputs on PSUs func.set_field_simple(mag_vec1)