import time
import matplotlib.pyplot as plt
from .libphox import Labphox
import numpy as np
import json
import os
[docs]
class Cryoswitch:
def __init__(self, debug=False, COM_port='', IP=None, SN=None, override_abspath=False):
self.debug = debug
self.port = COM_port
self.IP = IP
self.verbose = True
self.labphox = Labphox(self.port, debug=self.debug, IP=self.IP, SN=SN)
self.ports_enabled = self.labphox.N_channel
self.SN = self.labphox.board_SN
self.HW_rev = self.get_HW_revision()
self.HW_rev_N = int(self.get_HW_revision()[-1])
self.wait_time = 0.5
self.pulse_duration_ms = 15
self.converter_voltage = 5
self.MEASURED_converter_voltage = 0
self.current_switch_model = ''
self.tolerance = 0.15
if override_abspath:
self.abs_path = override_abspath + '\\'
else:
self.abs_path = os.path.dirname(__file__) + '\\'
self.decimals = 2
self.plot = False
self.log_wav = True
self.log_wav_dir = self.abs_path + r'data'
self.align_edges = True
self.plot_polarization = True
self.pulse_logging = True
self.pulse_logging_filename = self.abs_path + r'pulse_logging.txt'
self.log_pulses_to_display = 5
self.warning_threshold_current = 60
self.track_states = True
self.track_states_file = self.abs_path + r'states.json'
self.constants_file_name = self.abs_path + r'constants.json'
self.__constants()
if self.track_states:
self.tracking_init()
if self.pulse_logging:
self.pulse_logging_init()
if self.log_wav:
self.log_wav_init()
[docs]
def tracking_init(self):
if not os.path.isfile(self.track_states_file):
with open(self.track_states_file, 'w') as fp:
json.dump(STATES_DEFAULT, fp, indent=4)
file = open(self.track_states_file)
states = json.load(file)
file.close()
if self.SN not in states.keys():
states[self.SN] = states['SN']
with open(self.track_states_file, 'w') as outfile:
json.dump(states, outfile, indent=4, sort_keys=True)
[docs]
def pulse_logging_init(self):
if not os.path.isfile(self.pulse_logging_filename):
file = open(self.pulse_logging_filename, 'w')
file.close()
[docs]
def log_wav_init(self):
if not os.path.isdir(self.log_wav_dir):
os.mkdir(self.log_wav_dir)
def __constants(self):
if not os.path.isfile(self.constants_file_name):
with open(self.constants_file_name, 'w') as fp:
json.dump(CONSTANTS, fp, indent=4)
file = open(self.constants_file_name)
constants = json.load(file)
file.close()
if self.HW_rev in constants.keys():
constants = constants[self.HW_rev]
self.ADC_12B_res = constants['ADC_12B_res']
self.ADC_8B_res = constants['ADC_8B_res']
self.ADC_cal_ref = constants['ADC_cal_ref']
self.bv_R1 = constants['bv_R1']
self.bv_R2 = constants['bv_R2']
self.bv_ADC = constants['bv_ADC']
self.converter_divider = constants['converter_divider']
self.converter_ADC = constants['converter_ADC']
self.converter_VREF = constants['converter_VREF']
self.converter_R1 = constants['converter_R1']
self.converter_R2 = constants['converter_R2']
self.converter_Rf = constants['converter_Rf']
self.converter_DAC_lower_bound = constants['converter_DAC_lower_bound']
self.converter_DAC_upper_bound = constants['converter_DAC_upper_bound']
self.converter_correction_codes = constants['converter_correction_codes']
self.converter_output_voltage_range = constants['converter_output_voltage_range']
self.OCP_gain = constants['OCP_gain']
self.OCP_range = constants['OCP_range']
self.pulse_duration_range = constants['pulse_duration_range']
self.sampling_frequency_range = constants['sampling_frequency_range']
self.current_sense_R = constants['current_sense_R']
self.current_gain = constants['current_gain']
self.polarization_params = constants['polarization_params']
self.sampling_freq = 28000
if constants['calibrate_ADC']:
self.labphox.ADC3_cmd('start')
time.sleep(0.1)
ref_values = []
for it in range(5):
ref_values.append(self.get_V_ref())
measured_ref = sum(ref_values) / len(ref_values)
if 3.1 < measured_ref < 3.5:
self.measured_adc_ref = measured_ref
else:
print(f'Measured ADC ref {measured_ref}V outside of range')
self.measured_adc_ref = self.labphox.adc_ref
else:
self.measured_adc_ref = self.labphox.adc_ref
else:
print(f'Failed to load constants, HW revision {self.HW_rev} not int {constants.keys()}')
[docs]
def set_FW_upgrade_mode(self):
self.labphox.reset_cmd('boot')
[docs]
def get_UIDs(self):
UID0 = int(self.labphox.utility_cmd('UID', 0))
UID1 = int(self.labphox.utility_cmd('UID', 1))
UID2 = int(self.labphox.utility_cmd('UID', 2))
return [UID0, UID1, UID2]
[docs]
def flash(self, path=None):
reply = input('Are you sure you want to flash the device?')
if 'Y' in reply.upper():
self.set_FW_upgrade_mode()
time.sleep(5)
self.labphox.FLASH_utils(path)
else:
print('Aborting flash sequence...')
[docs]
def reset(self):
self.labphox.reset_cmd('reset')
time.sleep(3)
[docs]
def reconnect(self):
self.labphox.connect()
[docs]
def enable_5V(self):
self.labphox.gpio_cmd('EN_5V', 1)
[docs]
def disable_5V(self):
self.labphox.gpio_cmd('EN_5V', 0)
[docs]
def enable_3V3(self):
self.labphox.gpio_cmd('EN_3V3', 1)
[docs]
def disable_3V3(self):
self.labphox.gpio_cmd('EN_3V3', 0)
[docs]
def standby(self):
self.set_output_voltage(5)
self.disable_converter()
self.disable_negative_supply()
self.disable_3V3()
self.disable_5V()
[docs]
def calculate_error(self, measured, set):
error = abs((measured - set) / set)
return error
[docs]
def measure_ADC(self, channel):
self.labphox.ADC_cmd('select', channel)
time.sleep(self.wait_time)
return self.labphox.ADC_cmd('get')
[docs]
def get_converter_voltage(self):
converter_gain = self.measured_adc_ref * self.converter_divider / self.ADC_12B_res
code = self.measure_ADC(self.converter_ADC)
converter_voltage = round(code * converter_gain, self.decimals)
self.MEASURED_converter_voltage = converter_voltage
return converter_voltage
[docs]
def get_bias_voltage(self):
bias_gain = self.measured_adc_ref * ((self.bv_R2 + self.bv_R1) / self.bv_R1) / self.ADC_12B_res
bias_offset = self.measured_adc_ref*self.bv_R2/self.bv_R1
code = self.measure_ADC(self.bv_ADC)
bias_voltage = code * bias_gain-bias_offset
return round(bias_voltage, self.decimals)
[docs]
def check_voltage(self, measured_voltage, target_voltage, tolerance=0.1, pre_str=''):
error = self.calculate_error(measured_voltage, target_voltage)
if error > tolerance:
print(f'{pre_str} Failed to set voltage: {target_voltage} , measured voltage: {round(measured_voltage, self.decimals)}V')
# print(pre_str, 'failed to set voltage , measured voltage', round(measured_voltage, self.decimals))
return False
else:
# print(pre_str, 'voltage set to', round(measured_voltage, self.decimals), 'V')
print(f'{pre_str} Voltage set to {round(measured_voltage, self.decimals)}V')
return True
[docs]
def get_HW_revision(self):
return self.labphox.HW
[docs]
def get_internal_temperature(self):
code = self.measure_ADC(16)
VSENSE = self.measured_adc_ref * code / self.ADC_12B_res
V25 = 0.76
Avg_Slope = 0.0025
temp = ((VSENSE - V25) / Avg_Slope) + 25
return temp
[docs]
def get_V_ref(self):
if self.ADC_cal_ref:
self.labphox.ADC3_cmd('select', 8)
time.sleep(self.wait_time)
code = self.labphox.ADC3_cmd('get')
Ref_2V5_code = code
ADC_ref = 2.5 * self.ADC_12B_res / Ref_2V5_code
return round(ADC_ref, 4)
else:
print('Calibration reference is not available in this HW rev')
return None
[docs]
def enable_negative_supply(self):
self.labphox.gpio_cmd('EN_CHGP', 1)
time.sleep(1)
bias_voltage = self.get_bias_voltage()
if self.verbose:
self.check_voltage(bias_voltage, -5, tolerance=self.tolerance, pre_str='BIAS STATUS:')
return bias_voltage
[docs]
def disable_negative_supply(self):
self.labphox.gpio_cmd('EN_CHGP', 0)
return self.get_bias_voltage()
[docs]
def calculate_output_code(self, Vout):
code = ((self.converter_VREF - (
Vout - self.converter_VREF * (1 + (self.converter_R1 / self.converter_R2))) * (
self.converter_Rf / self.converter_R1)) * (self.ADC_12B_res / self.measured_adc_ref))
code = int((code / self.converter_correction_codes[0]) - self.converter_correction_codes[1])
if code < self.converter_DAC_lower_bound or code > self.converter_DAC_upper_bound:
print('Wrong DAC value, dont mess with the DAC. DAC angry.')
return False
return code
[docs]
def set_output_voltage(self, Vout):
if self.converter_output_voltage_range[0] <= Vout <= self.converter_output_voltage_range[1]:
if Vout > 10:
self.disable_negative_supply()
else:
self.enable_negative_supply()
self.labphox.DAC_cmd('on', DAC=1)
code = self.calculate_output_code(Vout)
if code:
self.labphox.DAC_cmd('set', DAC=1, value=code)
# if Vout < self.converter_voltage:
# self.discharge()
time.sleep(2)
self.converter_voltage = Vout
measured_voltage = self.get_converter_voltage()
if self.verbose:
self.check_voltage(measured_voltage, Vout, tolerance=self.tolerance, pre_str='CONVERTER STATUS:')
return measured_voltage
else:
print(f'Failed to calculate output code')
return False
else:
print('Voltage outside of range (5-30V)')
return False
[docs]
def enable_output_channels(self):
enabled = False
counter = 0
response = {}
while not enabled:
response = self.labphox.IO_expander_cmd('on')
if int(response['value']) == 0:
enabled = True
elif counter > 3:
break
counter += 1
if not int(response['value']) == 0:
print('Failed to enable output channels!', str(response['value']))
elif self.verbose and counter > 1:
print(counter, 'attempts to enable output channel')
return int(response['value'])
[docs]
def disable_output_channels(self):
self.labphox.IO_expander_cmd('off')
[docs]
def enable_converter(self, init_voltage=None):
code = self.calculate_output_code(5)
self.labphox.DAC_cmd('set', DAC=1, value=code)
self.labphox.DAC_cmd('on', DAC=1)
self.labphox.gpio_cmd('PWR_EN', 1)
self.labphox.gpio_cmd('DCDC_EN', 1)
if init_voltage is None:
init_voltage = self.converter_voltage
self.set_output_voltage(init_voltage)
[docs]
def disable_converter(self):
code = self.calculate_output_code(5)
self.labphox.DAC_cmd('set', DAC=1, value=code)
self.labphox.gpio_cmd('DCDC_EN', 0)
self.labphox.gpio_cmd('PWR_EN', 0)
[docs]
def enable_OCP(self):
code = self.calculate_OCP_code(50)
self.labphox.DAC_cmd('set', DAC=2, value=code)
self.labphox.DAC_cmd('on', DAC=2)
self.set_OCP_mA(100)
[docs]
def reset_OCP(self):
self.labphox.gpio_cmd('CHOPPING_EN', 1)
time.sleep(0.2)
self.labphox.gpio_cmd('CHOPPING_EN', 0)
[docs]
def calculate_OCP_code(self, OCP_value):
code = int(OCP_value*(self.current_sense_R*self.current_gain*self.ADC_12B_res/(self.OCP_gain*1000*self.measured_adc_ref)))
if 0 < code < 4095:
return code
else:
return None
[docs]
def set_OCP_mA(self, OCP_value):
if self.OCP_range[0] <= OCP_value <= self.OCP_range[1]:
DAC_reg = self.calculate_OCP_code(OCP_value)
if DAC_reg:
self.labphox.DAC_cmd('set', DAC=2, value=DAC_reg)
return OCP_value
print(f'Over current protection outside of range {self.OCP_range[0]}-{self.OCP_range[1]}mA')
return None
[docs]
def get_OCP_status(self):
return self.labphox.gpio_cmd('OCP_OUT_STATUS')
[docs]
def enable_chopping(self):
self.labphox.gpio_cmd('CHOPPING_EN', 1)
[docs]
def disable_chopping(self):
self.labphox.gpio_cmd('CHOPPING_EN', 0)
[docs]
def reset_output_supervisor(self):
self.disable_converter()
self.labphox.gpio_cmd('FORCE_PWR_EN', 1)
time.sleep(0.5)
self.labphox.gpio_cmd('FORCE_PWR_EN', 0)
self.enable_converter()
[docs]
def get_output_state(self):
return self.labphox.gpio_cmd('PWR_STATUS')
[docs]
def set_pulse_duration_ms(self, ms_duration):
if self.pulse_duration_range[0] <= ms_duration <= self.pulse_duration_range[1]:
self.pulse_duration_ms = ms_duration
pulse_offset = 100
self.labphox.timer_cmd('duration', round(ms_duration * 100 + pulse_offset))
if self.verbose:
print(f'Pulse duration set to {ms_duration} ms')
else:
print(f'Pulse duration outside of range ({self.pulse_duration_range[0]}-{self.pulse_duration_range[1]}ms)')
[docs]
def set_sampling_frequency_khz(self, f_khz):
if self.sampling_frequency_range[0] <= f_khz <= self.sampling_frequency_range[1]:
self.labphox.timer_cmd('sampling', int(84000/f_khz))
self.sampling_freq = f_khz * 1000
else:
print(f'Sampling frequency outside of range ({self.sampling_frequency_range[0]}-{self.sampling_frequency_range[1]}khz)')
[docs]
def calculate_polarization_current_mA(self, voltage=None, resistance=None):
if not voltage:
voltage = self.MEASURED_converter_voltage
if self.converter_voltage <= 10:
th_current = (voltage - 2.2) / self.polarization_params[0] + (voltage - 0.2 + 5) / self.polarization_params[1] + (voltage - 3) / self.polarization_params[2]
elif self.converter_voltage < 15:
th_current = (voltage - 2.2) / self.polarization_params[0] + (voltage - 0.2) / self.polarization_params[1] + (voltage - 3) / self.polarization_params[2]
else:
th_current = (voltage - 2.2) / self.polarization_params[0] + (voltage - 10) / self.polarization_params[1] + (voltage - 3) / self.polarization_params[2]
if resistance:
th_current += voltage / resistance
return round(th_current * 1000, 1)
[docs]
def send_pulse(self):
if not self.get_power_status():
print('WARNING: Timing protection triggered, resetting...')
self.reset_output_supervisor()
current_gain = 1000 * self.measured_adc_ref / (self.current_sense_R * self.current_gain * self.ADC_8B_res)
current_data = self.labphox.application_cmd('pulse', 1)
return current_data*current_gain
[docs]
def select_switch_model(self, model='R583423141'):
if model.upper() == 'R583423141'.upper():
self.current_switch_model = 'R583423141'
self.labphox.IO_expander_cmd('type', value=1)
return True
elif model.upper() == 'R573423600'.upper():
self.current_switch_model = 'R573423600'
self.labphox.IO_expander_cmd('type', value=2)
return True
else:
return False
[docs]
def validate_selected_channel(self, number, polarity, reply):
if polarity and self.current_switch_model == 'R583423141':
shift_byte = 0b0110
offset = 0
elif not polarity and self.current_switch_model == 'R583423141':
shift_byte = 0b1001
offset = 0
elif polarity and self.current_switch_model == 'R573423600':
shift_byte = 0b10
offset = 4096
elif not polarity and self.current_switch_model == 'R573423600':
shift_byte = 0b01
offset = 8192
else:
shift_byte = 0
offset = 0
validation_id = (shift_byte << 2 * number) + offset
validation_id1 = validation_id & 255
validation_id2 = validation_id >> 8
if int(reply['value']) != validation_id1|validation_id2:
print('Wrong channel validation ID')
print('Validation ID, Received', reply['value'], '->Expected', validation_id1 | validation_id2)
return False
else:
return True
[docs]
def select_output_channel(self, port, number, polarity):
if 0 < number < 7:
number = number - 1
if polarity:
reply = self.labphox.IO_expander_cmd('connect', port, number)
else:
reply = self.labphox.IO_expander_cmd('disconnect', port, number)
return self.validate_selected_channel(number, polarity, reply)
else:
print('Contact out of range')
return None
[docs]
def plotting_function(self, current_profile, port, contact, polarity):
if polarity:
polarity_str = 'Connect'
else:
polarity_str = 'Disconnect'
if self.align_edges:
edge = np.argmax(current_profile > 0)
current_data = current_profile[edge:]
else:
current_data = current_profile
data_points = len(current_data)
sampling_period = 1 / self.sampling_freq
x_axis = np.linspace(0, data_points * sampling_period, data_points) * 1000
plt.plot(x_axis, current_data)
if self.plot_polarization:
polarization_current = self.calculate_polarization_current_mA()
plt.hlines(polarization_current, x_axis[0], x_axis[-1], colors='red',
linestyles='dashed')
# plt.text(x_axis[-1], polarization_current, 'Pol current')
plt.xlabel('Time [ms]')
plt.ylabel('Current [mA]')
plt.title(time.strftime("%b-%m %H:%M:%S%p", time.gmtime()))
plt.suptitle('Port ' + port + '-' + str(contact) + ' ' + polarity_str)
plt.xlim(x_axis[0], x_axis[-1])
if self.current_switch_model == 'R583423141':
plt.ylim(0, 100)
elif self.current_switch_model == 'R573423600':
plt.ylim(0, 200)
plt.grid()
plt.show()
[docs]
def select_and_pulse(self, port, contact, polarity):
if polarity:
polarity = 1
else:
polarity = 0
selection_result = self.select_output_channel(port, contact, polarity)
if selection_result:
current_profile = self.send_pulse()
self.disable_output_channels()
if self.plot:
self.plotting_function(current_profile=current_profile, port=port, contact=contact, polarity=polarity)
if self.track_states:
self.save_switch_state(port, contact, polarity)
if self.pulse_logging:
self.log_pulse(port, contact, polarity, current_profile.max())
if self.log_wav:
self.log_waveform(port, contact, polarity, current_profile)
return current_profile
else:
return []
[docs]
def save_switch_state(self, port, contact, polarity):
file = open(self.track_states_file)
states = json.load(file)
file.close()
SN = self.SN
port = 'port_' + str(port)
contact = 'contact_' + str(contact)
if SN in states.keys():
states[SN][port][contact] = polarity
with open(self.track_states_file, 'w') as outfile:
json.dump(states, outfile, indent=4, sort_keys=True)
[docs]
def get_switches_state(self, port=None):
file = open(self.track_states_file)
states = json.load(file)
file.close()
ports = []
if self.ports_enabled == 1:
ports = ['A']
elif self.ports_enabled == 2:
ports = ['A', 'B']
elif self.ports_enabled == 3:
ports = ['A', 'B', 'C']
elif self.ports_enabled == 4:
ports = ['A', 'B', 'C', 'D']
if self.SN in states.keys():
if port in ports:
current_state = states[self.SN]
print('Port ' + port + ' state')
for switch in range(1, 7):
state = current_state['port_' + port]['contact_' + str(switch)]
if state:
if switch == 1:
print(str(switch) + ' ----' + chr(0x2510))
else:
print(str(switch) + ' ----' + chr(0x2524))
else:
print(str(switch) + ' - -' + chr(0x2502))
print(' ' + chr(0x2514) + '- COM')
print('')
return states[self.SN]
else:
return None
[docs]
def log_pulse(self, port, contact, polarity, max_current):
if polarity:
direction = 'Connect '
else:
direction = 'Disconnect'
pulse_string = direction + '-> Port:' + port + '-' + str(contact) + ', CurrentMax:' + str(round(max_current)) + ' Timestamp:' + str(int(time.time()))
if max_current < self.warning_threshold_current:
warning_string = ' *Warnings: Low current detected!'
else:
warning_string = ''
with open(self.pulse_logging_filename, 'a') as logging_file:
logging_file.write(pulse_string + warning_string + '\n')
[docs]
def get_pulse_history(self, port=None, pulse_number=None):
if not pulse_number:
pulse_number = self.log_pulses_to_display
with open(self.pulse_logging_filename, 'r') as logging_file:
pulse_info = logging_file.readlines()
list_for_display = []
counter = 0
for idx, pulse in enumerate(pulse_info):
pulse = pulse_info[-idx-1]
if port:
if "Port:" + port + "-" in pulse:
list_for_display.append(pulse)
counter += 1
else:
list_for_display.append(pulse)
counter += 1
if counter >= pulse_number:
break
for idx, pulse in enumerate(list_for_display):
raw_data = list_for_display[-idx - 1].split(',')
if '*' in raw_data[-1]:
extra_text = raw_data[1].split('*')[-1].strip()
pulse_time = time.localtime(int(raw_data[1].split('*')[0].split(':')[-1].strip()))
else:
extra_text = ''
pulse_time = time.localtime(int(raw_data[1].split(':')[-1].strip()))
print(raw_data[0] + ', ' + time.strftime("%a %b-%m %H:%M:%S%p", pulse_time) + ' ' + extra_text)
[docs]
def connect(self, port, contact):
send_pulse = self.validate_port_contact(port, contact)
if send_pulse:
if self.debug:
print(f'Connecting Port:{port}, Contact {contact}')
current_profile = self.select_and_pulse(port, contact, 1)
return current_profile
else:
print(f'Port or contact out of range: Port {port}, Contact {contact}')
return None
[docs]
def disconnect(self, port, contact):
send_pulse = self.validate_port_contact(port, contact)
if send_pulse:
if self.debug:
print(f'Connecting Port:{port}, Contact {contact}')
current_profile = self.select_and_pulse(port, contact, 0)
return current_profile
else:
print(f'Port or contact out of range: Port {port}, Contact {contact}')
return None
[docs]
def disconnect_all(self, port):
for contact in range(1, 7):
self.disconnect(port, contact)
if self.plot:
plt.legend([1, 2, 3, 4, 5, 6])
[docs]
def smart_connect(self, port, contact, force=False):
states = self.get_switches_state()
port_state = states['port_' + port]
contacts = [1, 2, 3, 4, 5, 6]
contacts.remove(contact)
for other_contact in contacts:
if port_state['contact_' + str(other_contact)] == 1:
print('Disconnecting', other_contact)
self.disconnect(port, other_contact)
if port_state['contact_' + str(contact)] == 1:
print('Contact', contact, 'is already connected')
if force:
print('Connecting', contact)
return self.connect(port, contact)
else:
print('Connecting', contact)
return self.connect(port, contact)
return None
[docs]
def discharge(self):
if self.HW_rev_N >= 4:
self.labphox.application_cmd('test_circuit', 1)
test_current = self.send_pulse()
self.labphox.application_cmd('test_circuit', 0)
return test_current
else:
return None
[docs]
def test_internals(self, voltage=10):
if self.HW_rev_N >= 4:
last_voltage = self.converter_voltage
self.set_output_voltage(voltage)
voltage = self.MEASURED_converter_voltage
expected_current = ((voltage - 2.2) / 10000 + (voltage - 3) / 4700 + voltage / 480) * 1000
test_current = self.discharge()
if self.plot:
plt.plot(test_current)
plt.hlines(expected_current, 0, len(test_current), colors='red', linestyles='dashed')
plt.xlabel('Sample')
plt.ylabel('Current [mA]')
self.set_output_voltage(last_voltage)
return test_current
else:
print('Discharge is not possible in this HW revision')
return None
[docs]
def get_power_status(self):
return self.labphox.gpio_cmd('PWR_STATUS')
[docs]
def set_ip(self, add='192.168.1.101'):
self.labphox.ETHERNET_cmd('set_ip_str', add)
[docs]
def get_ip(self):
add = self.labphox.ETHERNET_cmd('get_ip_str')
print(f'IP: {add}')
return add
[docs]
def set_sub_net_mask(self, mask='255.255.255.0'):
self.labphox.ETHERNET_cmd('set_mask_str', mask)
[docs]
def get_sub_net_mask(self):
mask = self.labphox.ETHERNET_cmd('get_mask_str')
print(f'Subnet Mask: {mask}')
return mask
[docs]
def start(self):
if self.verbose:
print('Initialization...')
self.labphox.ADC_cmd('start')
self.enable_3V3()
self.enable_5V()
self.enable_OCP()
self.set_OCP_mA(80)
self.enable_chopping()
self.set_pulse_duration_ms(15)
self.enable_converter()
# self.set_output_voltage(5)
time.sleep(1)
self.enable_output_channels()
self.select_switch_model('R583423141')
if not self.get_power_status():
if self.verbose:
print('POWER STATUS: Output voltage not enabled')
else:
if self.verbose:
print('POWER STATUS: Ready')
if __name__ == "__main__":
switch = Cryoswitch(IP='192.168.1.101') ## -> CryoSwitch class declaration and USB connection
switch.start() ## -> Initialization of the internal hardware
switch.get_internal_temperature()
switch.get_pulse_history(pulse_number=5, port='A') ##-> Show the last 5 pulses send through on port A
switch.set_output_voltage(5) ## -> Set the output pulse voltage to 5V
switch.connect(port='A', contact=1) ## Connect contact 1 of port A to the common terminal
switch.disconnect(port='A', contact=1) ## Disconnects contact 1 of port A from the common terminal
switch.smart_connect(port='A', contact=1) ## Connect contact 1 and disconnect wichever port was connected previously (based on the history)
CONSTANTS = { "HW_Ver. 0": {
"ADC_12B_res": 4095,
"ADC_8B_res": 255,
"ADC_cal_ref": False,
"bv_R1": 68000,
"bv_R2": 100000,
"bv_ADC": 3,
"converter_divider": 11,
"converter_ADC": 10,
"converter_VREF": 1.23,
"converter_R1": 500000,
"converter_R2": 500000,
"converter_Rf": 15000,
"converter_DAC_lower_bound": 550,
"converter_DAC_upper_bound": 1500,
"converter_correction_codes": [1, 0],
"converter_output_voltage_range": [5, 29],
"OCP_gain": 2,
"OCP_range": [1, 300],
"pulse_duration_range": [1, 100],
"sampling_frequency_range": [10, 100],
"current_sense_R": 1,
"current_gain": 20,
"calibrate_ADC": 0,
"polarization_params": [4700, 3000, 4700]
},
"HW_Ver. 2": {
"ADC_12B_res": 4095,
"ADC_8B_res": 255,
"ADC_cal_ref": False,
"bv_R1": 68000,
"bv_R2": 100000,
"bv_ADC": 3,
"converter_divider": 11,
"converter_ADC": 10,
"converter_VREF": 1.23,
"converter_R1": 500000,
"converter_R2": 500000,
"converter_Rf": 15000,
"converter_DAC_lower_bound": 500,
"converter_DAC_upper_bound": 1500,
"converter_correction_codes": [1, 0],
"converter_output_voltage_range": [5, 29],
"OCP_gain": 2,
"OCP_range": [1, 300],
"pulse_duration_range": [1, 100],
"sampling_frequency_range": [10, 100],
"current_sense_R": 1,
"current_gain": 20,
"calibrate_ADC": 0,
"polarization_params": [4700, 3000, 4700]
},
"HW_Ver. 3": {
"ADC_12B_res": 4095,
"ADC_8B_res": 255,
"ADC_cal_ref": 2.5,
"bv_R1": 68000,
"bv_R2": 100000,
"bv_ADC": 3,
"converter_divider": 11,
"converter_ADC": 10,
"converter_VREF": 1.23,
"converter_R1": 500000,
"converter_R2": 33000,
"converter_Rf": 56000,
"converter_DAC_lower_bound": 0,
"converter_DAC_upper_bound": 4095,
"converter_correction_codes": [1.01722519, 0.01721413],
"converter_output_voltage_range": [5, 29],
"OCP_gain": 2,
"OCP_range": [1, 300],
"pulse_duration_range": [1, 100],
"sampling_frequency_range": [10, 100],
"current_sense_R": 0.5,
"current_gain": 20,
"calibrate_ADC": 1,
"polarization_params": [4700, 3000, 4700]
},
"HW_Ver. 4": {
"ADC_12B_res": 4095,
"ADC_8B_res": 255,
"ADC_cal_ref": 2.5,
"bv_R1": 68000,
"bv_R2": 100000,
"bv_ADC": 3,
"converter_divider": 11,
"converter_ADC": 10,
"converter_VREF": 1.24,
"converter_R1": 500000,
"converter_R2": 33000,
"converter_Rf": 56000,
"converter_DAC_lower_bound": 0,
"converter_DAC_upper_bound": 4095,
"converter_correction_codes": [1.03418631, 0.11739705],
"converter_output_voltage_range": [5, 29],
"OCP_gain": 2,
"OCP_range": [1, 300],
"pulse_duration_range": [1, 100],
"sampling_frequency_range": [10, 100],
"current_sense_R": 0.5,
"current_gain": 20,
"calibrate_ADC": 1,
"polarization_params": [10000, 3000, 4700]
},
"HW_Ver. 5": {
"ADC_12B_res": 4095,
"ADC_8B_res": 255,
"ADC_cal_ref": 2.5,
"bv_R1": 68000,
"bv_R2": 100000,
"bv_ADC": 3,
"converter_divider": 11,
"converter_ADC": 10,
"converter_VREF": 1.24,
"converter_R1": 500000,
"converter_R2": 33000,
"converter_Rf": 56000,
"converter_DAC_lower_bound": 0,
"converter_DAC_upper_bound": 4095,
"converter_correction_codes": [1.03418631, 0.11739705],
"converter_output_voltage_range": [5, 29],
"OCP_gain": 2,
"OCP_range": [1, 300],
"pulse_duration_range": [1, 100],
"sampling_frequency_range": [10, 100],
"current_sense_R": 0.5,
"current_gain": 20,
"calibrate_ADC": 1,
"polarization_params": [10000, 3000, 4700]
}
}
STATES_DEFAULT = {
"SN": {
"port_A": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_B": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_C": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_D": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
}
},
"SN0": {
"port_A": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_B": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_C": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_D": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
}
},
"SN12": {
"port_A": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_B": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_C": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_D": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
}
},
"SN22": {
"port_A": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_B": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_C": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_D": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
}
},
"SN23": {
"port_A": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_B": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_C": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_D": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
}
},
"SN24": {
"port_A": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_B": {
"contact_1": 1,
"contact_2": 0,
"contact_3": 1,
"contact_4": 1,
"contact_5": 1,
"contact_6": 1
},
"port_C": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_D": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
}
},
"SN25": {
"port_A": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_B": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_C": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_D": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
}
},
"SN26": {
"port_A": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_B": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_C": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_D": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
}
},
"SN300": {
"port_A": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_B": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_C": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_D": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
}
},
"SN6": {
"port_A": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_B": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_C": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_D": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
}
},
"SN65535": {
"port_A": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_B": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_C": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
},
"port_D": {
"contact_1": 0,
"contact_2": 0,
"contact_3": 0,
"contact_4": 0,
"contact_5": 0,
"contact_6": 0
}
}
}