From 06fbe85b432a8cc154aaf576edfae268ce25e2bd Mon Sep 17 00:00:00 2001 From: Gustavo Date: Mon, 15 May 2023 14:39:36 -0700 Subject: [PATCH 01/43] ZXY6005s powersupply library prototype --- core_code/ZXY6005s.py | 74 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 core_code/ZXY6005s.py diff --git a/core_code/ZXY6005s.py b/core_code/ZXY6005s.py new file mode 100644 index 0000000..1ed818f --- /dev/null +++ b/core_code/ZXY6005s.py @@ -0,0 +1,74 @@ +import serial +import time +import utilities as utils #debugging +import struct + +#v1.1_0514 +# Library that manages the ZXY6005s power supply + + +#these functions to be used for later +#raw bytes to a string +def as_string(raw_data): + return bytearray(raw_data[:-1]) + +#raw bytes to a float +def as_float(raw_data): + f = struct.unpack_from(">f", bytearray(raw_data))[0] + return f + +#raw bytes to a word +def as_word(raw_data): + w = struct.unpack_from(">H", bytearray(raw_data))[0] + return w + + +class ZXY6005s: + def __init__(self, port,input_delay=utils.INPUT_DELAY, baudrate=9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=1): + self.port = port + self.input_delay = input_delay + self.baudrate = baudrate + self.baudrate = baudrate + self.parity = parity + self.bytesize = bytesize + self.timeout = timeout + self.serial = None + utils.log(0, "Powersupply info:\n\tPort: " + str(port) + '\n\tInput delay: ' str(input_delay) + '\n\tBaud rate: ' + str(baudrate) + '\n\tParity: ' + str(parity) + '\n\t stop bits: ' + str(stopbits) + '\n\tByte Size: ' + str(bytesize) + '\n\tTimeout: ' + str(timeout)) + + def is_open(self): + return self.serial.is_open + + def get_device_information(self): + return self.__device_information + + def disconnect(self): + self.serial.close() + + def send_command(self, command): + self.serial.write(command.encode()) + + def set_voltage(self, voltage): + self.send_command(f"VSET:{voltage:.2f}") + + def set_current(self, current): + self.send_command(f"ISET:{current:.3f}") + + def enable_output(self): + self.send_command("OUT1") + + def disable_output(self): + self.send_command("OUT0") + + + + + + + + +#Notes +#Baudrate: speed of communication over a data channel +#Parity: bit added to a string as a form of error detection + + + From 0420c96c72bc5b3cfe25b48edc8efafafdec8fe7 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Mon, 15 May 2023 14:42:17 -0700 Subject: [PATCH 02/43] Correct folder reupload --- ZXY6005s.py | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++ testmain.py | 13 ++++++++++ 2 files changed, 87 insertions(+) create mode 100644 ZXY6005s.py create mode 100644 testmain.py diff --git a/ZXY6005s.py b/ZXY6005s.py new file mode 100644 index 0000000..9360f06 --- /dev/null +++ b/ZXY6005s.py @@ -0,0 +1,74 @@ +import serial +import time +#import utilities as utils #debugging +import struct + +#v1.1_0514 +# Library that manages the ZXY6005s power supply + + +#these functions to be used for later +#raw bytes to a string +def as_string(raw_data): + return bytearray(raw_data[:-1]) + +#raw bytes to a float +def as_float(raw_data): + f = struct.unpack_from(">f", bytearray(raw_data))[0] + return f + +#raw bytes to a word +def as_word(raw_data): + w = struct.unpack_from(">H", bytearray(raw_data))[0] + return w + + +class ZXY6005s: + def __init__(self, port,input_delay=utils.INPUT_DELAY, baudrate=9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=1): + self.port = port + self.input_delay = input_delay + self.baudrate = baudrate + self.baudrate = baudrate + self.parity = parity + self.bytesize = bytesize + self.timeout = timeout + self.serial = None + utils.log(0, "Powersupply info:\n\tPort: " + str(port) + '\n\tInput delay: ' str(input_delay) + '\n\tBaud rate: ' + str(baudrate) + '\n\tParity: ' + str(parity) + '\n\t stop bits: ' + str(stopbits) + '\n\tByte Size: ' + str(bytesize) + '\n\tTimeout: ' + str(timeout)) + + def is_open(self): + return self.serial.is_open + + def get_device_information(self): + return self.__device_information + + def disconnect(self): + self.serial.close() + + def send_command(self, command): + self.serial.write(command.encode()) + + def set_voltage(self, voltage): + self.send_command(f"VSET:{voltage:.2f}") + + def set_current(self, current): + self.send_command(f"ISET:{current:.3f}") + + def enable_output(self): + self.send_command("OUT1") + + def disable_output(self): + self.send_command("OUT0") + + + + + + + + +#Notes +#Baudrate: speed of communication over a data channel +#Parity: bit added to a string as a form of error detection + + + diff --git a/testmain.py b/testmain.py new file mode 100644 index 0000000..4347e1f --- /dev/null +++ b/testmain.py @@ -0,0 +1,13 @@ +from zxy6005s import ZXY6005s + +psu = ZXY6005s('/dev/ttyUSB0') +psu.connec() + +psu.set_voltage(4.0) +psu.set_current(0.5) + +psu.enable_output() +time.sleep(10) +psu.disable_output() + +psu.disconnect() From ae1713617897e616b26ab073b96a74307b065ea9 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Sat, 27 May 2023 12:10:53 -0700 Subject: [PATCH 03/43] Reviving old code --- cage_controller.py | 2 +- command_line.py | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/cage_controller.py b/cage_controller.py index 716a160..8cd7eff 100644 --- a/cage_controller.py +++ b/cage_controller.py @@ -1,6 +1,6 @@ import serial # Stuff for controlling the power supplies import time # Stuff for regulated sensor delays -import smbus # Stuff for controlling temperature and magnetic sensors +import smbus2 # Stuff for controlling temperature and magnetic sensors import utilities as utils # Stuff for debugging and/or general info from gpiozero import LED diff --git a/command_line.py b/command_line.py index acf826a..22f9c70 100755 --- a/command_line.py +++ b/command_line.py @@ -122,4 +122,9 @@ def poll_data(duration = 10.0, dt = 1.0): time_step.append(time_step[-1] + dt) # temp_array.append(temperature()) mag_array.append(cage_controller.magnetometer()) - return time_step, mag_array #temp_array, mag_array \ No newline at end of file + return time_step, mag_array #temp_array, mag_array + +if __name__ == "__main__": + interface() + + From 9b10458d32db2bd3c1c772396b453fcc801ad0f3 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Wed, 21 Jun 2023 16:00:32 -0700 Subject: [PATCH 04/43] Arduino driver WIP --- Arduino_Comms/Arduino.py | 195 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 Arduino_Comms/Arduino.py diff --git a/Arduino_Comms/Arduino.py b/Arduino_Comms/Arduino.py new file mode 100644 index 0000000..32e2bf3 --- /dev/null +++ b/Arduino_Comms/Arduino.py @@ -0,0 +1,195 @@ +#This file enables communication with the Arduino which will control 3 H-Bridges (X,Y,Z) and initialized and interact with the magnetometer +#Documentation for Serial Commands: https://github.com/oresat/oresat-helmholtz/blob/main/Arduino_Comms/COMMS_README.txt +#Data Sheet + +import serial +import serial.tools.list_ports +from enum import Enum + +class Commands(Enum): + '''The following are the commands the arduino is listening for without any serial data returned''' + POSITIVE_X = 'x' + '''Activate X H-bridge in Positive Polarity''' + POSITIVE_Y = 'y' + '''Activate Y H-bridge in Positive Polarity''' + POSITIVE_Z = 'z' + '''Activate Z H-bridge in Positive Polarity''' + NEGATIVE_X = 'X' + '''Activate X H-bridge in Negative Polarity''' + NEGATIVE_Y = 'Y' + '''Activate Y H-bridge in Negative Polarity''' + NEGATIVE_Z = 'Z' + '''Activate Z H-bridge in Negative Polarity''' + DEACTIVATE_X = 'b' + '''De-Activate X H-Bridge''' + DEACTIVATE_Y = 'c' + '''De-Activate Y H-Bridge''' + DEACTIVATE_Z = 'd' + '''De-Activate Z H-Bridge''' + + '''The following are the commands the arduino is listening for with a serial data return''' + MAGNETOMETER = 'm' + '''Request current magnetic field reading + Data return is "X,Y,Z" magnetic field in uT. + The values of each value X,Y,Z can be positive or negative + Here is an example return: "1000.05, -200.33, 500.79" + Note: Refer to the nomen on the magnetometer to interpret positive and negative field directions''' + + MAGNETOMETER_STATUS = 'q' + '''Data return is "0" -- magnetometer not initialized + "1" -- magnetometer is initialized + note: magnetometer is initialized on setup/startup of arduino script. + Restarting the serial interface will reset the arduino and will attempt re-initialization. + If failures persist inspect wiring to sensor and the physical sensor.''' + + H_BRIDGE_STATUS = 's' + '''Query the H-Bridge's status: + Data return is "XYZ" where + X is X axis H-Bridge status + Y is Y axis H-Bridge status + Z is Z axis H-Bridge status + Each position can be 0, 1, or 2: + 0: Bridge is de-activated + 1: Bridge is activated in positive polarity + 2: Bridge is activated in negative polarity + Example: + 021 + X axis H-Bridge is de-activated + Y axis H-Bridge is activated in negative polarity + Z axis H-Bridge is activated in positive polarity''' + + MAGNETOMETER_TEMP = 't' + '''Request Ambient Temperature from Magnetometer: + The magnetometer has a temperature sensor built in, might as well provide the ability to read it. + The serial data return is in degrees Celcius: + ##.## + Example: 17.80''' + + +class Arduino: + + BAUDRATE = 9600 + INPUT_DELAY = 0.001 + BYTESIZE = serial.EIGHTBITS + PARITY = serial.PARITY_NONE + STOPBITS = serial.STOPBITS_ONE + TIMEOUT = 1 + + def __init__(self, name: str): + '''Object Construction. Passes the name of the arduino's USB port''' + serial_port = None + for i in serial.tools.list_ports.comports(): + if i.name == name: + serial_port = i.device + break + if serial_port is None: + raise Exception(f'Could not ind device with id of {name}') + + self.ser = serial.Serial( + port = serial_port, + baudrate = self.BAUDRATE, + parity = self.PARITY, + stopbits = self.STOPBITS, + bytesize = self.BYTESIZE, + timeout = self.TIMEOUT + ) + + def write_message(self, msg): + '''writes a command to serial port''' + if self.ser.out_waiting != 0: + self.ser.flush() + self.ser.write(msg) + self.ser.flush() + + def read_message(self, ending_token = '\n'): + '''reads from serial port until a specific character''' + data = self.ser.read_until(ending_token) + return data.decode().strip() + + def send_command(self, msg): + '''sends a command to serial port and reads the message returned''' + self.write_message(msg) + return self.read_message() + + def create_command(self, command): + '''creates command to send through serial port''' + ''' is address, ends on <\n>, and encode as bytes''' + msg = f'A{command}\n'.encode() + return msg +#definitions for function that help operate the commands. + @property + def set_positive_X(self) -> str: + '''str: set X H-bridge to positive polarity''' + msg = self.create_command(Commands.POSITIVE_X.value) + return self.send_command(msg) + + @property + def set_positive_Y(self) -> str: + '''str: set Y H-bridge to positive polarity''' + msg = self.create_command(Commands.POSITIVE_Y.value) + return self.send_command(msg) + + @property + def set_positive_Z(self) -> str: + '''str: set Z H-bridge to positive polarity''' + msg = self.create_command(Commands.POSITIVE_Z.value) + return self.send_command(msg) + + @property + def set_negative_X(self) -> str: + '''str: set X-bridge to negative polarity''' + msg = self.create_command(Commands.NEGATIVE_X.value) + return self.send_command(msg) + + @property + def set_negative_Y(self) -> str: + '''str: set Y-bridge to negative polarity''' + msg = self.create_command(Commands.NEGATIVE_Y.value) + return self.send_command(msg) + + @property + def set_negative_Z(self) -> str: + '''str: set Z-bridge to negative polarity''' + msg = self.create_command(Commands.NEGATIVE_Z.value) + return self.send_command(msg) + + @property + def deactivate_X(self) -> str: + '''str: turn off X H-bridge''' + msg = self.create_command(Commands.DEACTIVATE_X.value) + return self.send_command(msg) + + @property + def deactivate_Y(self) -> str: + '''str: turn off Y H-bridge''' + msg = self.create_command(Commands.DEACTIVATE_Y.value) + return self.send_command(msg) + + @property + def deactivate_Z(self) -> str: + '''str: turn off Z H-bridge''' + msg = self.create_command(Commands.DEACTIVATE_Z.value) + return self.send_command(msg) + + + + + + + + + + + + + + + + + + + + + + + From 81ac2a3f8ba60a565df00cee49fdf1b2e17988a2 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Fri, 23 Jun 2023 13:15:16 -0700 Subject: [PATCH 05/43] Arduino Driver WIP v2 --- Arduino_Comms/Arduino.py | 43 ++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/Arduino_Comms/Arduino.py b/Arduino_Comms/Arduino.py index 32e2bf3..f79b385 100644 --- a/Arduino_Comms/Arduino.py +++ b/Arduino_Comms/Arduino.py @@ -20,6 +20,11 @@ class Commands(Enum): '''Activate Y H-bridge in Negative Polarity''' NEGATIVE_Z = 'Z' '''Activate Z H-bridge in Negative Polarity''' + + #This command seems redundant. Uncomment if you want to use it. + #DEACTIVATE_ALL + #'''De-activates all H-Bridges''' + DEACTIVATE_X = 'b' '''De-Activate X H-Bridge''' DEACTIVATE_Y = 'c' @@ -28,7 +33,7 @@ class Commands(Enum): '''De-Activate Z H-Bridge''' '''The following are the commands the arduino is listening for with a serial data return''' - MAGNETOMETER = 'm' + MAGNETOMETER_READING = 'm' '''Request current magnetic field reading Data return is "X,Y,Z" magnetic field in uT. The values of each value X,Y,Z can be positive or negative @@ -152,6 +157,12 @@ def set_negative_Z(self) -> str: '''str: set Z-bridge to negative polarity''' msg = self.create_command(Commands.NEGATIVE_Z.value) return self.send_command(msg) + + #Deactivate all function. Comment out if you want to use it. + #def deactivate_all(self) -> str: + #str: deactivates all H-Bridges at the same time.''' + #msg = self.create_command(Commands.DEACTIVATE_ALL.value) + #return self.send_command(msg) @property def deactivate_X(self) -> str: @@ -171,13 +182,33 @@ def deactivate_Z(self) -> str: msg = self.create_command(Commands.DEACTIVATE_Z.value) return self.send_command(msg) - - - - - +#Missing 4 functions: + @property + def magnetometer_reading(self) -> str: + '''str: return current magnetic field reading''' + msg = self.create_command(Commands.MAGNETOMETER_READING.value) + return self.send_command(msg) +#do something print or decode() if this fails + @property + def magnetometer_status(self) -> str: + '''str: returns 0 if magnetometer not initialized. 1 otherwise.''' + msg = self.create_command(Commands.MAGNETOMETER_STATUS.value) + return self.send_command(msg) +#this should work + @property + def bridge_status(self) -> str: + '''str: data return off current status of each H-bridge''' + msg = self.create_command(Commands.H_BRIDGE_STATUS.value) + return self.send_command(msg) +#this should also work. Might need decode() + @property + def magnetometer_temp(self) -> str: + '''str: requests the ambient temperature of magnetometer.''' + msg = self.create_command(Commands.MAGNETOMETER_TEMP.value) + return self.send_command(msg) +#final command. this should work because it just returns a numberr From f6ee8bb40bf1dc021c8e8c3ec39f15123fede5d7 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Fri, 23 Jun 2023 15:25:52 -0700 Subject: [PATCH 06/43] Arduino Driver WIP v2.3 --- Arduino_Comms/Arduino.py | 136 +++++++++++++++++++-------------------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/Arduino_Comms/Arduino.py b/Arduino_Comms/Arduino.py index f79b385..42aeff8 100644 --- a/Arduino_Comms/Arduino.py +++ b/Arduino_Comms/Arduino.py @@ -81,82 +81,82 @@ class Arduino: TIMEOUT = 1 def __init__(self, name: str): - '''Object Construction. Passes the name of the arduino's USB port''' - serial_port = None - for i in serial.tools.list_ports.comports(): - if i.name == name: - serial_port = i.device - break - if serial_port is None: - raise Exception(f'Could not ind device with id of {name}') + '''Object Construction. Passes the name of the arduino's USB port''' + serial_port = None + for i in serial.tools.list_ports.comports(): + if i.name == name: + serial_port = i.device + break + if serial_port is None: + raise Exception(f'Could not ind device with id of {name}') - self.ser = serial.Serial( - port = serial_port, - baudrate = self.BAUDRATE, - parity = self.PARITY, - stopbits = self.STOPBITS, - bytesize = self.BYTESIZE, - timeout = self.TIMEOUT + self.ser = serial.Serial( + port = serial_port, + baudrate = self.BAUDRATE, + parity = self.PARITY, + stopbits = self.STOPBITS, + bytesize = self.BYTESIZE, + timeout = self.TIMEOUT ) def write_message(self, msg): - '''writes a command to serial port''' - if self.ser.out_waiting != 0: + '''writes a command to serial port''' + if self.ser.out_waiting != 0: self.ser.flush() - self.ser.write(msg) - self.ser.flush() + self.ser.write(msg) + self.ser.flush() def read_message(self, ending_token = '\n'): - '''reads from serial port until a specific character''' - data = self.ser.read_until(ending_token) - return data.decode().strip() + '''reads from serial port until a specific character''' + data = self.ser.read_until(ending_token) + return data.decode().strip() def send_command(self, msg): - '''sends a command to serial port and reads the message returned''' - self.write_message(msg) - return self.read_message() + '''sends a command to serial port and reads the message returned''' + self.write_message(msg) + return self.read_message() def create_command(self, command): - '''creates command to send through serial port''' - ''' is address, ends on <\n>, and encode as bytes''' - msg = f'A{command}\n'.encode() - return msg + '''creates command to send through serial port''' + ''' is address, ends on <\n>, and encode as bytes''' + msg = f'A{command}\n'.encode() + return msg #definitions for function that help operate the commands. @property def set_positive_X(self) -> str: - '''str: set X H-bridge to positive polarity''' - msg = self.create_command(Commands.POSITIVE_X.value) - return self.send_command(msg) + '''str: set X H-bridge to positive polarity''' + msg = self.create_command(Commands.POSITIVE_X.value) + return self.send_command(msg) @property def set_positive_Y(self) -> str: - '''str: set Y H-bridge to positive polarity''' - msg = self.create_command(Commands.POSITIVE_Y.value) - return self.send_command(msg) + '''str: set Y H-bridge to positive polarity''' + msg = self.create_command(Commands.POSITIVE_Y.value) + return self.send_command(msg) @property def set_positive_Z(self) -> str: - '''str: set Z H-bridge to positive polarity''' - msg = self.create_command(Commands.POSITIVE_Z.value) - return self.send_command(msg) + '''str: set Z H-bridge to positive polarity''' + msg = self.create_command(Commands.POSITIVE_Z.value) + return self.send_command(msg) @property def set_negative_X(self) -> str: - '''str: set X-bridge to negative polarity''' - msg = self.create_command(Commands.NEGATIVE_X.value) - return self.send_command(msg) + '''str: set X-bridge to negative polarity''' + msg = self.create_command(Commands.NEGATIVE_X.value) + return self.send_command(msg) @property def set_negative_Y(self) -> str: - '''str: set Y-bridge to negative polarity''' - msg = self.create_command(Commands.NEGATIVE_Y.value) - return self.send_command(msg) + '''str: set Y-bridge to negative polarity''' + msg = self.create_command(Commands.NEGATIVE_Y.value) + return self.send_command(msg) @property def set_negative_Z(self) -> str: - '''str: set Z-bridge to negative polarity''' - msg = self.create_command(Commands.NEGATIVE_Z.value) - return self.send_command(msg) + '''str: set Z-bridge to negative polarity''' + msg = self.create_command(Commands.NEGATIVE_Z.value) + return self.send_command(msg) #Deactivate all function. Comment out if you want to use it. #def deactivate_all(self) -> str: @@ -166,48 +166,48 @@ def set_negative_Z(self) -> str: @property def deactivate_X(self) -> str: - '''str: turn off X H-bridge''' - msg = self.create_command(Commands.DEACTIVATE_X.value) - return self.send_command(msg) + '''str: turn off X H-bridge''' + msg = self.create_command(Commands.DEACTIVATE_X.value) + return self.send_command(msg) @property def deactivate_Y(self) -> str: - '''str: turn off Y H-bridge''' - msg = self.create_command(Commands.DEACTIVATE_Y.value) - return self.send_command(msg) + '''str: turn off Y H-bridge''' + msg = self.create_command(Commands.DEACTIVATE_Y.value) + return self.send_command(msg) @property def deactivate_Z(self) -> str: - '''str: turn off Z H-bridge''' - msg = self.create_command(Commands.DEACTIVATE_Z.value) - return self.send_command(msg) + '''str: turn off Z H-bridge''' + msg = self.create_command(Commands.DEACTIVATE_Z.value) + return self.send_command(msg) #Missing 4 functions: @property def magnetometer_reading(self) -> str: - '''str: return current magnetic field reading''' - msg = self.create_command(Commands.MAGNETOMETER_READING.value) - return self.send_command(msg) + '''str: return current magnetic field reading''' + msg = self.create_command(Commands.MAGNETOMETER_READING.value) + return self.send_command(msg) #do something print or decode() if this fails @property def magnetometer_status(self) -> str: - '''str: returns 0 if magnetometer not initialized. 1 otherwise.''' - msg = self.create_command(Commands.MAGNETOMETER_STATUS.value) - return self.send_command(msg) + '''str: returns 0 if magnetometer not initialized. 1 otherwise.''' + msg = self.create_command(Commands.MAGNETOMETER_STATUS.value) + return self.send_command(msg) #this should work @property def bridge_status(self) -> str: - '''str: data return off current status of each H-bridge''' - msg = self.create_command(Commands.H_BRIDGE_STATUS.value) - return self.send_command(msg) + '''str: data return off current status of each H-bridge''' + msg = self.create_command(Commands.H_BRIDGE_STATUS.value) + return self.send_command(msg) #this should also work. Might need decode() @property def magnetometer_temp(self) -> str: - '''str: requests the ambient temperature of magnetometer.''' - msg = self.create_command(Commands.MAGNETOMETER_TEMP.value) - return self.send_command(msg) + '''str: requests the ambient temperature of magnetometer.''' + msg = self.create_command(Commands.MAGNETOMETER_TEMP.value) + return self.send_command(msg) #final command. this should work because it just returns a numberr From 2c78dba5383b82c884f4c35f62a3ca050dafe1b4 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Mon, 26 Jun 2023 13:53:14 -0700 Subject: [PATCH 07/43] Arduino driver v2.4 --- Arduino_Comms/Arduino.py | 266 +++++++++++++++++++-------------------- 1 file changed, 132 insertions(+), 134 deletions(-) diff --git a/Arduino_Comms/Arduino.py b/Arduino_Comms/Arduino.py index 42aeff8..6fa56f2 100644 --- a/Arduino_Comms/Arduino.py +++ b/Arduino_Comms/Arduino.py @@ -21,9 +21,8 @@ class Commands(Enum): NEGATIVE_Z = 'Z' '''Activate Z H-bridge in Negative Polarity''' - #This command seems redundant. Uncomment if you want to use it. - #DEACTIVATE_ALL - #'''De-activates all H-Bridges''' + DEACTIVATE_ALL = 'a' + '''De-activates all H-Bridges''' DEACTIVATE_X = 'b' '''De-Activate X H-Bridge''' @@ -72,143 +71,142 @@ class Commands(Enum): class Arduino: + + #Serial communication settings for the Arduino Nano. + BAUDRATE = 115200 + INPUT_DELAY = 0.001 + BYTESIZE = serial.EIGHTBITS + PARITY = serial.PARITY_NONE + STOPBITS = serial.STOPBITS_ONE + TIMEOUT = 1 + + def __init__(self, name: str): + '''Object Construction. Passes the name of the arduino's USB port''' + serial_port = None + for i in serial.tools.list_ports.comports(): + if i.name == name: + serial_port = i.device + break + if serial_port is None: + raise Exception(f'Could not ind device with id of {name}') - BAUDRATE = 9600 - INPUT_DELAY = 0.001 - BYTESIZE = serial.EIGHTBITS - PARITY = serial.PARITY_NONE - STOPBITS = serial.STOPBITS_ONE - TIMEOUT = 1 - - def __init__(self, name: str): - '''Object Construction. Passes the name of the arduino's USB port''' - serial_port = None - for i in serial.tools.list_ports.comports(): - if i.name == name: - serial_port = i.device - break - if serial_port is None: - raise Exception(f'Could not ind device with id of {name}') - - self.ser = serial.Serial( - port = serial_port, - baudrate = self.BAUDRATE, - parity = self.PARITY, - stopbits = self.STOPBITS, - bytesize = self.BYTESIZE, - timeout = self.TIMEOUT + self.ser = serial.Serial( + port = serial_port, + baudrate = self.BAUDRATE, + parity = self.PARITY, + stopbits = self.STOPBITS, + bytesize = self.BYTESIZE, + timeout = self.TIMEOUT ) - def write_message(self, msg): - '''writes a command to serial port''' - if self.ser.out_waiting != 0: - self.ser.flush() - self.ser.write(msg) - self.ser.flush() - - def read_message(self, ending_token = '\n'): - '''reads from serial port until a specific character''' - data = self.ser.read_until(ending_token) - return data.decode().strip() - - def send_command(self, msg): - '''sends a command to serial port and reads the message returned''' - self.write_message(msg) - return self.read_message() - - def create_command(self, command): - '''creates command to send through serial port''' - ''' is address, ends on <\n>, and encode as bytes''' - msg = f'A{command}\n'.encode() - return msg + def write_message(self, msg): + '''writes a command to serial port''' + if self.ser.out_waiting != 0: + self.ser.flush() + + self.ser.write(msg) + self.ser.flush() + + def read_message(self, ending_token = '\n'): + '''reads from serial port until a specific character''' + data = self.ser.read_until(ending_token) + return data.decode().strip() + + def send_command(self, msg): + '''sends a command to serial port and reads the message returned''' + self.write_message(msg) + return self.read_message() + + def create_command(self, command): + '''creates command to send through serial port''' + ''' is address, ends on <\n>, and encode as bytes''' + msg = f'A{command}\n'.encode() + return msg + #definitions for function that help operate the commands. - @property - def set_positive_X(self) -> str: - '''str: set X H-bridge to positive polarity''' - msg = self.create_command(Commands.POSITIVE_X.value) - return self.send_command(msg) - - @property - def set_positive_Y(self) -> str: - '''str: set Y H-bridge to positive polarity''' - msg = self.create_command(Commands.POSITIVE_Y.value) - return self.send_command(msg) - - @property - def set_positive_Z(self) -> str: - '''str: set Z H-bridge to positive polarity''' - msg = self.create_command(Commands.POSITIVE_Z.value) - return self.send_command(msg) - - @property - def set_negative_X(self) -> str: - '''str: set X-bridge to negative polarity''' - msg = self.create_command(Commands.NEGATIVE_X.value) - return self.send_command(msg) - - @property - def set_negative_Y(self) -> str: - '''str: set Y-bridge to negative polarity''' - msg = self.create_command(Commands.NEGATIVE_Y.value) - return self.send_command(msg) - - @property - def set_negative_Z(self) -> str: - '''str: set Z-bridge to negative polarity''' - msg = self.create_command(Commands.NEGATIVE_Z.value) - return self.send_command(msg) + @property + def set_positive_X(self) -> str: + '''str: set X H-bridge to positive polarity''' + msg = self.create_command(Commands.POSITIVE_X.value) + return self.send_command(msg) + + @property + def set_positive_Y(self) -> str: + '''str: set Y H-bridge to positive polarity''' + msg = self.create_command(Commands.POSITIVE_Y.value) + return self.send_command(msg) + + @property + def set_positive_Z(self) -> str: + '''str: set Z H-bridge to positive polarity''' + msg = self.create_command(Commands.POSITIVE_Z.value) + return self.send_command(msg) + + @property + def set_negative_X(self) -> str: + '''str: set X-bridge to negative polarity''' + msg = self.create_command(Commands.NEGATIVE_X.value) + return self.send_command(msg) + + @property + def set_negative_Y(self) -> str: + '''str: set Y-bridge to negative polarity''' + msg = self.create_command(Commands.NEGATIVE_Y.value) + return self.send_command(msg) + + @property + def set_negative_Z(self) -> str: + '''str: set Z-bridge to negative polarity''' + msg = self.create_command(Commands.NEGATIVE_Z.value) + return self.send_command(msg) + + @property + def deactivate_all(self) -> str: + '''str: deactivates all H-Bridges at the same time.''' + msg = self.create_command(Commands.DEACTIVATE_ALL.value) + return self.send_command(msg) + + @property + def deactivate_X(self) -> str: + '''str: turn off X H-bridge''' + msg = self.create_command(Commands.DEACTIVATE_X.value) + return self.send_command(msg) + + @property + def deactivate_Y(self) -> str: + '''str: turn off Y H-bridge''' + msg = self.create_command(Commands.DEACTIVATE_Y.value) + return self.send_command(msg) - #Deactivate all function. Comment out if you want to use it. - #def deactivate_all(self) -> str: - #str: deactivates all H-Bridges at the same time.''' - #msg = self.create_command(Commands.DEACTIVATE_ALL.value) - #return self.send_command(msg) - - @property - def deactivate_X(self) -> str: - '''str: turn off X H-bridge''' - msg = self.create_command(Commands.DEACTIVATE_X.value) - return self.send_command(msg) - - @property - def deactivate_Y(self) -> str: - '''str: turn off Y H-bridge''' - msg = self.create_command(Commands.DEACTIVATE_Y.value) - return self.send_command(msg) + @property + def deactivate_Z(self) -> str: + '''str: turn off Z H-bridge''' + msg = self.create_command(Commands.DEACTIVATE_Z.value) + return self.send_command(msg) + + @property + def magnetometer_reading(self) -> str: + '''str: return current magnetic field reading''' + msg = self.create_command(Commands.MAGNETOMETER_READING.value) + return self.send_command(msg) + + @property + def magnetometer_status(self) -> str: + '''str: returns 0 if magnetometer not initialized. 1 otherwise.''' + msg = self.create_command(Commands.MAGNETOMETER_STATUS.value) + return self.send_command(msg) + + @property + def bridge_status(self) -> str: + '''str: data return off current status of each H-bridge''' + msg = self.create_command(Commands.H_BRIDGE_STATUS.value) + return self.send_command(msg) - @property - def deactivate_Z(self) -> str: - '''str: turn off Z H-bridge''' - msg = self.create_command(Commands.DEACTIVATE_Z.value) - return self.send_command(msg) - -#Missing 4 functions: - @property - def magnetometer_reading(self) -> str: - '''str: return current magnetic field reading''' - msg = self.create_command(Commands.MAGNETOMETER_READING.value) - return self.send_command(msg) -#do something print or decode() if this fails - - @property - def magnetometer_status(self) -> str: - '''str: returns 0 if magnetometer not initialized. 1 otherwise.''' - msg = self.create_command(Commands.MAGNETOMETER_STATUS.value) - return self.send_command(msg) -#this should work - - @property - def bridge_status(self) -> str: - '''str: data return off current status of each H-bridge''' - msg = self.create_command(Commands.H_BRIDGE_STATUS.value) - return self.send_command(msg) -#this should also work. Might need decode() - @property - def magnetometer_temp(self) -> str: - '''str: requests the ambient temperature of magnetometer.''' - msg = self.create_command(Commands.MAGNETOMETER_TEMP.value) - return self.send_command(msg) -#final command. this should work because it just returns a numberr + @property + def magnetometer_temp(self) -> str: + '''str: requests the ambient temperature of magnetometer.''' + msg = self.create_command(Commands.MAGNETOMETER_TEMP.value) + return self.send_command(msg) From fc142f17533706feb22266f3f8d3f5265d707bea Mon Sep 17 00:00:00 2001 From: Gustavo Date: Thu, 29 Jun 2023 12:47:55 -0700 Subject: [PATCH 08/43] Updated Arduino Nano code. --- Arduino_Comms/PSAS_HHCage/PSAS_HHCage.ino | 159 ++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 Arduino_Comms/PSAS_HHCage/PSAS_HHCage.ino diff --git a/Arduino_Comms/PSAS_HHCage/PSAS_HHCage.ino b/Arduino_Comms/PSAS_HHCage/PSAS_HHCage.ino new file mode 100644 index 0000000..0866fdd --- /dev/null +++ b/Arduino_Comms/PSAS_HHCage/PSAS_HHCage.ino @@ -0,0 +1,159 @@ +#include +/* Assign a unique ID to this sensor at the same time */ +Adafruit_MMC5603 mmc = Adafruit_MMC5603(12345); + +//Assigning pins to variables +int xina = 6; +int xinb = 7; +int yina = 4; +int yinb = 5; +int zina = 2; +int zinb = 3; +int xstat = 0; +int ystat = 0; +int zstat = 0; +int magstat = 0; + + +int incomingByte = 0; // for incoming serial data + +void setup() { + // Setting pins as output. + pinMode(xina, OUTPUT); + pinMode(xinb, OUTPUT); + pinMode(yina, OUTPUT); + pinMode(yinb, OUTPUT); + pinMode(zina, OUTPUT); + pinMode(zinb, OUTPUT); + + //Setting all pins off + digitalWrite(xina,LOW); + digitalWrite(xinb,LOW); + digitalWrite(yina,LOW); + digitalWrite(yinb,LOW); + digitalWrite(zina,LOW); + digitalWrite(zinb,LOW); + + //Baudrate/bytes per second set. + Serial.begin(115200); + + + // Initialise the mag sensor */ + if (mmc.begin(MMC56X3_DEFAULT_ADDRESS, &Wire)) { // I2C mode + magstat = 1; + //mmc.printSensorDetails(); + } + +} + +void loop() { + // put your main code here, to run repeatedly: + + // reply only when you receive data: + if (Serial.available() > 0) { + // read the incoming byte: + incomingByte = Serial.read(); + + // say what you got: + // Serial.print("I received: "); + // Serial.println(incomingByte, DEC); + } + if (incomingByte != 0){ + //Shutdown + if (incomingByte == 97){ + digitalWrite(xina,LOW); + digitalWrite(xinb,LOW); + digitalWrite(yina,LOW); + digitalWrite(yinb,LOW); + digitalWrite(zina,LOW); + digitalWrite(zinb,LOW); + xstat = 0; + ystat = 0; + zstat = 0; + } + //X Bridge Off character: 'b' Not working + if (incomingByte == 'b'){ + digitalWrite(xina,LOW); + digitalWrite(xinb,LOW); + xstat = 0; + } + //Y Bridge Off character: 'c' Not working + if (incomingByte == 'c'){ + digitalWrite(yina,LOW); + digitalWrite(yinb,LOW); + ystat = 0; + } + //Z Bridge Off character: 'd' Not working + if (incomingByte == 'd'){ + digitalWrite(zina,LOW); + digitalWrite(zinb,LOW); + zstat = 0; + } + //H-Bridge Status message + if (incomingByte == 's'){ + Serial.print(xstat); + Serial.print(ystat); + Serial.println(zstat); + } + //mag Status message + if (incomingByte == 'q'){ + Serial.println(magstat); + } + //positive "x" + if (incomingByte == 'x'){ + digitalWrite(xinb,LOW); + digitalWrite(xina,HIGH); + xstat = 1; + } + //negative "X" Not working + if (incomingByte == 'X'){ + digitalWrite(xina,LOW); + digitalWrite(xinb,HIGH); + xstat = 2; + } + //positive "y" + if (incomingByte == 'y'){ + digitalWrite(yinb,LOW); + digitalWrite(yina,HIGH); + ystat = 1; + } + //negative "Y" Not working + if (incomingByte == 'Y'){ + digitalWrite(yina,LOW); + digitalWrite(yinb,HIGH); + ystat = 2; + } + //positive "z" + if (incomingByte == 'z'){ + digitalWrite(zinb,LOW); + digitalWrite(zina,HIGH); + zstat = 1; + } + //negative "Z" Not working + if (incomingByte == 'Z'){ + digitalWrite(zina,LOW); + digitalWrite(zinb,HIGH); + zstat = 2; + } + //mag reading + if (incomingByte == 'm'){ + sensors_event_t event; + mmc.getEvent(&event); + Serial.print(event.magnetic.x); + Serial.print(","); + Serial.print(event.magnetic.y); + Serial.print(","); + Serial.println(event.magnetic.z); + } + //temp reading + if (incomingByte == 't'){ + sensors_event_t event; + mmc.getEvent(&event); + float temp_c = mmc.readTemperature(); + Serial.println(temp_c); + } + //end of loop + incomingByte = 0; + Serial.flush(); +} +} From d3fe2c3949ecd7b3fa15f10c1868cd007f2f5c64 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Thu, 27 Jul 2023 10:38:04 -0700 Subject: [PATCH 09/43] ZXY6005s library (finished --- core_code/ZXY6005s.py | 224 +++++++++++++++++++++++++++++------------- 1 file changed, 154 insertions(+), 70 deletions(-) diff --git a/core_code/ZXY6005s.py b/core_code/ZXY6005s.py index 1ed818f..dcac48a 100644 --- a/core_code/ZXY6005s.py +++ b/core_code/ZXY6005s.py @@ -1,74 +1,158 @@ -import serial -import time -import utilities as utils #debugging -import struct - -#v1.1_0514 -# Library that manages the ZXY6005s power supply - +#Copy of ZXY6005s library. +#Author: Teresa Labolle +#Documentation: INSERT STUFF HERE -#these functions to be used for later -#raw bytes to a string -def as_string(raw_data): - return bytearray(raw_data[:-1]) - -#raw bytes to a float -def as_float(raw_data): - f = struct.unpack_from(">f", bytearray(raw_data))[0] - return f - -#raw bytes to a word -def as_word(raw_data): - w = struct.unpack_from(">H", bytearray(raw_data))[0] - return w +import serial +import serial.tools.list_ports +from enum import Enum + +class Commands(Enum): + '''Get power supply unit model. Response: ZXY6005s''' + MODEL = 'a' + '''Get firmware version. Response: R2.7Z''' + FIRMWARE_VERSION = 'v' + '''Set amp hour counter to specified value. Response: Asa(value)''' + SET_AMP_HOUR = 'sa' + '''Return the amp hour reading. Response: Ara(5 digit value)''' + RETURN_AMP_HOUR = 'ra' + '''Set voltage to specified value. Response: Asu(value)''' + SET_VOLTAGE = 'su' + '''Return voltage measurement. Response: Aru(5 digit value)''' + RETURN_VOLTAGE = 'ru' + '''Set current limit to specified value. Response: Asi(value)''' + SET_CURRENT_LIMIT = 'si' + '''Return current in amps. Response: Ari(4 digit value)''' + RETURN_CURRENT = 'ri' + '''Return current mode [Constant Voltage(CV) or Constant Current(CC)] Response: Arc0 or Arc1''' + RETURN_MODE = 'rc' + '''Return temperature in Celsius. Response: Art(3 digit value)''' + RETURN_TEMP = 'rt' + '''Set power output (On/Off). Response: Aso(1 or 0)''' + SET_OUTPUT = 'so' class ZXY6005s: - def __init__(self, port,input_delay=utils.INPUT_DELAY, baudrate=9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=1): - self.port = port - self.input_delay = input_delay - self.baudrate = baudrate - self.baudrate = baudrate - self.parity = parity - self.bytesize = bytesize - self.timeout = timeout - self.serial = None - utils.log(0, "Powersupply info:\n\tPort: " + str(port) + '\n\tInput delay: ' str(input_delay) + '\n\tBaud rate: ' + str(baudrate) + '\n\tParity: ' + str(parity) + '\n\t stop bits: ' + str(stopbits) + '\n\tByte Size: ' + str(bytesize) + '\n\tTimeout: ' + str(timeout)) - - def is_open(self): - return self.serial.is_open - - def get_device_information(self): - return self.__device_information - - def disconnect(self): - self.serial.close() - - def send_command(self, command): - self.serial.write(command.encode()) - - def set_voltage(self, voltage): - self.send_command(f"VSET:{voltage:.2f}") - - def set_current(self, current): - self.send_command(f"ISET:{current:.3f}") - - def enable_output(self): - self.send_command("OUT1") - - def disable_output(self): - self.send_command("OUT0") - - - - - - - - -#Notes -#Baudrate: speed of communication over a data channel -#Parity: bit added to a string as a form of error detection - - - + BAUDRATE = 9600 + INPUT_DELAY = 0.001 + BYTESIZE = serial.EIGHTBITS + PARITY = serial.PARITY_NONE + STOPBITS = serial.STOPBITS_ONE + TIMEOUT = 1 + + def __init__(self): + '''construct objects, using location for X, Y and Z power supplies''' + names = ['X', 'Y', 'Z'] + locations = ['1-1.5.4.3', '1-1.5.4.2', '1-1.5.4.1'] + self.devices = {} + for name, location in zip(names, locations): + serial_port = None + for i in serial.tools.list_ports.comports(): + if i.location == location: + serial_port = i.device + break + if serial_port is None: + raise Exception(f'Could not find device with location of {location}') + + self.devices[name] = serial.Serial( + port = serial_port, + baudrate = self.BAUDRATE, + parity = self.PARITY, + stopbits = self.STOPBITS, + bytesize = self.BYTESIZE, + timeout = self.TIMEOUT, + ) + + def write_message(self, device_name, msg): + '''writes a command to serial port''' + ser = self.devices[device_name] + if ser.out_waiting != 0: + ser.flush() + ser.write(msg) + ser.flush() + + def read_message(self, device_name, ending_token = '\n'): + '''reads from the serial port until a specified character''' + ser = self.devices[device_name] + data = ser.read_until(ending_token) + return data.decode().strip() + + def send_command(self, device_name, msg): + '''sends a command to serial port and reads the message returned''' + self.write_message(device_name, msg) + return self.read_message(device_name) + + def create_command(self, command): + '''creates a command to send through the serial port''' + ''' is address, end on <\n>, and encode as bytes''' + msg = f'A{command}\n'.encode() + return msg + + def model(self, device_name: str) -> str: + '''takes a device name and returns the model name''' + msg = self.create_command(Commands.MODEL.value) + return self.send_command(device_name, msg) + + def firmware_version(self, device_name: str) -> str: + '''takes a device name and returns the firmware version''' + msg = self.create_command(Commands.FIRMWARE_VERSION.value) + return self.send_command(device_name, msg) + + def set_output(self, device_name: str, value: bool): + '''takes a device name and a boolean: 1 for ON, 0 for OFF to set output ON/OFF''' + if value: + msg = f'{Commands.SET_OUTPUT.value}1' + else: + msg = f'{Commands.SET_OUTPUT.value}0' + msg = self.create_command(msg) + reply = self.send_command(device_name, msg) + if reply != msg.decode().strip(): + raise ValueError(f'Invalid reply was {reply}, expected {msg.decode().strip()}') + + def set_amp_hour(self, device_name: str, value: int): + '''takes a device name and an integer, sets amp hour counter to that value''' + msg = f'{Commands.SET_AMP_HOUR.value}{str(value)}' + msg = self.create_command(msg) + reply = self.send_command(device_name, msg) + if reply != msg.decode().strip(): + raise ValueError(f'Invalid reply was {reply}, expected {msg.decode().strip()}') + + def return_amp_hour(self, device_name: str) -> str: + '''takes a device name and returns amp hour reading''' + msg = self.create_command(Commands.RETURN_AMP_HOUR.value) + return self.send_command(device_name, msg) + + def set_voltage(self, device_name: str, value: int): + '''takes a device name and an integer, sets voltage to that value''' + msg = f'{Commands.SET_VOLTAGE.value}{str(value)}' + msg = self.create_command(msg) + reply = self.send_command(device_name, msg) + if reply != msg.decode().strip(): + raise ValueError(f'Invalid reply was {reply}, expected {msg.decode().strip()}') + + def return_voltage(self, device_name: str) -> str: + '''takes a device name and returns voltage measurement''' + msg = self.send_command(Commands.RETURN_VOLTAGE.value) + return self.send_command(device_name, msg) + + def set_current_limit(self, device_name: str, value: int): + '''takes a device name and an integer, sets current limit to that value''' + msg = f'{Commands.SET_CURRENT_LIMIT.value}{str(value)}' + msg = self.create_command(msg) + reply = self.send_command(device_name, msg) + if reply != msg.decode().strip(): + raise ValueError(f'Invalid reply was {reply}, expected {msg.decode().strip()}') + + def return_current(self, device_name: str) -> str: + '''takes a device name and returns current in amps''' + msg = self.create_command(Commands.RETURN_CURRENT.value) + + + def return_mode(self, device_name: str) -> str: + '''takes a device name and returns mode (CV or CC), see Data Sheet pg 6, Item 4''' + msg = self.create_command(Commands.RETURN_MODE.value) + return self.send_command(device_name, msg) + + def return_temp(self, device_name: str) -> str: + '''takes a device name and returns temperature in Celsius (of PSU?)''' + msg = self.create_command(Commands.RETURN_TEMP.value) + return self.send_command(device_name, msg) From f37e3c95bd8ff5cf6aa1d1a48f795a6049ebf05b Mon Sep 17 00:00:00 2001 From: Gustavo Date: Fri, 4 Aug 2023 15:30:55 -0700 Subject: [PATCH 10/43] Reorganized Helmholtz source code files --- oresat_helmholtz/Arduino.py | 224 +++++++++++++++++++++++++++++++++++ oresat_helmholtz/ZXY6005s.py | 158 ++++++++++++++++++++++++ oresat_helmholtz/__init__.py | 0 oresat_helmholtz/__main__.py | 52 ++++++++ 4 files changed, 434 insertions(+) create mode 100644 oresat_helmholtz/Arduino.py create mode 100644 oresat_helmholtz/ZXY6005s.py create mode 100644 oresat_helmholtz/__init__.py create mode 100644 oresat_helmholtz/__main__.py diff --git a/oresat_helmholtz/Arduino.py b/oresat_helmholtz/Arduino.py new file mode 100644 index 0000000..abed4f1 --- /dev/null +++ b/oresat_helmholtz/Arduino.py @@ -0,0 +1,224 @@ +#This file enables communication with the Arduino which will control 3 H-Bridges (X,Y,Z) and initialized and interact with the magnetometer +#Documentation for Serial Commands: https://github.com/oresat/oresat-helmholtz/blob/main/Arduino_Comms/COMMS_README.txt +#Data Sheet + +import serial +import serial.tools.list_ports +from enum import Enum + +class ArduinoCommands(Enum): + '''The following are the commands the arduino is listening for without any serial data returned''' + POSITIVE_X = 'x' + '''Activate X H-bridge in Positive Polarity''' + POSITIVE_Y = 'y' + '''Activate Y H-bridge in Positive Polarity''' + POSITIVE_Z = 'z' + '''Activate Z H-bridge in Positive Polarity''' + NEGATIVE_X = 'X' + '''Activate X H-bridge in Negative Polarity''' + NEGATIVE_Y = 'Y' + '''Activate Y H-bridge in Negative Polarity''' + NEGATIVE_Z = 'Z' + '''Activate Z H-bridge in Negative Polarity''' + + DEACTIVATE_ALL = 'a' + '''De-activates all H-Bridges''' + + DEACTIVATE_X = 'b' + '''De-Activate X H-Bridge''' + DEACTIVATE_Y = 'c' + '''De-Activate Y H-Bridge''' + DEACTIVATE_Z = 'd' + '''De-Activate Z H-Bridge''' + + '''The following are the commands the arduino is listening for with a serial data return''' + MAGNETOMETER_READING = 'm' + '''Request current magnetic field reading + Data return is "X,Y,Z" magnetic field in uT. + The values of each value X,Y,Z can be positive or negative + Here is an example return: "1000.05, -200.33, 500.79" + Note: Refer to the nomen on the magnetometer to interpret positive and negative field directions''' + + MAGNETOMETER_STATUS = 'q' + '''Data return is "0" -- magnetometer not initialized + "1" -- magnetometer is initialized + note: magnetometer is initialized on setup/startup of arduino script. + Restarting the serial interface will reset the arduino and will attempt re-initialization. + If failures persist inspect wiring to sensor and the physical sensor.''' + + H_BRIDGE_STATUS = 's' + '''Query the H-Bridge's status: + Data return is "XYZ" where + X is X axis H-Bridge status + Y is Y axis H-Bridge status + Z is Z axis H-Bridge status + Each position can be 0, 1, or 2: + 0: Bridge is de-activated + 1: Bridge is activated in positive polarity + 2: Bridge is activated in negative polarity + Example: + 021 + X axis H-Bridge is de-activated + Y axis H-Bridge is activated in negative polarity + Z axis H-Bridge is activated in positive polarity''' + + MAGNETOMETER_TEMP = 't' + '''Request Ambient Temperature from Magnetometer: + The magnetometer has a temperature sensor built in, might as well provide the ability to read it. + The serial data return is in degrees Celcius: + ##.## + Example: 17.80''' + + +class Arduino: + + #Serial communication settings for the Arduino Nano. + BAUDRATE = 115200 + INPUT_DELAY = 0.001 + BYTESIZE = serial.EIGHTBITS + PARITY = serial.PARITY_NONE + STOPBITS = serial.STOPBITS_ONE + TIMEOUT = 1 + + def __init__(self, name: str): + '''Object Construction. Passes the name of the arduino's USB port''' + serial_port = None + for i in serial.tools.list_ports.comports(): + if i.name == name: + serial_port = i.device + break + if serial_port is None: + raise Exception(f'Could not ind device with id of {name}') + + self.ser = serial.Serial( + port = serial_port, + baudrate = self.BAUDRATE, + parity = self.PARITY, + stopbits = self.STOPBITS, + bytesize = self.BYTESIZE, + timeout = self.TIMEOUT + ) + + def write_message(self, msg): + '''writes a command to serial port''' + if self.ser.out_waiting != 0: + self.ser.flush() + + self.ser.write(msg) + self.ser.flush() + + def read_message(self, ending_token = '\n'): + '''reads from serial port until a specific character''' + data = self.ser.read_until(ending_token) + return data.decode().strip() + + def send_command(self, msg): + '''sends a command to serial port and reads the message returned''' + self.write_message(msg) + return self.read_message() + + def create_command(self, command): + '''creates command to send through serial port''' + ''' is address, ends on <\n>, and encode as bytes''' + msg = f'A{command}\n'.encode() + return msg + +#definitions for function that help operate the commands. + @property + def set_positive_X(self) -> str: + '''str: set X H-bridge to positive polarity''' + msg = self.create_command(ArduinoCommands.POSITIVE_X.value) + return self.send_command(msg) + + @property + def set_positive_Y(self) -> str: + '''str: set Y H-bridge to positive polarity''' + msg = self.create_command(ArduinoCommands.POSITIVE_Y.value) + return self.send_command(msg) + + @property + def set_positive_Z(self) -> str: + '''str: set Z H-bridge to positive polarity''' + msg = self.create_command(ArduinoCommands.POSITIVE_Z.value) + return self.send_command(msg) + + @property + def set_negative_X(self) -> str: + '''str: set X-bridge to negative polarity''' + msg = self.create_command(ArduinoCommands.NEGATIVE_X.value) + return self.send_command(msg) + + @property + def set_negative_Y(self) -> str: + '''str: set Y-bridge to negative polarity''' + msg = self.create_command(ArduinoCommands.NEGATIVE_Y.value) + return self.send_command(msg) + + @property + def set_negative_Z(self) -> str: + '''str: set Z-bridge to negative polarity''' + msg = self.create_command(ArduinoCommands.NEGATIVE_Z.value) + return self.send_command(msg) + + @property + def deactivate_all(self) -> str: + '''str: deactivates all H-Bridges at the same time.''' + msg = self.create_command(ArduinoCommands.DEACTIVATE_ALL.value) + return self.send_command(msg) + + @property + def deactivate_X(self) -> str: + '''str: turn off X H-bridge''' + msg = self.create_command(ArduinoCommands.DEACTIVATE_X.value) + return self.send_command(msg) + + @property + def deactivate_Y(self) -> str: + '''str: turn off Y H-bridge''' + msg = self.create_command(ArduinoCommands.DEACTIVATE_Y.value) + return self.send_command(msg) + + @property + def deactivate_Z(self) -> str: + '''str: turn off Z H-bridge''' + msg = self.create_command(ArduinoCommands.DEACTIVATE_Z.value) + return self.send_command(msg) + + @property + def magnetometer_reading(self) -> str: + '''str: return current magnetic field reading''' + msg = self.create_command(ArduinoCommands.MAGNETOMETER_READING.value) + return self.send_command(msg) + + @property + def magnetometer_status(self) -> str: + '''str: returns 0 if magnetometer not initialized. 1 otherwise.''' + msg = self.create_command(ArduinoCommands.MAGNETOMETER_STATUS.value) + return self.send_command(msg) + + @property + def bridge_status(self) -> str: + '''str: data return off current status of each H-bridge''' + msg = self.create_command(ArduinoCommands.H_BRIDGE_STATUS.value) + return self.send_command(msg) + + @property + def magnetometer_temp(self) -> str: + '''str: requests the ambient temperature of magnetometer.''' + msg = self.create_command(ArduinoCommands.MAGNETOMETER_TEMP.value) + return self.send_command(msg) + + + + + + + + + + + + + + + diff --git a/oresat_helmholtz/ZXY6005s.py b/oresat_helmholtz/ZXY6005s.py new file mode 100644 index 0000000..c54886d --- /dev/null +++ b/oresat_helmholtz/ZXY6005s.py @@ -0,0 +1,158 @@ +#Copy of ZXY6005s library. +#Author: Teresa Labolle +#Documentation: INSERT STUFF HERE + +import serial +import serial.tools.list_ports +from enum import Enum + +class ZXY6005sCommands(Enum): + '''Get power supply unit model. Response: ZXY6005s''' + MODEL = 'a' + '''Get firmware version. Response: R2.7Z''' + FIRMWARE_VERSION = 'v' + '''Set amp hour counter to specified value. Response: Asa(value)''' + SET_AMP_HOUR = 'sa' + '''Return the amp hour reading. Response: Ara(5 digit value)''' + RETURN_AMP_HOUR = 'ra' + '''Set voltage to specified value. Response: Asu(value)''' + SET_VOLTAGE = 'su' + '''Return voltage measurement. Response: Aru(5 digit value)''' + RETURN_VOLTAGE = 'ru' + '''Set current limit to specified value. Response: Asi(value)''' + SET_CURRENT_LIMIT = 'si' + '''Return current in amps. Response: Ari(4 digit value)''' + RETURN_CURRENT = 'ri' + '''Return current mode [Constant Voltage(CV) or Constant Current(CC)] Response: Arc0 or Arc1''' + RETURN_MODE = 'rc' + '''Return temperature in Celsius. Response: Art(3 digit value)''' + RETURN_TEMP = 'rt' + '''Set power output (On/Off). Response: Aso(1 or 0)''' + SET_OUTPUT = 'so' + + +class ZXY6005s: + BAUDRATE = 9600 + INPUT_DELAY = 0.001 + BYTESIZE = serial.EIGHTBITS + PARITY = serial.PARITY_NONE + STOPBITS = serial.STOPBITS_ONE + TIMEOUT = 1 + + def __init__(self): + '''construct objects, using location for X, Y and Z power supplies''' + names = ['X', 'Y', 'Z'] + locations = ['1-1.5.4.3', '1-1.5.4.2', '1-1.5.4.1'] + self.devices = {} + for name, location in zip(names, locations): + serial_port = None + for i in serial.tools.list_ports.comports(): + if i.location == location: + serial_port = i.device + break + if serial_port is None: + raise Exception(f'Could not find device with location of {location}') + + self.devices[name] = serial.Serial( + port = serial_port, + baudrate = self.BAUDRATE, + parity = self.PARITY, + stopbits = self.STOPBITS, + bytesize = self.BYTESIZE, + timeout = self.TIMEOUT, + ) + + def write_message(self, device_name, msg): + '''writes a command to serial port''' + ser = self.devices[device_name] + if ser.out_waiting != 0: + ser.flush() + ser.write(msg) + ser.flush() + + def read_message(self, device_name, ending_token = '\n'): + '''reads from the serial port until a specified character''' + ser = self.devices[device_name] + data = ser.read_until(ending_token) + return data.decode().strip() + + def send_command(self, device_name, msg): + '''sends a command to serial port and reads the message returned''' + self.write_message(device_name, msg) + return self.read_message(device_name) + + def create_command(self, command): + '''creates a command to send through the serial port''' + ''' is address, end on <\n>, and encode as bytes''' + msg = f'A{command}\n'.encode() + return msg + + def model(self, device_name: str) -> str: + '''takes a device name and returns the model name''' + msg = self.create_command(ZXY6005sCommands.MODEL.value) + return self.send_command(device_name, msg) + + def firmware_version(self, device_name: str) -> str: + '''takes a device name and returns the firmware version''' + msg = self.create_command(ZXY6005sCommands.FIRMWARE_VERSION.value) + return self.send_command(device_name, msg) + + def set_output(self, device_name: str, value: bool): + '''takes a device name and a boolean: 1 for ON, 0 for OFF to set output ON/OFF''' + if value: + msg = f'{ZXY6005sCommands.SET_OUTPUT.value}1' + else: + msg = f'{ZXY6005sCommands.SET_OUTPUT.value}0' + msg = self.create_command(msg) + reply = self.send_command(device_name, msg) + if reply != msg.decode().strip(): + raise ValueError(f'Invalid reply was {reply}, expected {msg.decode().strip()}') + + def set_amp_hour(self, device_name: str, value: int): + '''takes a device name and an integer, sets amp hour counter to that value''' + msg = f'{ZXY6005sCommands.SET_AMP_HOUR.value}{str(value)}' + msg = self.create_command(msg) + reply = self.send_command(device_name, msg) + if reply != msg.decode().strip(): + raise ValueError(f'Invalid reply was {reply}, expected {msg.decode().strip()}') + + def return_amp_hour(self, device_name: str) -> str: + '''takes a device name and returns amp hour reading''' + msg = self.create_command(ZXY6005sCommands.RETURN_AMP_HOUR.value) + return self.send_command(device_name, msg) + + def set_voltage(self, device_name: str, value: int): + '''takes a device name and an integer, sets voltage to that value''' + msg = f'{ZXY6005sCommands.SET_VOLTAGE.value}{str(value)}' + msg = self.create_command(msg) + reply = self.send_command(device_name, msg) + if reply != msg.decode().strip(): + raise ValueError(f'Invalid reply was {reply}, expected {msg.decode().strip()}') + + def return_voltage(self, device_name: str) -> str: + '''takes a device name and returns voltage measurement''' + msg = self.send_command(ZXY6005sCommands.RETURN_VOLTAGE.value) + return self.send_command(device_name, msg) + + def set_current_limit(self, device_name: str, value: int): + '''takes a device name and an integer, sets current limit to that value''' + msg = f'{ZXY6005sCommands.SET_CURRENT_LIMIT.value}{str(value)}' + msg = self.create_command(msg) + reply = self.send_command(device_name, msg) + if reply != msg.decode().strip(): + raise ValueError(f'Invalid reply was {reply}, expected {msg.decode().strip()}') + + def return_current(self, device_name: str) -> str: + '''takes a device name and returns current in amps''' + msg = self.create_command(ZXY6005sCommands.RETURN_CURRENT.value) + + + def return_mode(self, device_name: str) -> str: + '''takes a device name and returns mode (CV or CC), see Data Sheet pg 6, Item 4''' + msg = self.create_command(ZXY6005sCommands.RETURN_MODE.value) + return self.send_command(device_name, msg) + + def return_temp(self, device_name: str) -> str: + '''takes a device name and returns temperature in Celsius (of PSU?)''' + msg = self.create_command(ZXY6005sCommands.RETURN_TEMP.value) + return self.send_command(device_name, msg) diff --git a/oresat_helmholtz/__init__.py b/oresat_helmholtz/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py new file mode 100644 index 0000000..58820de --- /dev/null +++ b/oresat_helmholtz/__main__.py @@ -0,0 +1,52 @@ +import cmd +from argparse import ArgumentParser + +from .Arduino import Arduino, ArduinoCommands +from .ZXY6005s import ZXY6005s, ZXY6005sCommands + +class HelmholtzShell(cmd.Cmd): + intro = "Welcome to the Helmholtz Shell! Type 'help' to list commands \n" + prompt = "> " + file = None + + def __init__(self, arduino: Arduino, psu: ZXY6005s, mock:bool): + super().__init__() + self.arduino = arduino + self.psu = psu + self.mock = mock + + def do_power(self, arg): + if not self.mock: + self.psu.set_output(arg[0].upper(), arg[1]=="1") + + + def help_power(self): + print("power ") + print("mag can be 'X', 'Y', or 'Z") + print("value can be '1' or '0'") + + def do_exit(self, arg): + return True + + def help_exit(self): + print("Type in exit to close the program ") + +def main(): + parser = ArgumentParser() + parser.add_argument('-d', '--device', default = '/dev/ttyUSB3', help='path to arduino device') + parser.add_argument('-m', '--mock', action = "store_true") + args = parser.parse_args() + + if args.mock: + arduino = None + psu = None + else: + arduino = Arduino(args.device) + psu = ZXY6005s() + + + shell = HelmholtzShell(arduino, psu, args.mock) + shell.cmdloop() + +if __name__ == "__main__": + main() From 07261713f54ad3609942766fc5a44435fadeec57 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Sun, 6 Aug 2023 15:46:38 -0700 Subject: [PATCH 11/43] Adding more functions to the HC shell --- oresat_helmholtz/__main__.py | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index 58820de..039c3e1 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -9,25 +9,46 @@ class HelmholtzShell(cmd.Cmd): prompt = "> " file = None + #Main objection construction for power supply and arduino libraries. def __init__(self, arduino: Arduino, psu: ZXY6005s, mock:bool): super().__init__() self.arduino = arduino self.psu = psu self.mock = mock - + + #Takes device name and returns model. + def do_model(self, arg): + if not self.mock: + self.psu.model(arg[0].upper()) + + #Help message for model command. + def help_model(self): + print("Device name can be 'X', 'Y' or 'Z'. ") + + #Takes device name and returns firmware version. + def do_firmware(self, arg): + if not self.mock: + self.psu.firmware_version(arg[0].upper()) + + #Help message for firmware function. + def help_firmware(self): + print("Device name can be 'X', 'Y', or 'Z'. ") + + #Turns on specified power supply. def do_power(self, arg): if not self.mock: self.psu.set_output(arg[0].upper(), arg[1]=="1") - + #Power supply on/off help message. def help_power(self): - print("power ") - print("mag can be 'X', 'Y', or 'Z") - print("value can be '1' or '0'") + print("Power . ") + print("Device name can be 'X', 'Y', or 'Z'. ") + print("Value can be '1' or '0', where '1' is on and '0' is off.") + #Closes program and exits. def do_exit(self, arg): return True - + #Help message for exit program. def help_exit(self): print("Type in exit to close the program ") From 763b1c251cf9d1ac7641ccd110e9a55d45ac40a1 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Fri, 11 Aug 2023 11:17:08 -0700 Subject: [PATCH 12/43] Adding more functions to the HC shell --- oresat_helmholtz/__main__.py | 227 +++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index 039c3e1..023ac2e 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -45,6 +45,233 @@ def help_power(self): print("Device name can be 'X', 'Y', or 'Z'. ") print("Value can be '1' or '0', where '1' is on and '0' is off.") + #Sets amp hour to counter value give. Takes device name and int value. + def do_amp_hour(self, arg): + if not self.mock: + self.psu.set_amp_hour(arg[0].upper(), arg[1]) + + #Amp hour set function help message. + def help_amp_hour(self): + print("Please enter device name and integer") + print("Device name can be 'X', 'Y', or 'Z'. ") + print("Value needs to be in amps") + + #Returns amp hour of a given device. + def do_return_amp_hour(self, arg): + if not self.mock: + self.psu.return_amp_hour(arg[0].upper()) + + #Help message for return amp hour + def help_return_amp_hour(self): + print("Device name can be 'X', 'Y', or 'Z'. ") + print("This function will return amp hour of device name given.") + + #Setting voltage for a specified device. + def do_voltage(self, arg): + if not self.mock: + self.psu.set_voltage(arg[0].upper(), arg[1]) + + #Help message for set voltage. + def help_voltage(self): + print("Device name can be 'X', 'Y', or 'Z'. ") + print("This function requires a int value. Please input voltage desired as an integer. ") + + #Returns voltage of a given device. + def do_return_voltage(self, arg): + if not self.mock: + self.psu.return_voltage(arg[0].upper()) + + #Help message for returning voltage. + def help_return_voltage(self): + print("Device name can be 'X', 'Y', or 'Z'. ") + print("This function is meant to return voltage of a given device. ") + + #Sets current limit to be a value entered. + def do_current_limit(self, arg): + if not self.mock: + self.psu.set_current_limit(arg[0].upper(), arg[1]) + + #Help message for current_limit function. + def help_current_limit(self): + print("Device name can only be 'X', 'Y' or 'Z'. ") + print("Value must be a integer with voltage units. ") + print("This function takes a device name and value and sets the current limit to that value. ") + + #Takes a device name and returns its current in amps. + def do_return_current(self, arg): + if not self.mock: + self.psu.return_current(arg[0].upper()) + + #Help message for returning current function. + def help_return_current(self): + print("This function takes a device name and returns its current in amps. ") + print("Device name can be 'X', 'Y', or 'Z'. ") + + #Returns the mode of a given device. + def do_return_mode(self, arg): + if not self.mock: + self.psu.return_mode(arg[0].upper()) + + #Help message for return_mode function. + def help_return_mode(self): + print("This function takes a device name and returns what mode it is in. ") + print("Modes can be CV (Constant Voltage) or CC (Constant Current). ") + print("Device name can only be 'X', 'Y', 'Z'. ") + + #Returns the temperature of a device in Celsius. + def do_return_temp(self, arg): + if not self.mock: + self.psu.return_temp(arg[0].upper()) + + #Help message for return_temp function. + def help_return_temp(self): + print("This function returns the temperature of a device name in Celsius. ") + print("Device name can only be 'X', 'Y', or 'Z'. ") + + #Set X H-bridge to positive polarity. + def do_set_postive_X(self, arg): + if not self.mock: + self.arduino.set_positive_X(arg[0]) + + #Help message for positive_X + def help_positive_X(self): + print("This function sets the X bridge to positive polarity.") + print("Accepted values are 'x'. ") + + #Set Y H-bridge to positive polarity. + def do_set_positive_Y(self, arg): + if not self.mock: + self.arduino.set_positive_Y(arg[0]) + + #Help message for positive_Y. + def help_positive_Y(self): + print("This function sets the Y bridge to positive polarity. ") + print("Accepted values are 'y'. ") + + #Set Z H-bridge to positive polarity. + def do_set_positive_Z(self, arg): + if not self.mock: + self.arduino.set_positive_Z(arg[0]) + + #Help message for positive_Z. + def help_positive_Z(self): + print("This function sets the Z bridge to positive polarity. ") + print("Accepted values are: 'z'. ") + + #Set X H-bridge to negative polarity. + def do_set_negative_X(self, arg): + if not self.mock: + self.arduino.set_negative_X(arg[0].upper()) + + #Help message for positive_x. + def help_set_negative_X(self): + print("This function sets the X H-bridge to negative polarity.") + print("Accepted values are: 'X'. ") + + #Set Y H-bridge to negative polarity. + def do_set_negative_Y(self, arg): + if not self.mock: + self.arduino.set_negative_Z(arg[0].upper()) + + #Help message for negative_Y. + def help_set_negative_Y(self): + print("This function sets the Y H-bridge to negative polarity. ") + print("Accepted values are: 'Y'. ") + + #Set Z H-bridge to negative polarity. + def do_set_negative_Z(self, arg): + if not self.mock: + self.arduino.set_negative_Z(arg[0].upper()) + + #Help message for set_negative_Z. + def help_set_negative_Z(self): + print("This function sets the Z H-bridge to negative polarity. ") + print("Accepted values are: 'Z'. ") + + #Deactivates all H-bridges. + def do_deactivate_all(self, arg): + if not self.mock: + self.arduino.deactivate_all(arg[0]) + + #Help message for deactivate_all. + def help_deactivate_all(self): + print("This function deactivates all H-Bridges. ") + print("Accepted values are: 'a'. ") + + #Deactivates the X H-bridge. + def do_deactivate_X(self, arg): + if not self.mock: + self.arduino.deactivate_X(arg[0]) + + #Help message for deactivate_X. + def help_deactivate_X(self): + print("This function deactivates just the X H-bridge. ") + print("Accepted values are: 'b'. ") + + #Deactivates the Y H-bridge. + def do_deactivate_Y(self, args): + if not self.mock: + self.arduino.deactivate_Y(arg[0]) + + #Help message for deactivate_Y. + def help_deactivate_Y(self): + print("This function deactivates just the Y H-bridge.") + print("Accepted values are: 'c'. ") + + #Deactivates the Z H-bridge. + def do_deactivate_Z(self, arg): + if not self.mock: + self.arduino.deactivate_Z(arg[0]) + + #Help message for deactivate_Z. + def help_deactivate_Z(self): + print("This function deactivates just the Z H-bridge. ") + print("Accepted values are: 'd'. ") + + #Returns the magnetic field reading. + def do_magnetometer_reading(self, arg): + if not self.mock: + self.arduino.magnetometer_reading(arg[0]) + + #Help message for magnetometer_reading. + def help_magnetometer_reading(self): + print("This function returns the current magnetic field reading. ") + print("Accepted values are: 'm'. ") + + #Is the magnetometer on or off? + def do_magnetometer_status(self, arg): + if not self.mock: + self.arduino.magnetometer_status(arg[0]) + + #Help message for magnetometer_status. + def help_magnetometer_reading(self): + print("This function returns whether the magnetometer is on/off. ") + print("Accepted values are: 'q'. ") + + #Returns the status of all 3 H-bridges. + def do_bridge_status(self, arg): + if not self.mock: + self.arduino.bridge_status(arg[0]) + + #Help message for bridge_status. + def help_bridge_status(self): + print("This function returns the status of all 3 H-bridges. ") + print("1 = Bridge set to positive polarity. ") + print("2 = Bridge set to negative polarity. ") + print("0 = Bridge is turned off. ") + print("Accepted values are: 's'. ") + + #Returns the temperature of the magnetometer. + def do_magnetometer_temp(self, arg): + if not self.mock: + self.arduino.magnetometer_temp(arg[0]) + + #Help message for magnetometer_temp. + def help_magnetometer_temp(self): + print("This function returns the temperature of the magnetometer in Celsius. ") + print("Accepted values are: 't'. ") + + #Closes program and exits. def do_exit(self, arg): return True From c7be74f360dfef52a4cff382acd330fadd00135a Mon Sep 17 00:00:00 2001 From: Gustavo Date: Fri, 11 Aug 2023 11:19:25 -0700 Subject: [PATCH 13/43] Corrections made to Arduino functions. --- oresat_helmholtz/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index 023ac2e..b673bde 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -209,7 +209,7 @@ def help_deactivate_X(self): print("Accepted values are: 'b'. ") #Deactivates the Y H-bridge. - def do_deactivate_Y(self, args): + def do_deactivate_Y(self, arg): if not self.mock: self.arduino.deactivate_Y(arg[0]) From 1836745121d863ef9f0d4b0fdda422b4d9aab5ea Mon Sep 17 00:00:00 2001 From: Gustavo Date: Fri, 11 Aug 2023 15:41:45 -0700 Subject: [PATCH 14/43] Updated Arduino driver v2.5 --- Arduino_Comms/Arduino.py | 224 --------------------------------------- 1 file changed, 224 deletions(-) delete mode 100644 Arduino_Comms/Arduino.py diff --git a/Arduino_Comms/Arduino.py b/Arduino_Comms/Arduino.py deleted file mode 100644 index 6fa56f2..0000000 --- a/Arduino_Comms/Arduino.py +++ /dev/null @@ -1,224 +0,0 @@ -#This file enables communication with the Arduino which will control 3 H-Bridges (X,Y,Z) and initialized and interact with the magnetometer -#Documentation for Serial Commands: https://github.com/oresat/oresat-helmholtz/blob/main/Arduino_Comms/COMMS_README.txt -#Data Sheet - -import serial -import serial.tools.list_ports -from enum import Enum - -class Commands(Enum): - '''The following are the commands the arduino is listening for without any serial data returned''' - POSITIVE_X = 'x' - '''Activate X H-bridge in Positive Polarity''' - POSITIVE_Y = 'y' - '''Activate Y H-bridge in Positive Polarity''' - POSITIVE_Z = 'z' - '''Activate Z H-bridge in Positive Polarity''' - NEGATIVE_X = 'X' - '''Activate X H-bridge in Negative Polarity''' - NEGATIVE_Y = 'Y' - '''Activate Y H-bridge in Negative Polarity''' - NEGATIVE_Z = 'Z' - '''Activate Z H-bridge in Negative Polarity''' - - DEACTIVATE_ALL = 'a' - '''De-activates all H-Bridges''' - - DEACTIVATE_X = 'b' - '''De-Activate X H-Bridge''' - DEACTIVATE_Y = 'c' - '''De-Activate Y H-Bridge''' - DEACTIVATE_Z = 'd' - '''De-Activate Z H-Bridge''' - - '''The following are the commands the arduino is listening for with a serial data return''' - MAGNETOMETER_READING = 'm' - '''Request current magnetic field reading - Data return is "X,Y,Z" magnetic field in uT. - The values of each value X,Y,Z can be positive or negative - Here is an example return: "1000.05, -200.33, 500.79" - Note: Refer to the nomen on the magnetometer to interpret positive and negative field directions''' - - MAGNETOMETER_STATUS = 'q' - '''Data return is "0" -- magnetometer not initialized - "1" -- magnetometer is initialized - note: magnetometer is initialized on setup/startup of arduino script. - Restarting the serial interface will reset the arduino and will attempt re-initialization. - If failures persist inspect wiring to sensor and the physical sensor.''' - - H_BRIDGE_STATUS = 's' - '''Query the H-Bridge's status: - Data return is "XYZ" where - X is X axis H-Bridge status - Y is Y axis H-Bridge status - Z is Z axis H-Bridge status - Each position can be 0, 1, or 2: - 0: Bridge is de-activated - 1: Bridge is activated in positive polarity - 2: Bridge is activated in negative polarity - Example: - 021 - X axis H-Bridge is de-activated - Y axis H-Bridge is activated in negative polarity - Z axis H-Bridge is activated in positive polarity''' - - MAGNETOMETER_TEMP = 't' - '''Request Ambient Temperature from Magnetometer: - The magnetometer has a temperature sensor built in, might as well provide the ability to read it. - The serial data return is in degrees Celcius: - ##.## - Example: 17.80''' - - -class Arduino: - - #Serial communication settings for the Arduino Nano. - BAUDRATE = 115200 - INPUT_DELAY = 0.001 - BYTESIZE = serial.EIGHTBITS - PARITY = serial.PARITY_NONE - STOPBITS = serial.STOPBITS_ONE - TIMEOUT = 1 - - def __init__(self, name: str): - '''Object Construction. Passes the name of the arduino's USB port''' - serial_port = None - for i in serial.tools.list_ports.comports(): - if i.name == name: - serial_port = i.device - break - if serial_port is None: - raise Exception(f'Could not ind device with id of {name}') - - self.ser = serial.Serial( - port = serial_port, - baudrate = self.BAUDRATE, - parity = self.PARITY, - stopbits = self.STOPBITS, - bytesize = self.BYTESIZE, - timeout = self.TIMEOUT - ) - - def write_message(self, msg): - '''writes a command to serial port''' - if self.ser.out_waiting != 0: - self.ser.flush() - - self.ser.write(msg) - self.ser.flush() - - def read_message(self, ending_token = '\n'): - '''reads from serial port until a specific character''' - data = self.ser.read_until(ending_token) - return data.decode().strip() - - def send_command(self, msg): - '''sends a command to serial port and reads the message returned''' - self.write_message(msg) - return self.read_message() - - def create_command(self, command): - '''creates command to send through serial port''' - ''' is address, ends on <\n>, and encode as bytes''' - msg = f'A{command}\n'.encode() - return msg - -#definitions for function that help operate the commands. - @property - def set_positive_X(self) -> str: - '''str: set X H-bridge to positive polarity''' - msg = self.create_command(Commands.POSITIVE_X.value) - return self.send_command(msg) - - @property - def set_positive_Y(self) -> str: - '''str: set Y H-bridge to positive polarity''' - msg = self.create_command(Commands.POSITIVE_Y.value) - return self.send_command(msg) - - @property - def set_positive_Z(self) -> str: - '''str: set Z H-bridge to positive polarity''' - msg = self.create_command(Commands.POSITIVE_Z.value) - return self.send_command(msg) - - @property - def set_negative_X(self) -> str: - '''str: set X-bridge to negative polarity''' - msg = self.create_command(Commands.NEGATIVE_X.value) - return self.send_command(msg) - - @property - def set_negative_Y(self) -> str: - '''str: set Y-bridge to negative polarity''' - msg = self.create_command(Commands.NEGATIVE_Y.value) - return self.send_command(msg) - - @property - def set_negative_Z(self) -> str: - '''str: set Z-bridge to negative polarity''' - msg = self.create_command(Commands.NEGATIVE_Z.value) - return self.send_command(msg) - - @property - def deactivate_all(self) -> str: - '''str: deactivates all H-Bridges at the same time.''' - msg = self.create_command(Commands.DEACTIVATE_ALL.value) - return self.send_command(msg) - - @property - def deactivate_X(self) -> str: - '''str: turn off X H-bridge''' - msg = self.create_command(Commands.DEACTIVATE_X.value) - return self.send_command(msg) - - @property - def deactivate_Y(self) -> str: - '''str: turn off Y H-bridge''' - msg = self.create_command(Commands.DEACTIVATE_Y.value) - return self.send_command(msg) - - @property - def deactivate_Z(self) -> str: - '''str: turn off Z H-bridge''' - msg = self.create_command(Commands.DEACTIVATE_Z.value) - return self.send_command(msg) - - @property - def magnetometer_reading(self) -> str: - '''str: return current magnetic field reading''' - msg = self.create_command(Commands.MAGNETOMETER_READING.value) - return self.send_command(msg) - - @property - def magnetometer_status(self) -> str: - '''str: returns 0 if magnetometer not initialized. 1 otherwise.''' - msg = self.create_command(Commands.MAGNETOMETER_STATUS.value) - return self.send_command(msg) - - @property - def bridge_status(self) -> str: - '''str: data return off current status of each H-bridge''' - msg = self.create_command(Commands.H_BRIDGE_STATUS.value) - return self.send_command(msg) - - @property - def magnetometer_temp(self) -> str: - '''str: requests the ambient temperature of magnetometer.''' - msg = self.create_command(Commands.MAGNETOMETER_TEMP.value) - return self.send_command(msg) - - - - - - - - - - - - - - - From 6131d3587145e13edd0b42433a397f247273aa2b Mon Sep 17 00:00:00 2001 From: Gustavo Date: Fri, 11 Aug 2023 15:43:46 -0700 Subject: [PATCH 15/43] PSU driver duplicate --- ZXY6005s.py | 74 -------------------- core_code/ZXY6005s.py | 158 ------------------------------------------ 2 files changed, 232 deletions(-) delete mode 100644 ZXY6005s.py delete mode 100644 core_code/ZXY6005s.py diff --git a/ZXY6005s.py b/ZXY6005s.py deleted file mode 100644 index 9360f06..0000000 --- a/ZXY6005s.py +++ /dev/null @@ -1,74 +0,0 @@ -import serial -import time -#import utilities as utils #debugging -import struct - -#v1.1_0514 -# Library that manages the ZXY6005s power supply - - -#these functions to be used for later -#raw bytes to a string -def as_string(raw_data): - return bytearray(raw_data[:-1]) - -#raw bytes to a float -def as_float(raw_data): - f = struct.unpack_from(">f", bytearray(raw_data))[0] - return f - -#raw bytes to a word -def as_word(raw_data): - w = struct.unpack_from(">H", bytearray(raw_data))[0] - return w - - -class ZXY6005s: - def __init__(self, port,input_delay=utils.INPUT_DELAY, baudrate=9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=1): - self.port = port - self.input_delay = input_delay - self.baudrate = baudrate - self.baudrate = baudrate - self.parity = parity - self.bytesize = bytesize - self.timeout = timeout - self.serial = None - utils.log(0, "Powersupply info:\n\tPort: " + str(port) + '\n\tInput delay: ' str(input_delay) + '\n\tBaud rate: ' + str(baudrate) + '\n\tParity: ' + str(parity) + '\n\t stop bits: ' + str(stopbits) + '\n\tByte Size: ' + str(bytesize) + '\n\tTimeout: ' + str(timeout)) - - def is_open(self): - return self.serial.is_open - - def get_device_information(self): - return self.__device_information - - def disconnect(self): - self.serial.close() - - def send_command(self, command): - self.serial.write(command.encode()) - - def set_voltage(self, voltage): - self.send_command(f"VSET:{voltage:.2f}") - - def set_current(self, current): - self.send_command(f"ISET:{current:.3f}") - - def enable_output(self): - self.send_command("OUT1") - - def disable_output(self): - self.send_command("OUT0") - - - - - - - - -#Notes -#Baudrate: speed of communication over a data channel -#Parity: bit added to a string as a form of error detection - - - diff --git a/core_code/ZXY6005s.py b/core_code/ZXY6005s.py deleted file mode 100644 index dcac48a..0000000 --- a/core_code/ZXY6005s.py +++ /dev/null @@ -1,158 +0,0 @@ -#Copy of ZXY6005s library. -#Author: Teresa Labolle -#Documentation: INSERT STUFF HERE - -import serial -import serial.tools.list_ports -from enum import Enum - -class Commands(Enum): - '''Get power supply unit model. Response: ZXY6005s''' - MODEL = 'a' - '''Get firmware version. Response: R2.7Z''' - FIRMWARE_VERSION = 'v' - '''Set amp hour counter to specified value. Response: Asa(value)''' - SET_AMP_HOUR = 'sa' - '''Return the amp hour reading. Response: Ara(5 digit value)''' - RETURN_AMP_HOUR = 'ra' - '''Set voltage to specified value. Response: Asu(value)''' - SET_VOLTAGE = 'su' - '''Return voltage measurement. Response: Aru(5 digit value)''' - RETURN_VOLTAGE = 'ru' - '''Set current limit to specified value. Response: Asi(value)''' - SET_CURRENT_LIMIT = 'si' - '''Return current in amps. Response: Ari(4 digit value)''' - RETURN_CURRENT = 'ri' - '''Return current mode [Constant Voltage(CV) or Constant Current(CC)] Response: Arc0 or Arc1''' - RETURN_MODE = 'rc' - '''Return temperature in Celsius. Response: Art(3 digit value)''' - RETURN_TEMP = 'rt' - '''Set power output (On/Off). Response: Aso(1 or 0)''' - SET_OUTPUT = 'so' - - -class ZXY6005s: - BAUDRATE = 9600 - INPUT_DELAY = 0.001 - BYTESIZE = serial.EIGHTBITS - PARITY = serial.PARITY_NONE - STOPBITS = serial.STOPBITS_ONE - TIMEOUT = 1 - - def __init__(self): - '''construct objects, using location for X, Y and Z power supplies''' - names = ['X', 'Y', 'Z'] - locations = ['1-1.5.4.3', '1-1.5.4.2', '1-1.5.4.1'] - self.devices = {} - for name, location in zip(names, locations): - serial_port = None - for i in serial.tools.list_ports.comports(): - if i.location == location: - serial_port = i.device - break - if serial_port is None: - raise Exception(f'Could not find device with location of {location}') - - self.devices[name] = serial.Serial( - port = serial_port, - baudrate = self.BAUDRATE, - parity = self.PARITY, - stopbits = self.STOPBITS, - bytesize = self.BYTESIZE, - timeout = self.TIMEOUT, - ) - - def write_message(self, device_name, msg): - '''writes a command to serial port''' - ser = self.devices[device_name] - if ser.out_waiting != 0: - ser.flush() - ser.write(msg) - ser.flush() - - def read_message(self, device_name, ending_token = '\n'): - '''reads from the serial port until a specified character''' - ser = self.devices[device_name] - data = ser.read_until(ending_token) - return data.decode().strip() - - def send_command(self, device_name, msg): - '''sends a command to serial port and reads the message returned''' - self.write_message(device_name, msg) - return self.read_message(device_name) - - def create_command(self, command): - '''creates a command to send through the serial port''' - ''' is address, end on <\n>, and encode as bytes''' - msg = f'A{command}\n'.encode() - return msg - - def model(self, device_name: str) -> str: - '''takes a device name and returns the model name''' - msg = self.create_command(Commands.MODEL.value) - return self.send_command(device_name, msg) - - def firmware_version(self, device_name: str) -> str: - '''takes a device name and returns the firmware version''' - msg = self.create_command(Commands.FIRMWARE_VERSION.value) - return self.send_command(device_name, msg) - - def set_output(self, device_name: str, value: bool): - '''takes a device name and a boolean: 1 for ON, 0 for OFF to set output ON/OFF''' - if value: - msg = f'{Commands.SET_OUTPUT.value}1' - else: - msg = f'{Commands.SET_OUTPUT.value}0' - msg = self.create_command(msg) - reply = self.send_command(device_name, msg) - if reply != msg.decode().strip(): - raise ValueError(f'Invalid reply was {reply}, expected {msg.decode().strip()}') - - def set_amp_hour(self, device_name: str, value: int): - '''takes a device name and an integer, sets amp hour counter to that value''' - msg = f'{Commands.SET_AMP_HOUR.value}{str(value)}' - msg = self.create_command(msg) - reply = self.send_command(device_name, msg) - if reply != msg.decode().strip(): - raise ValueError(f'Invalid reply was {reply}, expected {msg.decode().strip()}') - - def return_amp_hour(self, device_name: str) -> str: - '''takes a device name and returns amp hour reading''' - msg = self.create_command(Commands.RETURN_AMP_HOUR.value) - return self.send_command(device_name, msg) - - def set_voltage(self, device_name: str, value: int): - '''takes a device name and an integer, sets voltage to that value''' - msg = f'{Commands.SET_VOLTAGE.value}{str(value)}' - msg = self.create_command(msg) - reply = self.send_command(device_name, msg) - if reply != msg.decode().strip(): - raise ValueError(f'Invalid reply was {reply}, expected {msg.decode().strip()}') - - def return_voltage(self, device_name: str) -> str: - '''takes a device name and returns voltage measurement''' - msg = self.send_command(Commands.RETURN_VOLTAGE.value) - return self.send_command(device_name, msg) - - def set_current_limit(self, device_name: str, value: int): - '''takes a device name and an integer, sets current limit to that value''' - msg = f'{Commands.SET_CURRENT_LIMIT.value}{str(value)}' - msg = self.create_command(msg) - reply = self.send_command(device_name, msg) - if reply != msg.decode().strip(): - raise ValueError(f'Invalid reply was {reply}, expected {msg.decode().strip()}') - - def return_current(self, device_name: str) -> str: - '''takes a device name and returns current in amps''' - msg = self.create_command(Commands.RETURN_CURRENT.value) - - - def return_mode(self, device_name: str) -> str: - '''takes a device name and returns mode (CV or CC), see Data Sheet pg 6, Item 4''' - msg = self.create_command(Commands.RETURN_MODE.value) - return self.send_command(device_name, msg) - - def return_temp(self, device_name: str) -> str: - '''takes a device name and returns temperature in Celsius (of PSU?)''' - msg = self.create_command(Commands.RETURN_TEMP.value) - return self.send_command(device_name, msg) From 56f9cccb325aa4fd179bbc21b7e5c64d947d3c81 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Mon, 14 Aug 2023 11:33:01 -0700 Subject: [PATCH 16/43] Updated Arduino object constructor and main constructor. --- oresat_helmholtz/Arduino.py | 7 ++++--- oresat_helmholtz/__main__.py | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/oresat_helmholtz/Arduino.py b/oresat_helmholtz/Arduino.py index abed4f1..f6264ab 100644 --- a/oresat_helmholtz/Arduino.py +++ b/oresat_helmholtz/Arduino.py @@ -80,15 +80,16 @@ class Arduino: STOPBITS = serial.STOPBITS_ONE TIMEOUT = 1 - def __init__(self, name: str): + def __init__(self, location: str): '''Object Construction. Passes the name of the arduino's USB port''' serial_port = None + for i in serial.tools.list_ports.comports(): - if i.name == name: + if i.location == location: serial_port = i.device break if serial_port is None: - raise Exception(f'Could not ind device with id of {name}') + raise Exception(f'Could not find device with location of {location}') self.ser = serial.Serial( port = serial_port, diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index b673bde..acf3e6a 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -281,7 +281,7 @@ def help_exit(self): def main(): parser = ArgumentParser() - parser.add_argument('-d', '--device', default = '/dev/ttyUSB3', help='path to arduino device') + parser.add_argument('-l', '--arduino-location', help='Location to Arduino. ') parser.add_argument('-m', '--mock', action = "store_true") args = parser.parse_args() @@ -289,7 +289,7 @@ def main(): arduino = None psu = None else: - arduino = Arduino(args.device) + arduino = Arduino(args.arduino_location) psu = ZXY6005s() From ba2190bb34c6a0545e18e896b3ea16bf22ecfe52 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Mon, 14 Aug 2023 11:40:29 -0700 Subject: [PATCH 17/43] Updated ZXY6005s constructor. --- oresat_helmholtz/ZXY6005s.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/oresat_helmholtz/ZXY6005s.py b/oresat_helmholtz/ZXY6005s.py index c54886d..3f002b9 100644 --- a/oresat_helmholtz/ZXY6005s.py +++ b/oresat_helmholtz/ZXY6005s.py @@ -48,20 +48,18 @@ def __init__(self): serial_port = None for i in serial.tools.list_ports.comports(): if i.location == location: - serial_port = i.device + self.devices[name] = serial.Serial( + port = i.device, + baudrate = self.BAUDRATE, + parity = self.PARITY, + stopbits = self.STOPBITS, + bytesize = self.BYTESIZE, + timeout = self.TIMEOUT, + ) break if serial_port is None: raise Exception(f'Could not find device with location of {location}') - self.devices[name] = serial.Serial( - port = serial_port, - baudrate = self.BAUDRATE, - parity = self.PARITY, - stopbits = self.STOPBITS, - bytesize = self.BYTESIZE, - timeout = self.TIMEOUT, - ) - def write_message(self, device_name, msg): '''writes a command to serial port''' ser = self.devices[device_name] From 3052a5e85140a36d0d2ae3a159b204702e859397 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Mon, 14 Aug 2023 11:48:30 -0700 Subject: [PATCH 18/43] Updated ZXY6005s constructor. --- oresat_helmholtz/ZXY6005s.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/oresat_helmholtz/ZXY6005s.py b/oresat_helmholtz/ZXY6005s.py index 3f002b9..1fa8b83 100644 --- a/oresat_helmholtz/ZXY6005s.py +++ b/oresat_helmholtz/ZXY6005s.py @@ -45,7 +45,6 @@ def __init__(self): locations = ['1-1.5.4.3', '1-1.5.4.2', '1-1.5.4.1'] self.devices = {} for name, location in zip(names, locations): - serial_port = None for i in serial.tools.list_ports.comports(): if i.location == location: self.devices[name] = serial.Serial( @@ -57,8 +56,8 @@ def __init__(self): timeout = self.TIMEOUT, ) break - if serial_port is None: - raise Exception(f'Could not find device with location of {location}') + if len(self.devices) != 3: + raise Exception(f'Could not find all 3 devices. ') def write_message(self, device_name, msg): '''writes a command to serial port''' From 608a90e5b869778a446f90d147da20a3a0420ed8 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Mon, 14 Aug 2023 12:18:18 -0700 Subject: [PATCH 19/43] Updated main to work with updated Arduino driver. Removed properties and made them functions. --- oresat_helmholtz/Arduino.py | 39 ++++++++++++++--------------- oresat_helmholtz/__main__.py | 48 ++++++++++++++++++------------------ 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/oresat_helmholtz/Arduino.py b/oresat_helmholtz/Arduino.py index f6264ab..f5b6bf4 100644 --- a/oresat_helmholtz/Arduino.py +++ b/oresat_helmholtz/Arduino.py @@ -125,86 +125,85 @@ def create_command(self, command): return msg #definitions for function that help operate the commands. - @property + def set_positive_X(self) -> str: '''str: set X H-bridge to positive polarity''' msg = self.create_command(ArduinoCommands.POSITIVE_X.value) return self.send_command(msg) - - @property + def set_positive_Y(self) -> str: '''str: set Y H-bridge to positive polarity''' msg = self.create_command(ArduinoCommands.POSITIVE_Y.value) return self.send_command(msg) - @property - def set_positive_Z(self) -> str: + + def set_set_positive_Z(self) -> str: '''str: set Z H-bridge to positive polarity''' msg = self.create_command(ArduinoCommands.POSITIVE_Z.value) return self.send_command(msg) - @property + def set_negative_X(self) -> str: '''str: set X-bridge to negative polarity''' msg = self.create_command(ArduinoCommands.NEGATIVE_X.value) return self.send_command(msg) - @property + def set_negative_Y(self) -> str: '''str: set Y-bridge to negative polarity''' msg = self.create_command(ArduinoCommands.NEGATIVE_Y.value) return self.send_command(msg) - @property + def set_negative_Z(self) -> str: '''str: set Z-bridge to negative polarity''' msg = self.create_command(ArduinoCommands.NEGATIVE_Z.value) return self.send_command(msg) - @property + def deactivate_all(self) -> str: '''str: deactivates all H-Bridges at the same time.''' msg = self.create_command(ArduinoCommands.DEACTIVATE_ALL.value) return self.send_command(msg) - @property + def deactivate_X(self) -> str: '''str: turn off X H-bridge''' msg = self.create_command(ArduinoCommands.DEACTIVATE_X.value) return self.send_command(msg) - @property + def deactivate_Y(self) -> str: '''str: turn off Y H-bridge''' msg = self.create_command(ArduinoCommands.DEACTIVATE_Y.value) return self.send_command(msg) - @property + def deactivate_Z(self) -> str: '''str: turn off Z H-bridge''' msg = self.create_command(ArduinoCommands.DEACTIVATE_Z.value) return self.send_command(msg) - @property - def magnetometer_reading(self) -> str: + + def get_magnetometer_reading(self) -> str: '''str: return current magnetic field reading''' msg = self.create_command(ArduinoCommands.MAGNETOMETER_READING.value) return self.send_command(msg) - @property - def magnetometer_status(self) -> str: + + def get_magnetometer_status(self) -> str: '''str: returns 0 if magnetometer not initialized. 1 otherwise.''' msg = self.create_command(ArduinoCommands.MAGNETOMETER_STATUS.value) return self.send_command(msg) - @property - def bridge_status(self) -> str: + + def get_bridge_status(self) -> str: '''str: data return off current status of each H-bridge''' msg = self.create_command(ArduinoCommands.H_BRIDGE_STATUS.value) return self.send_command(msg) - @property - def magnetometer_temp(self) -> str: + + def get_magnetometer_temp(self) -> str: '''str: requests the ambient temperature of magnetometer.''' msg = self.create_command(ArduinoCommands.MAGNETOMETER_TEMP.value) return self.send_command(msg) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index acf3e6a..0a75f40 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -19,7 +19,7 @@ def __init__(self, arduino: Arduino, psu: ZXY6005s, mock:bool): #Takes device name and returns model. def do_model(self, arg): if not self.mock: - self.psu.model(arg[0].upper()) + print(self.psu.model(arg[0].upper())) #Help message for model command. def help_model(self): @@ -28,7 +28,7 @@ def help_model(self): #Takes device name and returns firmware version. def do_firmware(self, arg): if not self.mock: - self.psu.firmware_version(arg[0].upper()) + print(self.psu.firmware_version(arg[0].upper())) #Help message for firmware function. def help_firmware(self): @@ -37,7 +37,7 @@ def help_firmware(self): #Turns on specified power supply. def do_power(self, arg): if not self.mock: - self.psu.set_output(arg[0].upper(), arg[1]=="1") + print(self.psu.set_output(arg[0].upper(), arg[1]=="1")) #Power supply on/off help message. def help_power(self): @@ -48,7 +48,7 @@ def help_power(self): #Sets amp hour to counter value give. Takes device name and int value. def do_amp_hour(self, arg): if not self.mock: - self.psu.set_amp_hour(arg[0].upper(), arg[1]) + print(self.psu.set_amp_hour(arg[0].upper(), arg[1])) #Amp hour set function help message. def help_amp_hour(self): @@ -59,7 +59,7 @@ def help_amp_hour(self): #Returns amp hour of a given device. def do_return_amp_hour(self, arg): if not self.mock: - self.psu.return_amp_hour(arg[0].upper()) + print(self.psu.return_amp_hour(arg[0].upper())) #Help message for return amp hour def help_return_amp_hour(self): @@ -79,7 +79,7 @@ def help_voltage(self): #Returns voltage of a given device. def do_return_voltage(self, arg): if not self.mock: - self.psu.return_voltage(arg[0].upper()) + print(self.psu.return_voltage(arg[0].upper())) #Help message for returning voltage. def help_return_voltage(self): @@ -100,7 +100,7 @@ def help_current_limit(self): #Takes a device name and returns its current in amps. def do_return_current(self, arg): if not self.mock: - self.psu.return_current(arg[0].upper()) + print(self.psu.return_current(arg[0].upper())) #Help message for returning current function. def help_return_current(self): @@ -110,7 +110,7 @@ def help_return_current(self): #Returns the mode of a given device. def do_return_mode(self, arg): if not self.mock: - self.psu.return_mode(arg[0].upper()) + print(self.psu.return_mode(arg[0].upper())) #Help message for return_mode function. def help_return_mode(self): @@ -121,7 +121,7 @@ def help_return_mode(self): #Returns the temperature of a device in Celsius. def do_return_temp(self, arg): if not self.mock: - self.psu.return_temp(arg[0].upper()) + print(self.psu.return_temp(arg[0].upper())) #Help message for return_temp function. def help_return_temp(self): @@ -131,7 +131,7 @@ def help_return_temp(self): #Set X H-bridge to positive polarity. def do_set_postive_X(self, arg): if not self.mock: - self.arduino.set_positive_X(arg[0]) + print(self.arduino.set_positive_X()) #Help message for positive_X def help_positive_X(self): @@ -141,7 +141,7 @@ def help_positive_X(self): #Set Y H-bridge to positive polarity. def do_set_positive_Y(self, arg): if not self.mock: - self.arduino.set_positive_Y(arg[0]) + print(self.arduino.set_positive_Y()) #Help message for positive_Y. def help_positive_Y(self): @@ -151,7 +151,7 @@ def help_positive_Y(self): #Set Z H-bridge to positive polarity. def do_set_positive_Z(self, arg): if not self.mock: - self.arduino.set_positive_Z(arg[0]) + print(self.arduino.set_positive_Z()) #Help message for positive_Z. def help_positive_Z(self): @@ -161,7 +161,7 @@ def help_positive_Z(self): #Set X H-bridge to negative polarity. def do_set_negative_X(self, arg): if not self.mock: - self.arduino.set_negative_X(arg[0].upper()) + print(self.arduino.set_negative_X()) #Help message for positive_x. def help_set_negative_X(self): @@ -171,7 +171,7 @@ def help_set_negative_X(self): #Set Y H-bridge to negative polarity. def do_set_negative_Y(self, arg): if not self.mock: - self.arduino.set_negative_Z(arg[0].upper()) + print(self.arduino.set_negative_Z()) #Help message for negative_Y. def help_set_negative_Y(self): @@ -181,7 +181,7 @@ def help_set_negative_Y(self): #Set Z H-bridge to negative polarity. def do_set_negative_Z(self, arg): if not self.mock: - self.arduino.set_negative_Z(arg[0].upper()) + print(self.arduino.set_negative_Z()) #Help message for set_negative_Z. def help_set_negative_Z(self): @@ -191,7 +191,7 @@ def help_set_negative_Z(self): #Deactivates all H-bridges. def do_deactivate_all(self, arg): if not self.mock: - self.arduino.deactivate_all(arg[0]) + self.arduino.deactivate_all() #Help message for deactivate_all. def help_deactivate_all(self): @@ -201,7 +201,7 @@ def help_deactivate_all(self): #Deactivates the X H-bridge. def do_deactivate_X(self, arg): if not self.mock: - self.arduino.deactivate_X(arg[0]) + self.arduino.deactivate_X() #Help message for deactivate_X. def help_deactivate_X(self): @@ -211,7 +211,7 @@ def help_deactivate_X(self): #Deactivates the Y H-bridge. def do_deactivate_Y(self, arg): if not self.mock: - self.arduino.deactivate_Y(arg[0]) + self.arduino.deactivate_Y() #Help message for deactivate_Y. def help_deactivate_Y(self): @@ -221,7 +221,7 @@ def help_deactivate_Y(self): #Deactivates the Z H-bridge. def do_deactivate_Z(self, arg): if not self.mock: - self.arduino.deactivate_Z(arg[0]) + self.arduino.deactivate_Z() #Help message for deactivate_Z. def help_deactivate_Z(self): @@ -231,7 +231,7 @@ def help_deactivate_Z(self): #Returns the magnetic field reading. def do_magnetometer_reading(self, arg): if not self.mock: - self.arduino.magnetometer_reading(arg[0]) + print(self.arduino.get_magnetometer_reading()) #Help message for magnetometer_reading. def help_magnetometer_reading(self): @@ -241,17 +241,17 @@ def help_magnetometer_reading(self): #Is the magnetometer on or off? def do_magnetometer_status(self, arg): if not self.mock: - self.arduino.magnetometer_status(arg[0]) + print(self.arduino.get_magnetometer_status()) #Help message for magnetometer_status. - def help_magnetometer_reading(self): + def help_magnetometer_status(self): print("This function returns whether the magnetometer is on/off. ") print("Accepted values are: 'q'. ") #Returns the status of all 3 H-bridges. def do_bridge_status(self, arg): if not self.mock: - self.arduino.bridge_status(arg[0]) + print(self.arduino.get_bridge_status()) #Help message for bridge_status. def help_bridge_status(self): @@ -264,7 +264,7 @@ def help_bridge_status(self): #Returns the temperature of the magnetometer. def do_magnetometer_temp(self, arg): if not self.mock: - self.arduino.magnetometer_temp(arg[0]) + print(self.arduino.get_magnetometer_temp()) #Help message for magnetometer_temp. def help_magnetometer_temp(self): From 3274b2f1934bef18f6b91fbb34fedcbe8bc241dd Mon Sep 17 00:00:00 2001 From: Gustavo Date: Mon, 14 Aug 2023 12:31:22 -0700 Subject: [PATCH 20/43] Updated ZXY6005s functions that return int values. --- oresat_helmholtz/ZXY6005s.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/oresat_helmholtz/ZXY6005s.py b/oresat_helmholtz/ZXY6005s.py index 1fa8b83..3ef345f 100644 --- a/oresat_helmholtz/ZXY6005s.py +++ b/oresat_helmholtz/ZXY6005s.py @@ -113,10 +113,11 @@ def set_amp_hour(self, device_name: str, value: int): if reply != msg.decode().strip(): raise ValueError(f'Invalid reply was {reply}, expected {msg.decode().strip()}') - def return_amp_hour(self, device_name: str) -> str: + def return_amp_hour(self, device_name: str) -> int: '''takes a device name and returns amp hour reading''' msg = self.create_command(ZXY6005sCommands.RETURN_AMP_HOUR.value) - return self.send_command(device_name, msg) + raw = self.send_command(device_name, msg) + return int(raw[3:].decode()) def set_voltage(self, device_name: str, value: int): '''takes a device name and an integer, sets voltage to that value''' @@ -126,10 +127,11 @@ def set_voltage(self, device_name: str, value: int): if reply != msg.decode().strip(): raise ValueError(f'Invalid reply was {reply}, expected {msg.decode().strip()}') - def return_voltage(self, device_name: str) -> str: + def return_voltage(self, device_name: str) -> int: '''takes a device name and returns voltage measurement''' msg = self.send_command(ZXY6005sCommands.RETURN_VOLTAGE.value) - return self.send_command(device_name, msg) + raw = self.send_command(device_name, msg) + return int(raw[3:].decode()) def set_current_limit(self, device_name: str, value: int): '''takes a device name and an integer, sets current limit to that value''' @@ -139,9 +141,11 @@ def set_current_limit(self, device_name: str, value: int): if reply != msg.decode().strip(): raise ValueError(f'Invalid reply was {reply}, expected {msg.decode().strip()}') - def return_current(self, device_name: str) -> str: + def return_current(self, device_name: str) -> int: '''takes a device name and returns current in amps''' msg = self.create_command(ZXY6005sCommands.RETURN_CURRENT.value) + raw = self.send_command(device_name, msg) + return int(raw[4:].decode()) def return_mode(self, device_name: str) -> str: @@ -149,7 +153,8 @@ def return_mode(self, device_name: str) -> str: msg = self.create_command(ZXY6005sCommands.RETURN_MODE.value) return self.send_command(device_name, msg) - def return_temp(self, device_name: str) -> str: + def return_temp(self, device_name: str) -> int: '''takes a device name and returns temperature in Celsius (of PSU?)''' msg = self.create_command(ZXY6005sCommands.RETURN_TEMP.value) - return self.send_command(device_name, msg) + raw = self.send_command(device_name, msg) + return int(raw[4:].decode()) From 536b950f85d0552bd43d22f4ce477ab6a5fe3612 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Mon, 14 Aug 2023 12:34:18 -0700 Subject: [PATCH 21/43] Updated ZXY6005s functions that return int values. --- oresat_helmholtz/ZXY6005s.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/oresat_helmholtz/ZXY6005s.py b/oresat_helmholtz/ZXY6005s.py index 3ef345f..e5b938e 100644 --- a/oresat_helmholtz/ZXY6005s.py +++ b/oresat_helmholtz/ZXY6005s.py @@ -117,7 +117,7 @@ def return_amp_hour(self, device_name: str) -> int: '''takes a device name and returns amp hour reading''' msg = self.create_command(ZXY6005sCommands.RETURN_AMP_HOUR.value) raw = self.send_command(device_name, msg) - return int(raw[3:].decode()) + return int(raw[3:]) def set_voltage(self, device_name: str, value: int): '''takes a device name and an integer, sets voltage to that value''' @@ -131,7 +131,7 @@ def return_voltage(self, device_name: str) -> int: '''takes a device name and returns voltage measurement''' msg = self.send_command(ZXY6005sCommands.RETURN_VOLTAGE.value) raw = self.send_command(device_name, msg) - return int(raw[3:].decode()) + return int(raw[3:]) def set_current_limit(self, device_name: str, value: int): '''takes a device name and an integer, sets current limit to that value''' @@ -145,7 +145,7 @@ def return_current(self, device_name: str) -> int: '''takes a device name and returns current in amps''' msg = self.create_command(ZXY6005sCommands.RETURN_CURRENT.value) raw = self.send_command(device_name, msg) - return int(raw[4:].decode()) + return int(raw[4:]) def return_mode(self, device_name: str) -> str: @@ -157,4 +157,4 @@ def return_temp(self, device_name: str) -> int: '''takes a device name and returns temperature in Celsius (of PSU?)''' msg = self.create_command(ZXY6005sCommands.RETURN_TEMP.value) raw = self.send_command(device_name, msg) - return int(raw[4:].decode()) + return int(raw[4:]) From 0dc14f65affdb2057cf1e34fd31934ed1915309f Mon Sep 17 00:00:00 2001 From: Gustavo Date: Mon, 14 Aug 2023 12:56:46 -0700 Subject: [PATCH 22/43] Updated psu power function in main. --- oresat_helmholtz/ZXY6005s.py | 12 ++++++++---- oresat_helmholtz/__main__.py | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/oresat_helmholtz/ZXY6005s.py b/oresat_helmholtz/ZXY6005s.py index e5b938e..94d80d7 100644 --- a/oresat_helmholtz/ZXY6005s.py +++ b/oresat_helmholtz/ZXY6005s.py @@ -145,16 +145,20 @@ def return_current(self, device_name: str) -> int: '''takes a device name and returns current in amps''' msg = self.create_command(ZXY6005sCommands.RETURN_CURRENT.value) raw = self.send_command(device_name, msg) - return int(raw[4:]) + return int(raw[3:]) def return_mode(self, device_name: str) -> str: - '''takes a device name and returns mode (CV or CC), see Data Sheet pg 6, Item 4''' + '''takes a device name and returns mode. see Data Sheet pg 6, Item 4''' msg = self.create_command(ZXY6005sCommands.RETURN_MODE.value) - return self.send_command(device_name, msg) + raw = self.send_command(device_name, msg) + if int(raw[3:]) == 1: + return 'CC' + else: + return 'CV' def return_temp(self, device_name: str) -> int: '''takes a device name and returns temperature in Celsius (of PSU?)''' msg = self.create_command(ZXY6005sCommands.RETURN_TEMP.value) raw = self.send_command(device_name, msg) - return int(raw[4:]) + return int(raw[3:]) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index 0a75f40..4f14d21 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -37,7 +37,8 @@ def help_firmware(self): #Turns on specified power supply. def do_power(self, arg): if not self.mock: - print(self.psu.set_output(arg[0].upper(), arg[1]=="1")) + args = arg.split(" ") + print(self.psu.set_output(args[0].upper(), args[1]=="1")) #Power supply on/off help message. def help_power(self): From b8c01d9fcbcf22403adfd83fad303cc080a11df7 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Mon, 14 Aug 2023 13:04:37 -0700 Subject: [PATCH 23/43] Updated exit function. --- oresat_helmholtz/__main__.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index 4f14d21..ac49306 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -130,12 +130,12 @@ def help_return_temp(self): print("Device name can only be 'X', 'Y', or 'Z'. ") #Set X H-bridge to positive polarity. - def do_set_postive_X(self, arg): + def do_set_positive_X(self, arg): if not self.mock: print(self.arduino.set_positive_X()) #Help message for positive_X - def help_positive_X(self): + def help_set_positive_X(self): print("This function sets the X bridge to positive polarity.") print("Accepted values are 'x'. ") @@ -145,7 +145,7 @@ def do_set_positive_Y(self, arg): print(self.arduino.set_positive_Y()) #Help message for positive_Y. - def help_positive_Y(self): + def help_set_positive_Y(self): print("This function sets the Y bridge to positive polarity. ") print("Accepted values are 'y'. ") @@ -155,7 +155,7 @@ def do_set_positive_Z(self, arg): print(self.arduino.set_positive_Z()) #Help message for positive_Z. - def help_positive_Z(self): + def help_set_positive_Z(self): print("This function sets the Z bridge to positive polarity. ") print("Accepted values are: 'z'. ") @@ -275,6 +275,10 @@ def help_magnetometer_temp(self): #Closes program and exits. def do_exit(self, arg): + print("Disabling power supplies.") + self.psu.set_output('X', 0) + self.psu.set_output('Y', 0) + self.psu.set_output('Z', 0) return True #Help message for exit program. def help_exit(self): From b219ee1a044ccae462ea642e29f5d1fa8dbe2d78 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Wed, 16 Aug 2023 12:58:24 -0700 Subject: [PATCH 24/43] Fixed an issue with ZXY6005s return voltage function. --- oresat_helmholtz/ZXY6005s.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oresat_helmholtz/ZXY6005s.py b/oresat_helmholtz/ZXY6005s.py index 94d80d7..eae91b0 100644 --- a/oresat_helmholtz/ZXY6005s.py +++ b/oresat_helmholtz/ZXY6005s.py @@ -129,7 +129,7 @@ def set_voltage(self, device_name: str, value: int): def return_voltage(self, device_name: str) -> int: '''takes a device name and returns voltage measurement''' - msg = self.send_command(ZXY6005sCommands.RETURN_VOLTAGE.value) + msg = self.create_command(ZXY6005sCommands.RETURN_VOLTAGE.value) raw = self.send_command(device_name, msg) return int(raw[3:]) From 0d109d1fde2bcfb0439b720d8f6ad06f330ff491 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Wed, 16 Aug 2023 13:20:37 -0700 Subject: [PATCH 25/43] Fixed an issue with setting Z H-bridge to positive polarity. --- oresat_helmholtz/Arduino.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oresat_helmholtz/Arduino.py b/oresat_helmholtz/Arduino.py index f5b6bf4..141d42f 100644 --- a/oresat_helmholtz/Arduino.py +++ b/oresat_helmholtz/Arduino.py @@ -137,7 +137,7 @@ def set_positive_Y(self) -> str: return self.send_command(msg) - def set_set_positive_Z(self) -> str: + def set_positive_Z(self) -> str: '''str: set Z H-bridge to positive polarity''' msg = self.create_command(ArduinoCommands.POSITIVE_Z.value) return self.send_command(msg) From 09ea87c6fe0e369dd9f05a66cc50e48c891e95f6 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Wed, 16 Aug 2023 13:55:48 -0700 Subject: [PATCH 26/43] Fixed an issue with setting Y H-Bridge to negative polarity. --- oresat_helmholtz/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index ac49306..d426f84 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -172,7 +172,7 @@ def help_set_negative_X(self): #Set Y H-bridge to negative polarity. def do_set_negative_Y(self, arg): if not self.mock: - print(self.arduino.set_negative_Z()) + print(self.arduino.set_negative_Y()) #Help message for negative_Y. def help_set_negative_Y(self): From 744c18dfabc88136a3d39dbb1c435d49055e5e27 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Mon, 21 Aug 2023 11:44:25 -0700 Subject: [PATCH 27/43] Rewrote commands for ZXY and changed a mode function. --- oresat_helmholtz/ZXY6005s.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/oresat_helmholtz/ZXY6005s.py b/oresat_helmholtz/ZXY6005s.py index eae91b0..398837b 100644 --- a/oresat_helmholtz/ZXY6005s.py +++ b/oresat_helmholtz/ZXY6005s.py @@ -7,29 +7,30 @@ from enum import Enum class ZXY6005sCommands(Enum): - '''Get power supply unit model. Response: ZXY6005s''' MODEL = 'a' - '''Get firmware version. Response: R2.7Z''' + '''Get power supply unit model. Response: ZXY6005s.''' FIRMWARE_VERSION = 'v' - '''Set amp hour counter to specified value. Response: Asa(value)''' + '''Get firmware version. Response: R2.7Z''' SET_AMP_HOUR = 'sa' - '''Return the amp hour reading. Response: Ara(5 digit value)''' + '''Set amp hour counter to specified value. Response: Asa(value)''' RETURN_AMP_HOUR = 'ra' - '''Set voltage to specified value. Response: Asu(value)''' + '''Return the amp hour reading. Response: Ara(5 digit value)''' SET_VOLTAGE = 'su' - '''Return voltage measurement. Response: Aru(5 digit value)''' + '''Set voltage to specified value. Response: Asu(value)''' RETURN_VOLTAGE = 'ru' - '''Set current limit to specified value. Response: Asi(value)''' + '''Return voltage measurement. Response: Aru(5 digit value)''' SET_CURRENT_LIMIT = 'si' - '''Return current in amps. Response: Ari(4 digit value)''' + '''Set current limit to specified value. Response: Asi(value)''' RETURN_CURRENT = 'ri' - '''Return current mode [Constant Voltage(CV) or Constant Current(CC)] Response: Arc0 or Arc1''' + '''Return current in amps. Response: Ari(4 digit value)''' + SET_MODE = 'sc' + '''Sets mode for each power supply. [Constant Voltage (CV) or Constant Current (CC)]''' RETURN_MODE = 'rc' - '''Return temperature in Celsius. Response: Art(3 digit value)''' + '''Return current mode [Constant Voltage(CV) or Constant Current(CC)] Response: Arc0 or Arc1''' RETURN_TEMP = 'rt' - '''Set power output (On/Off). Response: Aso(1 or 0)''' + '''Return temperature in Celsius. Response: Art(3 digit value)''' SET_OUTPUT = 'so' - + '''Set power output (On/Off). Response: Aso(1 or 0)''' class ZXY6005s: BAUDRATE = 9600 From f0c2f3d33f51c6bc87f866cda04550dbe0a3cb06 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Mon, 21 Aug 2023 15:12:39 -0700 Subject: [PATCH 28/43] Attempt to fix setting the current function in the HC shell. --- oresat_helmholtz/ZXY6005s.py | 6 ++---- oresat_helmholtz/__main__.py | 8 +++++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/oresat_helmholtz/ZXY6005s.py b/oresat_helmholtz/ZXY6005s.py index 398837b..c523653 100644 --- a/oresat_helmholtz/ZXY6005s.py +++ b/oresat_helmholtz/ZXY6005s.py @@ -22,9 +22,7 @@ class ZXY6005sCommands(Enum): SET_CURRENT_LIMIT = 'si' '''Set current limit to specified value. Response: Asi(value)''' RETURN_CURRENT = 'ri' - '''Return current in amps. Response: Ari(4 digit value)''' - SET_MODE = 'sc' - '''Sets mode for each power supply. [Constant Voltage (CV) or Constant Current (CC)]''' + '''Return current in amps. Response: Ari(4 digit value)''' RETURN_MODE = 'rc' '''Return current mode [Constant Voltage(CV) or Constant Current(CC)] Response: Arc0 or Arc1''' RETURN_TEMP = 'rt' @@ -138,7 +136,7 @@ def set_current_limit(self, device_name: str, value: int): '''takes a device name and an integer, sets current limit to that value''' msg = f'{ZXY6005sCommands.SET_CURRENT_LIMIT.value}{str(value)}' msg = self.create_command(msg) - reply = self.send_command(device_name, msg) + reply = self.send_command(device_name, msg) if reply != msg.decode().strip(): raise ValueError(f'Invalid reply was {reply}, expected {msg.decode().strip()}') diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index d426f84..d91770f 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -89,8 +89,14 @@ def help_return_voltage(self): #Sets current limit to be a value entered. def do_current_limit(self, arg): + args = arg.split(" ") + try: + value = int(args[1]) + except ValueError: + self.help_current_limit() + return if not self.mock: - self.psu.set_current_limit(arg[0].upper(), arg[1]) + print(self.psu.set_current_limit(arg[0].upper(), value)) #Help message for current_limit function. def help_current_limit(self): From 264bf6a364f21213cdd78a377c6334b9a5f66f07 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Mon, 21 Aug 2023 15:17:37 -0700 Subject: [PATCH 29/43] Fully functional HC shell. Fixed all bugs --- oresat_helmholtz/__main__.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index d91770f..c486cae 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -69,8 +69,14 @@ def help_return_amp_hour(self): #Setting voltage for a specified device. def do_voltage(self, arg): + args = arg.split(" ") + try: + value = int(args[1]) + except ValueError: + self.help_voltage() + return if not self.mock: - self.psu.set_voltage(arg[0].upper(), arg[1]) + self.psu.set_voltage(arg[0].upper(), value) #Help message for set voltage. def help_voltage(self): From f2562b2e7455918790e4e4a748746a629e003581 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Sun, 3 Sep 2023 17:03:32 -0700 Subject: [PATCH 30/43] Added Calibration Function. Can write to a .CSV and sweep test all axis. --- oresat_helmholtz/__main__.py | 55 ++++++++++++++++++++++++- oresat_helmholtz/sweepdata.csv | 74 ++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 oresat_helmholtz/sweepdata.csv diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index c486cae..b9cc9ab 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -1,11 +1,12 @@ import cmd +import csv from argparse import ArgumentParser from .Arduino import Arduino, ArduinoCommands from .ZXY6005s import ZXY6005s, ZXY6005sCommands class HelmholtzShell(cmd.Cmd): - intro = "Welcome to the Helmholtz Shell! Type 'help' to list commands \n" + intro = "Welcome to the Helmholtz Cage Shell! Type 'help' to list commands \n" prompt = "> " file = None @@ -283,7 +284,59 @@ def do_magnetometer_temp(self, arg): def help_magnetometer_temp(self): print("This function returns the temperature of the magnetometer in Celsius. ") print("Accepted values are: 't'. ") + + #Calibration function prototype + def do_calibration(self): + if not self.mock: + max_current = 1000 + min_current = 0 + step = -100 + with open("cage_cal.csv", "w") as new_file: + fieldnames = ['Current (A)', 'Magnetic Field X (T)', 'Magnetic Field Y (T)', 'Magnetic Field Z (T)'] + csv_writer= csv.DictWriter(new_file, fieldsnames = fieldnames, delimiter='\t') + csv_writer.writeheader() + + + for i in 'XYZ': + #Making sure all power supplies are off. + self.psu.set_output('X', 0) + self.psu.set_output('Y', 0) + self.psu.set_output('Z', 0) + + self.psu.set_output(i, 1) + + if i == 'X': + self.arduino.set_negative_X() + + elif i == 'Y': + self.arduino.set_negative_Y() + + elif i == 'Z': + self.arduino.set_negative_Z() + + + for current_val in range(max_current, min_current - step, step): + current_val = self.psu.set_current_limit(self, current_val) + mag_x, mag_y, mag_z = self.arduino.get_magnetometer_reading() + csv_writer.writerow(current_val, mag_x, mag_y, mag_z) + + if i == 'X': + self.arduino.set_positive_X() + + elif i == 'Y': + self.arduino.set_positive_Y() + + elif i == 'Z': + self.arduino.set_positive_Z() + + for current_val in range(min_current, max_current - step, step): + current_val = self.psu.set_current_limit(self, current_val) + mag_x, mag_y, mag_z = self.arduino.get_magnetometer_reading() + csv_writer.writerow(current_val, mag_x, mag_y, mag_z) + + + #Closes program and exits. def do_exit(self, arg): diff --git a/oresat_helmholtz/sweepdata.csv b/oresat_helmholtz/sweepdata.csv new file mode 100644 index 0000000..4771db1 --- /dev/null +++ b/oresat_helmholtz/sweepdata.csv @@ -0,0 +1,74 @@ +"X (Negative Polarity)", "Timestamp", "Current", "Mag. field reading", +"3:34", "0.998", "54.81, 74.26, 3.79", +"3:25", "0.898", "54.60, 73.04, 3.09", +"3:26", "0.797", "54.81, 74.35, 3.94", +"3:26", "0.698", "54.82, 76.71, 3.46", +"3:27", "0.548", "54.91, 76.72, 3.89", +"3:28", "0.498", "54.59, 76.59, 3.51", +"3:29", "0.395", "54.72, 76.33, 3.38", +"3:30", "0.297", "54.62, 76.33, 3.20", +"3:31", "0.195", "54.83, 76.87, 4.84", +"3:31", "0.097", "54.89, 82.61, 4.37", +"3:32", "0", "53.68, 62.27, 2.04" + +"X (Positive Polarity)", "Timestamp", "Current", "Mag. field reading", +"3:35", "0.108", "51.86, -13.11, 13.53", +"3:35", "0.198", "55.23, 11.41, 7.70", +"3:36", "0.297", "53.36, 52.19, -9.69", +"3:37", "0.396", "54.03, 66.41, -9.48", +"3:38", "0.497", "54.81, 65.91, -9.11", +"3:38", "0.598", "54.86, 89.66, 9.21", +"3:39", "0.698", "54.59, 75.43, 3.14", +"3:40", "0.795", "55.09, 86.28, 4.76", +"3:41", "0.898", "55.71, 98.53, 5.67", +"3:41", "0.998", "56.40, 111.25, 7.10" + +"Y (Negative Polarity)", "Timestamp", "Current", "Mag. field reading", +"3:45", "1.027", "148.87, -29.44, -21.58", +"3:46", "0.898", "148.41, -29.36, -21.43", +"3:47", "0.799", "148.07, -28.80, -20.94", +"3:48", "0.689", "147.93, -29.31, -21.05", +"3:49", "0.597", "147.11, -29.27, -20.95", +"3:50", "0.497", "151.49, -29.54, -21.74", +"3:51", "0.398", "151.09, -29.53, -21.76", +"3:52", "0.298", "151.06, -29.42, -21.79", +"3:53", "0.198", "150.31, -29.05, -21.87", +"3:53", "0.096", "150.56, -29.42, -21.76", +"3:54", "0", "130.57, -28.43, -18.54" + +"Y (Positive Polarity)", "Timestamp", "Current", "Mag. field reading", +"3:54", "0.096", "155.49, -29.62, -21.97", +"3:54", "1.98", "123.74, -28.29, -19.12", +"3:55", "0.297", "157.31, -30.83, -21.05", +"3:55", "0.398", "130.78, -28.05, -20.03", +"3:56", "0.498", "163.14, -30.59, -23.46", +"3:57", "0.597", "160.53, -29.94, -20.89", +"3:57", "0.695", "147.14, -29.27, -21.31", +"3:58", "0.800", "158.17, -29.90, -23.06", +"3:58", "0.898", "170.18, -30.61, -25.17", +"3:59", "0.997", "182.67, -31.20, -26.41" + +"Z (Negative Polarity)", "Timestamp", "Current", "Mag. field reading", +"1:13", "0.99", "38.17, -11.59, -107.21" +"1:15", "0.897", "38.06, -11.79, -105.95", +"1:15", "0.796", "37.89, -11.56, -106.49", +"1:16", "0.697", "38.14, -11.95, -105.84", +"1:17", "0.595", "37.74, -11.16, -109.19", +"1:17", "0.496", "37.66, -11.19, -109.24", +"1:18", "0.395", "37.61, -11.22, -110.29", +"1:19", "0.294", "37.51, -10.69, -110.07", +"1:20", "0.195", "37.87, -11.14, -111.26", +"1:20", "0.095", "37.84, -11.66, -108.08", +"1:21", "0", "40.83, -13.81, -87.66" + +"Z (Positive Polarity)", "Timestamp", "Current", "Mag. field reading", +"1:23", "0.095", "37.06, -10.61, -113.24", +"1:24", "0.196", "45.82, -8.93, -82.62", +"1:25", "0.295", "43.09, -7.84, -90.84", +"1:25", "0.392", "40.64, -5.04, -112.74", +"1:25", "0.497", "36.46, -13.24, -118.44", +"1:26", "0.597", "38.53, -3.03, -110.27", +"1:27", "0.696", "38.21, -11.57, -104.99", +"1:28", "0.795", "36.65, -10.57, -116.09", +"1:28", "0.894", "34.74, -8.92, -128.04", +"1:29", "0.999", "33.30, -7.34, -140.35" From 2a16acf8b95b62ea8fb4a33016268b24f78b6c5a Mon Sep 17 00:00:00 2001 From: Gustavo Date: Thu, 14 Sep 2023 12:41:31 -0700 Subject: [PATCH 31/43] Added Calibration Function. Can write to a .CSV and sweep test all axis. --- oresat_helmholtz/__main__.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index b9cc9ab..665d1d2 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -288,10 +288,13 @@ def help_magnetometer_temp(self): #Calibration function prototype def do_calibration(self): if not self.mock: + + #Current values. max_current = 1000 min_current = 0 step = -100 + #Opening and declaring headers for the CSV file. with open("cage_cal.csv", "w") as new_file: fieldnames = ['Current (A)', 'Magnetic Field X (T)', 'Magnetic Field Y (T)', 'Magnetic Field Z (T)'] csv_writer= csv.DictWriter(new_file, fieldsnames = fieldnames, delimiter='\t') @@ -299,13 +302,14 @@ def do_calibration(self): for i in 'XYZ': - #Making sure all power supplies are off. + #Making sure all power supplies are off by default. self.psu.set_output('X', 0) self.psu.set_output('Y', 0) self.psu.set_output('Z', 0) self.psu.set_output(i, 1) + #Setting X, Y and Z bridges to negative polarity. if i == 'X': self.arduino.set_negative_X() @@ -315,12 +319,13 @@ def do_calibration(self): elif i == 'Z': self.arduino.set_negative_Z() - + #Iterating starting at -1 amps to 0 amps. for current_val in range(max_current, min_current - step, step): current_val = self.psu.set_current_limit(self, current_val) mag_x, mag_y, mag_z = self.arduino.get_magnetometer_reading() csv_writer.writerow(current_val, mag_x, mag_y, mag_z) + #Setting X, Y and Z bridges to positive polarity. if i == 'X': self.arduino.set_positive_X() @@ -330,10 +335,14 @@ def do_calibration(self): elif i == 'Z': self.arduino.set_positive_Z() + #Iterating starting at 0 amps to 1 amps. for current_val in range(min_current, max_current - step, step): current_val = self.psu.set_current_limit(self, current_val) mag_x, mag_y, mag_z = self.arduino.get_magnetometer_reading() csv_writer.writerow(current_val, mag_x, mag_y, mag_z) + + #Next steps: sci pi on the .csv and find line of best fit (linear) between magnitude of Mag. Field and Current + # @@ -349,6 +358,7 @@ def do_exit(self, arg): def help_exit(self): print("Type in exit to close the program ") +#Main program. Objects declared here. Shell built. def main(): parser = ArgumentParser() parser.add_argument('-l', '--arduino-location', help='Location to Arduino. ') From e3a30e644f372dfd23d816a7161d77fd3067dbf5 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Thu, 14 Sep 2023 12:44:06 -0700 Subject: [PATCH 32/43] Added Calibration function help message. WIP --- oresat_helmholtz/__main__.py | 6 ++- oresat_helmholtz/sweepdata.csv | 74 ---------------------------------- 2 files changed, 4 insertions(+), 76 deletions(-) delete mode 100644 oresat_helmholtz/sweepdata.csv diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index 665d1d2..6d31ef9 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -343,8 +343,10 @@ def do_calibration(self): #Next steps: sci pi on the .csv and find line of best fit (linear) between magnitude of Mag. Field and Current # - - + + #Calibration function help message. + def help_calibration(self): + print("Testing help message for the calibration function. This is a WIP.") #Closes program and exits. diff --git a/oresat_helmholtz/sweepdata.csv b/oresat_helmholtz/sweepdata.csv deleted file mode 100644 index 4771db1..0000000 --- a/oresat_helmholtz/sweepdata.csv +++ /dev/null @@ -1,74 +0,0 @@ -"X (Negative Polarity)", "Timestamp", "Current", "Mag. field reading", -"3:34", "0.998", "54.81, 74.26, 3.79", -"3:25", "0.898", "54.60, 73.04, 3.09", -"3:26", "0.797", "54.81, 74.35, 3.94", -"3:26", "0.698", "54.82, 76.71, 3.46", -"3:27", "0.548", "54.91, 76.72, 3.89", -"3:28", "0.498", "54.59, 76.59, 3.51", -"3:29", "0.395", "54.72, 76.33, 3.38", -"3:30", "0.297", "54.62, 76.33, 3.20", -"3:31", "0.195", "54.83, 76.87, 4.84", -"3:31", "0.097", "54.89, 82.61, 4.37", -"3:32", "0", "53.68, 62.27, 2.04" - -"X (Positive Polarity)", "Timestamp", "Current", "Mag. field reading", -"3:35", "0.108", "51.86, -13.11, 13.53", -"3:35", "0.198", "55.23, 11.41, 7.70", -"3:36", "0.297", "53.36, 52.19, -9.69", -"3:37", "0.396", "54.03, 66.41, -9.48", -"3:38", "0.497", "54.81, 65.91, -9.11", -"3:38", "0.598", "54.86, 89.66, 9.21", -"3:39", "0.698", "54.59, 75.43, 3.14", -"3:40", "0.795", "55.09, 86.28, 4.76", -"3:41", "0.898", "55.71, 98.53, 5.67", -"3:41", "0.998", "56.40, 111.25, 7.10" - -"Y (Negative Polarity)", "Timestamp", "Current", "Mag. field reading", -"3:45", "1.027", "148.87, -29.44, -21.58", -"3:46", "0.898", "148.41, -29.36, -21.43", -"3:47", "0.799", "148.07, -28.80, -20.94", -"3:48", "0.689", "147.93, -29.31, -21.05", -"3:49", "0.597", "147.11, -29.27, -20.95", -"3:50", "0.497", "151.49, -29.54, -21.74", -"3:51", "0.398", "151.09, -29.53, -21.76", -"3:52", "0.298", "151.06, -29.42, -21.79", -"3:53", "0.198", "150.31, -29.05, -21.87", -"3:53", "0.096", "150.56, -29.42, -21.76", -"3:54", "0", "130.57, -28.43, -18.54" - -"Y (Positive Polarity)", "Timestamp", "Current", "Mag. field reading", -"3:54", "0.096", "155.49, -29.62, -21.97", -"3:54", "1.98", "123.74, -28.29, -19.12", -"3:55", "0.297", "157.31, -30.83, -21.05", -"3:55", "0.398", "130.78, -28.05, -20.03", -"3:56", "0.498", "163.14, -30.59, -23.46", -"3:57", "0.597", "160.53, -29.94, -20.89", -"3:57", "0.695", "147.14, -29.27, -21.31", -"3:58", "0.800", "158.17, -29.90, -23.06", -"3:58", "0.898", "170.18, -30.61, -25.17", -"3:59", "0.997", "182.67, -31.20, -26.41" - -"Z (Negative Polarity)", "Timestamp", "Current", "Mag. field reading", -"1:13", "0.99", "38.17, -11.59, -107.21" -"1:15", "0.897", "38.06, -11.79, -105.95", -"1:15", "0.796", "37.89, -11.56, -106.49", -"1:16", "0.697", "38.14, -11.95, -105.84", -"1:17", "0.595", "37.74, -11.16, -109.19", -"1:17", "0.496", "37.66, -11.19, -109.24", -"1:18", "0.395", "37.61, -11.22, -110.29", -"1:19", "0.294", "37.51, -10.69, -110.07", -"1:20", "0.195", "37.87, -11.14, -111.26", -"1:20", "0.095", "37.84, -11.66, -108.08", -"1:21", "0", "40.83, -13.81, -87.66" - -"Z (Positive Polarity)", "Timestamp", "Current", "Mag. field reading", -"1:23", "0.095", "37.06, -10.61, -113.24", -"1:24", "0.196", "45.82, -8.93, -82.62", -"1:25", "0.295", "43.09, -7.84, -90.84", -"1:25", "0.392", "40.64, -5.04, -112.74", -"1:25", "0.497", "36.46, -13.24, -118.44", -"1:26", "0.597", "38.53, -3.03, -110.27", -"1:27", "0.696", "38.21, -11.57, -104.99", -"1:28", "0.795", "36.65, -10.57, -116.09", -"1:28", "0.894", "34.74, -8.92, -128.04", -"1:29", "0.999", "33.30, -7.34, -140.35" From e8f750faee444e1f9ad1b6ccdf539bd263901b82 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Thu, 14 Sep 2023 12:49:17 -0700 Subject: [PATCH 33/43] Fixed calibration parameters --- oresat_helmholtz/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index 6d31ef9..ab23e01 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -286,7 +286,7 @@ def help_magnetometer_temp(self): print("Accepted values are: 't'. ") #Calibration function prototype - def do_calibration(self): + def do_calibration(self, arg): if not self.mock: #Current values. From 1190d6cb3e8127fafbaf4ad34073ccb7b974058c Mon Sep 17 00:00:00 2001 From: Gustavo Date: Thu, 14 Sep 2023 12:57:46 -0700 Subject: [PATCH 34/43] Fixed calibration parameters --- oresat_helmholtz/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index ab23e01..6d31ef9 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -286,7 +286,7 @@ def help_magnetometer_temp(self): print("Accepted values are: 't'. ") #Calibration function prototype - def do_calibration(self, arg): + def do_calibration(self): if not self.mock: #Current values. From d06f2155dda4cde8428e305bf3f42eef5fcb98dd Mon Sep 17 00:00:00 2001 From: Gustavo Date: Thu, 14 Sep 2023 13:30:38 -0700 Subject: [PATCH 35/43] Fixed calibration parameters --- oresat_helmholtz/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index 6d31ef9..ab23e01 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -286,7 +286,7 @@ def help_magnetometer_temp(self): print("Accepted values are: 't'. ") #Calibration function prototype - def do_calibration(self): + def do_calibration(self, arg): if not self.mock: #Current values. From f6959f41c4865e887f198df220a4ef7c1d682c30 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Thu, 14 Sep 2023 13:34:16 -0700 Subject: [PATCH 36/43] Fixed calibration parameters --- oresat_helmholtz/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index ab23e01..6d31ef9 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -286,7 +286,7 @@ def help_magnetometer_temp(self): print("Accepted values are: 't'. ") #Calibration function prototype - def do_calibration(self, arg): + def do_calibration(self): if not self.mock: #Current values. From c6d07b046639870d8df13b9d117ac115f8548385 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Thu, 14 Sep 2023 13:41:58 -0700 Subject: [PATCH 37/43] Fixed calibration parameters --- oresat_helmholtz/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index 6d31ef9..ab23e01 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -286,7 +286,7 @@ def help_magnetometer_temp(self): print("Accepted values are: 't'. ") #Calibration function prototype - def do_calibration(self): + def do_calibration(self, arg): if not self.mock: #Current values. From 1cea8a8441877e149570578b52d77250025a3fea Mon Sep 17 00:00:00 2001 From: Gustavo Date: Thu, 14 Sep 2023 13:43:01 -0700 Subject: [PATCH 38/43] Fixed typo --- oresat_helmholtz/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index ab23e01..c2921ac 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -297,7 +297,7 @@ def do_calibration(self, arg): #Opening and declaring headers for the CSV file. with open("cage_cal.csv", "w") as new_file: fieldnames = ['Current (A)', 'Magnetic Field X (T)', 'Magnetic Field Y (T)', 'Magnetic Field Z (T)'] - csv_writer= csv.DictWriter(new_file, fieldsnames = fieldnames, delimiter='\t') + csv_writer= csv.DictWriter(new_file, fieldnames = fieldnames, delimiter='\t') csv_writer.writeheader() From 8216b6c9b3be870dd3fd9d691033c90281fc5102 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Thu, 14 Sep 2023 13:48:57 -0700 Subject: [PATCH 39/43] Added missing variable in for loop --- oresat_helmholtz/__main__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index c2921ac..479a849 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -321,7 +321,7 @@ def do_calibration(self, arg): #Iterating starting at -1 amps to 0 amps. for current_val in range(max_current, min_current - step, step): - current_val = self.psu.set_current_limit(self, current_val) + current_val = self.psu.set_current_limit(self, i, current_val) mag_x, mag_y, mag_z = self.arduino.get_magnetometer_reading() csv_writer.writerow(current_val, mag_x, mag_y, mag_z) @@ -337,7 +337,7 @@ def do_calibration(self, arg): #Iterating starting at 0 amps to 1 amps. for current_val in range(min_current, max_current - step, step): - current_val = self.psu.set_current_limit(self, current_val) + current_val = self.psu.set_current_limit(self, i, current_val) mag_x, mag_y, mag_z = self.arduino.get_magnetometer_reading() csv_writer.writerow(current_val, mag_x, mag_y, mag_z) From 7b6aeca9e6b4de972a697bf2c01c3d8f460c6ba4 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Thu, 14 Sep 2023 13:51:04 -0700 Subject: [PATCH 40/43] Fixed typo --- oresat_helmholtz/__main__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index 479a849..f28b8e2 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -321,7 +321,7 @@ def do_calibration(self, arg): #Iterating starting at -1 amps to 0 amps. for current_val in range(max_current, min_current - step, step): - current_val = self.psu.set_current_limit(self, i, current_val) + current_val = self.psu.set_current_limit(i, current_val) mag_x, mag_y, mag_z = self.arduino.get_magnetometer_reading() csv_writer.writerow(current_val, mag_x, mag_y, mag_z) @@ -337,7 +337,7 @@ def do_calibration(self, arg): #Iterating starting at 0 amps to 1 amps. for current_val in range(min_current, max_current - step, step): - current_val = self.psu.set_current_limit(self, i, current_val) + current_val = self.psu.set_current_limit(i, current_val) mag_x, mag_y, mag_z = self.arduino.get_magnetometer_reading() csv_writer.writerow(current_val, mag_x, mag_y, mag_z) From 9bacb0cc6c12dc010a1bb4509751f7f7d648a226 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Thu, 14 Sep 2023 13:57:32 -0700 Subject: [PATCH 41/43] Fixed for loop issues --- oresat_helmholtz/__main__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index f28b8e2..682df6a 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -322,7 +322,7 @@ def do_calibration(self, arg): #Iterating starting at -1 amps to 0 amps. for current_val in range(max_current, min_current - step, step): current_val = self.psu.set_current_limit(i, current_val) - mag_x, mag_y, mag_z = self.arduino.get_magnetometer_reading() + mag_x, mag_y, mag_z = self.arduino.get_magnetometer_reading().split(",") csv_writer.writerow(current_val, mag_x, mag_y, mag_z) #Setting X, Y and Z bridges to positive polarity. @@ -338,7 +338,7 @@ def do_calibration(self, arg): #Iterating starting at 0 amps to 1 amps. for current_val in range(min_current, max_current - step, step): current_val = self.psu.set_current_limit(i, current_val) - mag_x, mag_y, mag_z = self.arduino.get_magnetometer_reading() + mag_x, mag_y, mag_z = self.arduino.get_magnetometer_reading().split(",") csv_writer.writerow(current_val, mag_x, mag_y, mag_z) #Next steps: sci pi on the .csv and find line of best fit (linear) between magnitude of Mag. Field and Current From f999cccf48aef164e06e7d708df645a77ed6a923 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Thu, 14 Sep 2023 14:03:31 -0700 Subject: [PATCH 42/43] Fixed for loop issues --- oresat_helmholtz/__main__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index 682df6a..1f59a37 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -323,7 +323,8 @@ def do_calibration(self, arg): for current_val in range(max_current, min_current - step, step): current_val = self.psu.set_current_limit(i, current_val) mag_x, mag_y, mag_z = self.arduino.get_magnetometer_reading().split(",") - csv_writer.writerow(current_val, mag_x, mag_y, mag_z) + dict_to_write = {'Current (A)': current_val, 'Magnetic Field X (T)': mag_x, 'Magnetic Field Y (T)':mag_y,'Magnetic Field Z (T)':mag_z} + csv_writer.writerow(dict_to_write) #Setting X, Y and Z bridges to positive polarity. if i == 'X': From dd331b89ff7a5afedd0732622aed0e461f342c49 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Thu, 14 Sep 2023 15:19:49 -0700 Subject: [PATCH 43/43] Fixed an issue where currents were not recorded --- oresat_helmholtz/__main__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/oresat_helmholtz/__main__.py b/oresat_helmholtz/__main__.py index 1f59a37..ced31cb 100644 --- a/oresat_helmholtz/__main__.py +++ b/oresat_helmholtz/__main__.py @@ -321,7 +321,8 @@ def do_calibration(self, arg): #Iterating starting at -1 amps to 0 amps. for current_val in range(max_current, min_current - step, step): - current_val = self.psu.set_current_limit(i, current_val) + self.psu.set_current_limit(i, current_val) + current_val = self.psu.return_current(i) mag_x, mag_y, mag_z = self.arduino.get_magnetometer_reading().split(",") dict_to_write = {'Current (A)': current_val, 'Magnetic Field X (T)': mag_x, 'Magnetic Field Y (T)':mag_y,'Magnetic Field Z (T)':mag_z} csv_writer.writerow(dict_to_write)