Commit 91efd0ebc5b41da7d6b45177f563eb5b40337d5e
Committed by
GitHub
1 parent
861f505391
Exists in
master
Add files via upload
Showing 9 changed files with 806 additions and 0 deletions Inline Diff
instruments/AG34461A.py
| File was created | 1 | from abstract_instrument import abstract_instrument | ||
| 2 | import socket | |||
| 3 | ||||
| 4 | #============================================================================== | |||
| 5 | ||||
| 6 | ALL_VAL_TYPE = ['DCV', 'ACV', 'DCI', 'ACI', 'RES2W', 'RES4W', 'FREQ'] | |||
| 7 | ALL_CHANNELS = ['1'] | |||
| 8 | ||||
| 9 | ADRESS = "192.168.0.61" | |||
| 10 | CONF_VAL_TYPE = ['CONF:VOLT:DC', 'CONF:VOLT:AC', 'CONF:CURR:DC', 'CONF:CURR:AC', 'CONF:RES', 'CONF:FRES', 'CONF:FREQ'] | |||
| 11 | ||||
| 12 | #============================================================================== | |||
| 13 | ||||
| 14 | class AG34461A(abstract_instrument): | |||
| 15 | def __init__(self, channels, vtypes, adress=ADRESS): | |||
| 16 | self.adress = adress | |||
| 17 | self.port = 5025 | |||
| 18 | self.channels = channels | |||
| 19 | self.vtypes = vtypes | |||
| 20 | ||||
| 21 | def model(self): | |||
| 22 | #self.send("*IDN?") | |||
| 23 | #return self.read() | |||
| 24 | return "AG34461A" | |||
| 25 | ||||
| 26 | def connect(self): | |||
| 27 | print('Connecting to device @%s:%s...' %(self.adress, self.port)) | |||
| 28 | self.sock = socket.socket(socket.AF_INET, | |||
| 29 | socket.SOCK_STREAM, | |||
| 30 | socket.IPPROTO_TCP) | |||
| 31 | self.sock.settimeout(10.0) # Don't hang around forever | |||
| 32 | self.sock.connect((self.adress, self.port)) | |||
| 33 | self.send("SYST:BEEP") | |||
| 34 | print(' --> Ok') | |||
| 35 | print(self.model()) | |||
| 36 | self.configure() | |||
| 37 | ||||
| 38 | def configure(self): | |||
| 39 | for ch in self.channels: | |||
| 40 | self.send(CONF_VAL_TYPE[ALL_VAL_TYPE.index(self.vtypes[self.channels.index(ch)])]) | |||
| 41 | ||||
| 42 | def getValue(self): | |||
| 43 | mes = '' | |||
| 44 | for ch in self.channels: | |||
| 45 | self.send("READ?") | |||
| 46 | mesTemp = self.read() | |||
| 47 | mes = mes + '\t' + mesTemp | |||
| 48 | return mes | |||
| 49 | ||||
| 50 | def read(self): | |||
| 51 | ans = '' | |||
| 52 | nb_data_list = [] | |||
| 53 | nb_data = '' | |||
| 54 | try: | |||
| 55 | while ans != '\n': | |||
| 56 | ans = self.sock.recv(1) | |||
| 57 | nb_data_list.append(ans) # Return the number of data | |||
| 58 | list_size = len(nb_data_list) | |||
| 59 | for j in range (0, list_size): | |||
| 60 | nb_data = nb_data+nb_data_list[j] |
instruments/AG34972A.py
| File was created | 1 | from abstract_instrument import abstract_instrument | ||
| 2 | import socket | |||
| 3 | ||||
| 4 | #============================================================================== | |||
| 5 | ||||
| 6 | ALL_VAL_TYPE = ['DCV', 'ACV', 'DCI', 'ACI', 'RES2W', 'RES4W', 'FREQ'] | |||
| 7 | ALL_CHANNELS = ['101', '102', '103', '104', '105'] | |||
| 8 | ||||
| 9 | ADRESS = "192.168.0.72" | |||
| 10 | CONF_VAL_TYPE = ['CONF:VOLT:DC', 'CONF:VOLT:AC', 'CONF:CURR:DC', 'CONF:CURR:AC', 'CONF:RES', 'CONF:FRES', 'CONF:FREQ'] | |||
| 11 | ||||
| 12 | #============================================================================== | |||
| 13 | ||||
| 14 | class AG34972A(abstract_instrument): | |||
| 15 | def __init__(self, channels, vtypes, adress): | |||
| 16 | self.adress = adress | |||
| 17 | self.port = 5025 | |||
| 18 | self.channels = channels | |||
| 19 | self.vtypes = vtypes | |||
| 20 | ||||
| 21 | def model(self): | |||
| 22 | #self.send("*IDN?") | |||
| 23 | #return self.read() | |||
| 24 | return "AG34972A" | |||
| 25 | ||||
| 26 | def connect(self): | |||
| 27 | print('Connecting to device @%s:%s...' %(self.adress, self.port)) | |||
| 28 | self.sock = socket.socket(socket.AF_INET, | |||
| 29 | socket.SOCK_STREAM, | |||
| 30 | socket.IPPROTO_TCP) | |||
| 31 | self.sock.settimeout(2.0) # Don't hang around forever | |||
| 32 | self.sock.connect((self.adress, self.port)) | |||
| 33 | self.send("SYST:BEEP") | |||
| 34 | print(' --> Ok') | |||
| 35 | print(self.model()) | |||
| 36 | self.configure() | |||
| 37 | ||||
| 38 | def configure(self): | |||
| 39 | self.strCh = '' | |||
| 40 | for ch in self.channels: | |||
| 41 | self.send('%s (@%s)'%(CONF_VAL_TYPE[ALL_VAL_TYPE.index(self.vtypes[self.channels.index(ch)])], ch)) | |||
| 42 | self.strCh = self.strCh + ch + ',' | |||
| 43 | self.strCh = self.strCh[0:-1] | |||
| 44 | self.send("ROUT:SCAN (@%s)"%self.strCh) | |||
| 45 | self.send("TRIG:COUN 1") | |||
| 46 | ||||
| 47 | def getValue(self): | |||
| 48 | self.send("INIT") | |||
| 49 | self.send("FETC?") | |||
| 50 | return self.read() | |||
| 51 | ||||
| 52 | def read(self): | |||
| 53 | ans = '' | |||
| 54 | nb_data_list = [] | |||
| 55 | nb_data = '' | |||
| 56 | try: | |||
| 57 | while ans != '\n': | |||
| 58 | ans = self.sock.recv(1) | |||
| 59 | nb_data_list.append(ans) # Return the number of data | |||
| 60 | list_size = len(nb_data_list) | |||
| 61 | for j in range (0, list_size): |
instruments/LS350.py
| File was created | 1 | from abstract_instrument import abstract_instrument | ||
| 2 | import socket | |||
| 3 | ||||
| 4 | #============================================================================== | |||
| 5 | ||||
| 6 | ALL_VAL_TYPE = ['TEMP', 'RES'] | |||
| 7 | ALL_CHANNELS = ['a', 'b', 'c', 'd'] | |||
| 8 | ||||
| 9 | ADRESS = "192.168.0.12" | |||
| 10 | CONF_VAL_TYPE = ['krdg?', 'srdg?'] | |||
| 11 | ||||
| 12 | #============================================================================== | |||
| 13 | ||||
| 14 | class LS350(abstract_instrument): | |||
| 15 | def __init__(self, channels, vtypes, adress): | |||
| 16 | self.adress = adress | |||
| 17 | self.port = 7777 | |||
| 18 | self.channels = channels | |||
| 19 | self.vtypes = vtypes | |||
| 20 | ||||
| 21 | def model(self): | |||
| 22 | #self.send("*IDN?") | |||
| 23 | #return self.read() | |||
| 24 | return "LS350" | |||
| 25 | ||||
| 26 | def connect(self): | |||
| 27 | print('Connecting to device @%s:%s...' %(self.adress, self.port)) | |||
| 28 | self.sock = socket.socket(socket.AF_INET, | |||
| 29 | socket.SOCK_STREAM, | |||
| 30 | socket.IPPROTO_TCP) | |||
| 31 | self.sock.settimeout(10.0) # Don't hang around forever | |||
| 32 | self.sock.connect((self.adress, self.port)) | |||
| 33 | print(' --> Ok') | |||
| 34 | print(self.model()) | |||
| 35 | self.configure() | |||
| 36 | ||||
| 37 | def configure(self): | |||
| 38 | self.strCh = '' | |||
| 39 | for ch in self.channels: | |||
| 40 | self.strCh = self.strCh + '%s %s;'%(CONF_VAL_TYPE[ALL_VAL_TYPE.index(self.vtypes[self.channels.index(ch)])], ch) | |||
| 41 | self.strCh = self.strCh[0:-1] | |||
| 42 | print(self.strCh) | |||
| 43 | ||||
| 44 | def getValue(self): | |||
| 45 | self.send(self.strCh) | |||
| 46 | return self.read() | |||
| 47 | ||||
| 48 | def read(self): | |||
| 49 | self.send("++read eoi") | |||
| 50 | ans = '' | |||
| 51 | nb_data_list = [] | |||
| 52 | nb_data = '' | |||
| 53 | try: | |||
| 54 | while ans != '\n': | |||
| 55 | ans = self.sock.recv(1) | |||
| 56 | nb_data_list.append(ans) # Return the number of data | |||
| 57 | list_size = len(nb_data_list) | |||
| 58 | for j in range (0, list_size): |
instruments/PM100D.py
| File was created | 1 | from abstract_instrument import abstract_instrument | ||
| 2 | import os | |||
| 3 | ||||
| 4 | #============================================================================== | |||
| 5 | ||||
| 6 | ALL_VAL_TYPE = ['PWR'] | |||
| 7 | ALL_CHANNELS = ['1'] | |||
| 8 | ||||
| 9 | ADRESS = "/dev/usbtmc0" | |||
| 10 | CONF_VAL_TYPE = ['PWR'] | |||
| 11 | ||||
| 12 | #============================================================================== | |||
| 13 | ||||
| 14 | class PM100D(abstract_instrument): | |||
| 15 | def __init__(self, channels, vtypes, adress): | |||
| 16 | self.adress = adress | |||
| 17 | self.channels = channels | |||
| 18 | self.vtypes = vtypes | |||
| 19 | ||||
| 20 | def model(self): | |||
| 21 | #self.send("*IDN?") | |||
| 22 | #return self.read() | |||
| 23 | return "PM100D" | |||
| 24 | ||||
| 25 | def connect(self): | |||
| 26 | print('Connecting to device @%s...' %(self.adress)) | |||
| 27 | self.FILE = os.open(self.adress, os.O_RDWR) | |||
| 28 | print(' --> Ok') | |||
| 29 | print(self.model()) | |||
| 30 | self.configure() | |||
| 31 | ||||
| 32 | def configure(self): | |||
| 33 | pass | |||
| 34 |
instruments/T7Pro.py
| File was created | 1 | from abstract_instrument import abstract_instrument | ||
| 2 | from labjack import ljm | |||
| 3 | import numpy | |||
| 4 | ||||
| 5 | #============================================================================== | |||
| 6 | ||||
| 7 | ALL_VAL_TYPE = ['TEMP', 'RES'] | |||
| 8 | ALL_CHANNELS = ['TEMP', '1', '2', '3', '4'] | |||
| 9 | ADRESS = "192.168.0.25" | |||
| 10 | ||||
| 11 | #============================================================================== | |||
| 12 | ||||
| 13 | class T7Pro(abstract_instrument): | |||
| 14 | def __init__(self, adress=ADRESS, vtype=[ALL_VAL_TYPE[0]], channels = [ALL_CHANNELS[0]]): | |||
| 15 | self.adress = adress | |||
| 16 | self.vtype = vtype | |||
| 17 | self.tempName = ["TEMPERATURE_AIR_K"] | |||
| 18 | self.res1Name = ["AIN0", "AIN10"] | |||
| 19 | self.res2Name = ["AIN2", "AIN11"] | |||
| 20 | self.res3Name = ["AIN4", "AIN12"] | |||
| 21 | self.res4Name = ["AIN6", "AIN13"] | |||
| 22 | ||||
| 23 | def model(self): | |||
| 24 | return 'T7Pro' | |||
| 25 | ||||
| 26 | def connect(self): | |||
| 27 | try: | |||
| 28 | print('Connecting to device @%s...' %(self.adress)) | |||
| 29 | self.handle = ljm.openS("T7", "ETHERNET", self.adress) | |||
| 30 | self.configureAINs() | |||
| 31 | print(' --> Ok') | |||
| 32 | ||||
| 33 | print(self.model()) | |||
| 34 | ||||
| 35 | if self.vtype == "TEMP": | |||
| 36 | 1 | |||
| 37 | elif self.vtype == "RES": | |||
| 38 | 1 | |||
| 39 | else: | |||
| 40 | print("Wrong -v argument") | |||
| 41 | raise | |||
| 42 | ||||
| 43 | except Exception as er: | |||
| 44 | print("Unexpected error during connection: " + str(er)) | |||
| 45 | raise | |||
| 46 | ||||
| 47 | def getValue(self): | |||
| 48 | mesTemp = self.read(self.tempName) | |||
| 49 | mesRes1 = self.read(self.res1Name) | |||
| 50 | mesRes2 = self.read(self.res2Name) | |||
| 51 | mesRes3 = self.read(self.res3Name) | |||
| 52 | mesRes4 = self.read(self.res4Name) | |||
| 53 | # mesRes4 = [1, 1] | |||
| 54 | # print("~~~~~~~~~~~~~~~~~~~~~~\n" + str(results) + "~~~~~~~~~~~~~~~~~~~~~~\n") | |||
| 55 | temp = mesTemp[0] | |||
| 56 | res1 = 100.*mesRes1[0]/mesRes1[1] | |||
| 57 | res2 = 100.*mesRes2[0]/mesRes2[1] | |||
| 58 | res3 = 100.*mesRes3[0]/mesRes3[1] | |||
| 59 | res4 = 100.*mesRes4[0]/mesRes4[1] | |||
| 60 | ||||
| 61 | if self.vtype == 'TEMP': | |||
| 62 | # Temperature calculation | |||
| 63 | temp1 = self.res2tempSensor(628, res1) | |||
| 64 | temp2 = self.res2tempSensor(16947, res2) | |||
| 65 | temp3 = self.res2tempSensor(625, res3) | |||
| 66 | temp4 = self.res2tempSensor(100, res4) | |||
| 67 | string = '%f\t%f\t%f\t%f\t%f\n'%(temp, temp1, temp2, temp3, temp4) | |||
| 68 | # string = '%f\t%f\n'%(temp, temp1) | |||
| 69 | elif self.vtype == 'RES': | |||
| 70 | string = '%f\t%f\t%f\t%f\t%f\n'%(temp, res1, res2, res3, res4) | |||
| 71 | # string = '%f\t%f\n'%(temp, res1) | |||
| 72 | else: | |||
| 73 | string = '' | |||
| 74 | ||||
| 75 | return string | |||
| 76 | ||||
| 77 | def read(self, names): | |||
| 78 | return ljm.eReadNames(self.handle, len(names), names) | |||
| 79 | ||||
| 80 | def disconnect(self): | |||
| 81 | ljm.close(self.handle) | |||
| 82 | ||||
| 83 | def send(self, command): | |||
| 84 | pass | |||
| 85 | ||||
| 86 | def configureAINs(self): | |||
| 87 | # Setup and call eWriteNames to configure AINs on the LabJack. | |||
| 88 | names = ["AIN0_NEGATIVE_CH", "AIN0_RANGE", "AIN0_RESOLUTION_INDEX", | |||
| 89 | "AIN1_NEGATIVE_CH", "AIN1_RANGE", "AIN1_RESOLUTION_INDEX", | |||
| 90 | "AIN2_NEGATIVE_CH", "AIN2_RANGE", "AIN2_RESOLUTION_INDEX", | |||
| 91 | "AIN3_NEGATIVE_CH", "AIN3_RANGE", "AIN3_RESOLUTION_INDEX", | |||
| 92 | "AIN4_NEGATIVE_CH", "AIN4_RANGE", "AIN4_RESOLUTION_INDEX", | |||
| 93 | "AIN5_NEGATIVE_CH", "AIN5_RANGE", "AIN5_RESOLUTION_INDEX", | |||
| 94 | "AIN6_NEGATIVE_CH", "AIN6_RANGE", "AIN6_RESOLUTION_INDEX", | |||
| 95 | "AIN7_NEGATIVE_CH", "AIN7_RANGE", "AIN7_RESOLUTION_INDEX", | |||
| 96 | "AIN8_NEGATIVE_CH", "AIN8_RANGE", "AIN8_RESOLUTION_INDEX", | |||
| 97 | "AIN9_NEGATIVE_CH", "AIN9_RANGE", "AIN9_RESOLUTION_INDEX", | |||
| 98 | "AIN10_NEGATIVE_CH", "AIN10_RANGE", "AIN10_RESOLUTION_INDEX", | |||
| 99 | "AIN11_NEGATIVE_CH", "AIN11_RANGE", "AIN11_RESOLUTION_INDEX", | |||
| 100 | "AIN12_NEGATIVE_CH", "AIN12_RANGE", "AIN12_RESOLUTION_INDEX", | |||
| 101 | "AIN13_NEGATIVE_CH", "AIN13_RANGE", "AIN13_RESOLUTION_INDEX" | |||
| 102 | ] | |||
| 103 | l_names = len(names) | |||
| 104 | aValues = [1, 0.1, 12,#0 | |||
| 105 | 199, 0.1, 12,#1 | |||
| 106 | 3, 0.1, 12,#2 | |||
| 107 | 199, 0.1, 12,#3 | |||
| 108 | 5, 0.1, 12,#4 | |||
| 109 | 199, 0.1, 12,#5 | |||
| 110 | 7, 0.1, 12,#6 | |||
| 111 | 199, 0.1, 12,#7 | |||
| 112 | 199, 0.1, 12,#8 | |||
| 113 | 199, 0.1, 12,#9 | |||
| 114 | 199, 0.1, 12,#10 | |||
| 115 | 199, 0.1, 12,#11 | |||
| 116 | 199, 0.1, 12,#12 | |||
| 117 | 199, 0.1, 12#13 | |||
| 118 | ] | |||
| 119 | ljm.eWriteNames(self.handle, l_names, names, aValues) | |||
| 120 | ||||
| 121 | ||||
| 122 | def res2tempSensor(self, sensor, res): | |||
| 123 | if sensor==627: | |||
| 124 | K = [0.399341181655472610, | |||
| 125 | 10.8420092277810909, | |||
| 126 | -26.4597939187660813, | |||
| 127 | 245.9828566655493379, | |||
| 128 | -668.069876596331596, | |||
| 129 | 1001.69882618263364, | |||
| 130 | -267.272089680656791] | |||
| 131 | if sensor==625: | |||
| 132 | K = [0.333548856582638109, | |||
| 133 | 11.7361551595386118, | |||
| 134 | -31.32988932320903987, | |||
| 135 | 262.878643524833024, | |||
| 136 | -704.163538021035492, | |||
| 137 | 1056.6040485650301, | |||
| 138 | -307.057196729816496] | |||
| 139 | if sensor==628: | |||
| 140 | K = [0.463200932294057566, | |||
| 141 | 13.5049710820894688, | |||
| 142 | -30.5191222755238414, | |||
| 143 | 231.098593852017075, | |||
| 144 | -550.122691885568202, | |||
| 145 | 806.038547554984689, | |||
| 146 | -198.510489917360246] | |||
| 147 | if sensor==16945: | |||
| 148 | K = [3.2497, 5.1777, 2.499] | |||
| 149 | if sensor==16943: | |||
| 150 | K = [3.4738, 5.1198, 2.3681] | |||
| 151 | if sensor==16944: | |||
| 152 | K = [3.3674, 5.2874, 2.5165] | |||
| 153 | if sensor==16941: | |||
| 154 | K = [2.9486, 4.5862, 2.266] |
instruments/TPG261.py
| File was created | 1 | from abstract_instrument import abstract_instrument | ||
| 2 | import serial | |||
| 3 | ||||
| 4 | #============================================================================== | |||
| 5 | ||||
| 6 | ALL_VAL_TYPE = ['PRE'] | |||
| 7 | ALL_CHANNELS = ['1'] | |||
| 8 | ADRESS = "/dev/ttyS0" | |||
| 9 | ||||
| 10 | #============================================================================== | |||
| 11 | ||||
| 12 | class TPG261(abstract_instrument): | |||
| 13 | def __init__(self, adress=ADRESS, vtype=[ALL_VAL_TYPE[0]], channels = [ALL_CHANNELS[0]]): | |||
| 14 | self.adress = adress | |||
| 15 | self.vtype = vtype | |||
| 16 | ||||
| 17 | def model(self): | |||
| 18 | return "PfeifferTPG261" | |||
| 19 | ||||
| 20 | def connect(self): | |||
| 21 | try: | |||
| 22 | print('Connecting to device @%s...' %(self.adress)) | |||
| 23 | self.TPG = MaxiGauge(self.adress) | |||
| 24 | print(' --> Ok') | |||
| 25 | ||||
| 26 | print(self.model()) | |||
| 27 | ||||
| 28 | if self.vtype == "PRE": | |||
| 29 | 1 | |||
| 30 | else: | |||
| 31 | print("Wrong -v argument") | |||
| 32 | raise | |||
| 33 | ||||
| 34 | except Exception as er: | |||
| 35 | print("Unexpected error during connection: " + str(er)) | |||
| 36 | raise | |||
| 37 | ||||
| 38 | def getValue(self): | |||
| 39 | self.read() | |||
| 40 | return "%s\n"%self.ps[0].pressure | |||
| 41 | ||||
| 42 | def read(self): | |||
| 43 | self.ps = self.TPG.pressures() | |||
| 44 | ||||
| 45 | def disconnect(self): | |||
| 46 | self.TPG.disconnect() | |||
| 47 | ||||
| 48 | def send(self, command): | |||
| 49 | pass | |||
| 50 | ||||
| 51 | ||||
| 52 | ||||
| 53 | ||||
| 54 | # from Philipp Klaus, philipp.l.klaus AT web.de PfeifferVacuum.py | |||
| 55 | ||||
| 56 | class MaxiGauge (object): | |||
| 57 | def __init__(self, serialPort, baud=9600, debug=False): | |||
| 58 | self.debug=debug | |||
| 59 | try: | |||
| 60 | self.connection = serial.Serial(serialPort, baudrate=baud, timeout=0.2) | |||
| 61 | except serial.serialutil.SerialException as se: | |||
| 62 | raise MaxiGaugeError(se) | |||
| 63 | #self.send(C['ETX']) ### We might reset the connection first, but it doesn't really matter: | |||
| 64 | ||||
| 65 | def checkDevice(self): | |||
| 66 | message = "The Display Contrast is currently set to %d (out of 20).\n" % self.displayContrast() | |||
| 67 | message += "Keys since MaxiGauge was switched on: %s (out of 1,2,3,4,5).\n" % ", ".join( map (str, self.pressedKeys()) ) | |||
| 68 | return message | |||
| 69 | ||||
| 70 | def pressedKeys(self): | |||
| 71 | keys = int(self.send('TKB',1)[0]) | |||
| 72 | pressedKeys = [] | |||
| 73 | for i in [4,3,2,1,0]: # It's got 5 keys | |||
| 74 | if keys/2**i == 1: | |||
| 75 | pressedKeys.append(i+1) | |||
| 76 | keys = keys%2**i | |||
| 77 | pressedKeys.reverse() | |||
| 78 | return pressedKeys | |||
| 79 | ||||
| 80 | def displayContrast(self,newContrast=-1): | |||
| 81 | if newContrast == -1: return int(self.send('DCC',1)[0]) | |||
| 82 | else: return int(self.send('DCC,%d' % (newContrast,) ,1)[0]) | |||
| 83 | ||||
| 84 | def pressures(self): | |||
| 85 | return [self.pressure(i+1) for i in range(1)] | |||
| 86 | ||||
| 87 | def pressure(self, sensor): | |||
| 88 | if sensor < 1 or sensor >6: raise MaxiGaugeError('Sensor can only be between 1 and 6. You choose ' + str(sensor)) | |||
| 89 | reading = self.send('PR%d' % sensor, 1) ## reading will have the form x,x.xxxEsx <CR><LF> (see p.88) | |||
| 90 | try: | |||
| 91 | r = reading[0].split(',') | |||
| 92 | status = int(r[0]) | |||
| 93 | pressure = float(r[-1]) | |||
| 94 | except: | |||
| 95 | raise MaxiGaugeError("Problem interpreting the returned line:\n%s" % reading) | |||
| 96 | return PressureReading(sensor, status, pressure) | |||
| 97 | ||||
| 98 | def debugMessage(self, message): | |||
| 99 | if self.debug: print(repr(message)) | |||
| 100 | ||||
| 101 | def send(self, mnemonic, numEnquiries = 0): | |||
| 102 | self.connection.flushInput() | |||
| 103 | self.write(mnemonic+LINE_TERMINATION) | |||
| 104 | #if mnemonic != C['ETX']: self.read() | |||
| 105 | #self.read() | |||
| 106 | self.getACQorNAK() | |||
| 107 | response = [] | |||
| 108 | for i in range(numEnquiries): | |||
| 109 | self.enquire() | |||
| 110 | response.append(self.read()) | |||
| 111 | return response | |||
| 112 | ||||
| 113 | def write(self,what): | |||
| 114 | self.debugMessage(what) | |||
| 115 | self.connection.write(what) | |||
| 116 | ||||
| 117 | def enquire(self): | |||
| 118 | self.write(C['ENQ']) | |||
| 119 | ||||
| 120 | def read(self): | |||
| 121 | data = "" | |||
| 122 | while True: | |||
| 123 | x = self.connection.read() | |||
| 124 | self.debugMessage(x) | |||
| 125 | data += x | |||
| 126 | if len(data)>1 and data[-2:]==LINE_TERMINATION: | |||
| 127 | break | |||
| 128 | return data[:-len(LINE_TERMINATION)] | |||
| 129 | ||||
| 130 | def getACQorNAK(self): | |||
| 131 | returncode = self.connection.readline() | |||
| 132 | self.debugMessage(returncode) | |||
| 133 | ## The following is usually expected but our MaxiGauge controller sometimes forgets this parameter... That seems to be a bug with the DCC command. | |||
| 134 | #if len(returncode)<3: raise MaxiGaugeError('Only received a line termination from MaxiGauge. Was expecting ACQ or NAK.') | |||
| 135 | if len(returncode)<3: self.debugMessage('Only received a line termination from MaxiGauge. Was expecting ACQ or NAK.') | |||
| 136 | if len(returncode)>2 and returncode[-3] == C['NAK']: | |||
| 137 | self.enquire() | |||
| 138 | returnedError = self.read() | |||
| 139 | error = str(returnedError).split(',' , 1) | |||
| 140 | print repr(error) | |||
| 141 | errmsg = { 'System Error': ERR_CODES[0][int(error[0])] , 'Gauge Error': ERR_CODES[1][int(error[1])] } | |||
| 142 | raise MaxiGaugeNAK(errmsg) | |||
| 143 | #if len(returncode)>2 and returncode[-3] != C['ACQ']: raise MaxiGaugeError('Expecting ACQ or NAK from MaxiGauge but neither were sent.') | |||
| 144 | if len(returncode)>2 and returncode[-3] != C['ACQ']: self.debugMessage('Expecting ACQ or NAK from MaxiGauge but neither were sent.') | |||
| 145 | # if no exception raised so far, the interface is just fine: | |||
| 146 | return returncode[:-(len(LINE_TERMINATION)+1)] | |||
| 147 | ||||
| 148 | def disconnect(self): | |||
| 149 | #self.send(C['ETX']) | |||
| 150 | if hasattr(self, 'connection') and self.connection: self.connection.close() | |||
| 151 | ||||
| 152 | def __del__(self): | |||
| 153 | self.disconnect() | |||
| 154 | ||||
| 155 | class PressureReading(object): | |||
| 156 | def __init__(self, id, status, pressure): | |||
| 157 | if int(id) not in range(1,7): raise MaxiGaugeError('Pressure Gauge ID must be between 1-6') | |||
| 158 | self.id = int(id) | |||
| 159 | if int(status) not in PRESSURE_READING_STATUS.keys(): raise MaxiGaugeError('The Pressure Status must be in the range %s' % PRESSURE_READING_STATUS.keys()) | |||
| 160 | self.status = int(status) | |||
| 161 | self.pressure = float(pressure) | |||
| 162 | ||||
| 163 | def statusMsg(self): | |||
| 164 | return PRESSURE_READING_STATUS[self.status] | |||
| 165 | ||||
| 166 | def __repr__(self): | |||
| 167 | return "Gauge #%d: Status %d (%s), Pressure: %f mbar\n" % (self.id, self.status, self.statusMsg(), self.pressure) | |||
| 168 | ||||
| 169 | ||||
| 170 | ### ------ now we define the exceptions that could occur ------ | |||
| 171 | ||||
| 172 | class MaxiGaugeError(Exception): | |||
| 173 | pass | |||
| 174 | ||||
| 175 | class MaxiGaugeNAK(MaxiGaugeError): | |||
| 176 | pass | |||
| 177 | ||||
| 178 | ### ------- Control Symbols as defined on p. 81 of the english | |||
| 179 | ### manual for the Pfeiffer Vacuum TPG256A ----------- | |||
| 180 | C = { | |||
| 181 | 'ETX': "\x03", # End of Text (Ctrl-C) Reset the interface | |||
| 182 | 'CR': "\x0D", # Carriage Return Go to the beginning of line | |||
| 183 | 'LF': "\x0A", # Line Feed Advance by one line | |||
| 184 | 'ENQ': "\x05", # Enquiry Request for data transmission | |||
| 185 | 'ACQ': "\x06", # Acknowledge Positive report signal | |||
| 186 | 'NAK': "\x15", # Negative Acknowledge Negative report signal | |||
| 187 | 'ESC': "\x1b", # Escape | |||
| 188 | } | |||
| 189 | ||||
| 190 | LINE_TERMINATION=C['CR']+C['LF'] # CR, LF and CRLF are all possible (p.82) | |||
| 191 | ||||
| 192 | ### Mnemonics as defined on p. 85 | |||
| 193 | M = [ | |||
| 194 | 'BAU', # Baud rate Baud rate 95 | |||
| 195 | 'CAx', # Calibration factor Sensor x Calibration factor sensor x (1 ... 6) 92 | |||
| 196 | 'CID', # Measurement point names Measurement point names 88 | |||
| 197 | 'DCB', # Display control Bargraph Bargraph 89 | |||
| 198 | 'DCC', # Display control Contrast Display control contrast 90 | |||
| 199 | 'DCD', # Display control Digits Display digits 88 | |||
| 200 | 'DCS', # Display control Screensave Display control screensave 90 | |||
| 201 | 'DGS', # Degas Degas 93 | |||
| 202 | 'ERR', # Error Status Error status 97 | |||
| 203 | 'FIL', # Filter time constant Filter time constant 92 | |||
| 204 | 'FSR', # Full scale range of linear sensors Full scale range of linear sensors 93 | |||
| 205 | 'LOC', # Parameter setup lock Parameter setup lock 91 | |||
| 206 | 'NAD', # Node (device) address for RS485 Node (device) address for RS485 96 | |||
| 207 | 'OFC', # Offset correction Offset correction 93 | |||
| 208 | 'OFC', # Offset correction Offset correction 93 | |||
| 209 | 'PNR', # Program number Program number 98 | |||
| 210 | 'PRx', # Status, Pressure sensor x (1 ... 6) Status, Pressure sensor x (1 ... 6) 88 | |||
| 211 | 'PUC', # Underrange Ctrl Underrange control 91 | |||
| 212 | 'RSX', # Interface Interface 94 | |||
| 213 | 'SAV', # Save default Save default 94 | |||
| 214 | 'SCx', # Sensor control Sensor control 87 | |||
| 215 | 'SEN', # Sensor on/off Sensor on/off 86 | |||
| 216 | 'SPx', # Set Point Control Source for Relay xThreshold value setting, Allocation 90 | |||
| 217 | 'SPS', # Set Point Status A,B,C,D,E,F Set point status 91 | |||
| 218 | 'TAI', # Test program A/D Identify Test A/D converter identification inputs 100 | |||
| 219 | 'TAS', # Test program A/D Sensor Test A/D converter measurement value inputs 100 | |||
| 220 | 'TDI', # Display test Display test 98 | |||
| 221 | 'TEE', # EEPROM test EEPROM test 100 | |||
| 222 | 'TEP', # EPROM test EPROM test 99 | |||
| 223 | 'TID', # Sensor identification Sensor identification 101 | |||
| 224 | 'TKB', # Keyboard test Keyboard test 99 | |||
| 225 | 'TRA', # RAM test RAM test 99 | |||
| 226 | 'UNI', # Unit of measurement (Display) Unit of measurement (pressure) 89 | |||
| 227 | 'WDT', # Watchdog and System Error Control Watchdog and system error control 101 | |||
| 228 | ] | |||
| 229 | ||||
| 230 |
instruments/__init__.py
| File was created | 1 | from os import listdir | ||
| 2 | from os.path import dirname | |||
| 3 | ||||
| 4 | for module in listdir(dirname(__file__)): | |||
| 5 | if module == '__init__.py' or module == 'abstract_instrument.py' or module[-3:] != '.py': | |||
| 6 | continue | |||
| 7 | __import__(module[:-3], locals(), globals()) |
instruments/abstract_instrument.py
| File was created | 1 | import abc | ||
| 2 | ||||
| 3 | class abstract_instrument(object): | |||
| 4 | __metaclass__ = abc.ABCMeta | |||
| 5 | ||||
| 6 | @abc.abstractmethod | |||
| 7 | def __init__(self, adress, vtype, channel): | |||
| 8 | """Build the class""" | |||
| 9 | return | |||
| 10 | ||||
| 11 | @abc.abstractmethod | |||
| 12 | def model(self): | |||
| 13 | """return the instrument model""" | |||
| 14 | return | |||
| 15 | ||||
| 16 | @abc.abstractmethod | |||
| 17 | def connect(self): | |||
| 18 | """Create a connection with the instrument""" | |||
| 19 | return | |||
| 20 | ||||
| 21 | @abc.abstractmethod | |||
| 22 | def disconnect(self): | |||
| 23 | """Disconnect the instrument""" | |||
| 24 | return | |||
| 25 | ||||
| 26 | @abc.abstractmethod | |||
| 27 | def configure(self): | |||
| 28 | """Configure the instrument""" | |||
| 29 | return | |||
| 30 | ||||
| 31 | @abc.abstractmethod | |||
| 32 | def read(self): | |||
| 33 | """read the buffer""" | |||
| 34 | return | |||
| 35 |
instruments/testDevice.py
| File was created | 1 | from abstract_instrument import abstract_instrument | ||
| 2 | import numpy, time | |||
| 3 | ||||
| 4 | #============================================================================== | |||
| 5 | ||||
| 6 | ALL_VAL_TYPE = ['vtype', 'DCV', 'ACV', 'DCI', 'ACI', 'RES2W', 'RES4W', 'FREQ'] | |||
| 7 | ALL_CHANNELS = ['0', '1'] | |||
| 8 | ADRESS = "123.456.789.123" | |||
| 9 | ||||
| 10 | #============================================================================== | |||
| 11 | ||||
| 12 | class testDevice(abstract_instrument): | |||
| 13 | def __init__(self, channels, vtype, adress = ADRESS): | |||
| 14 | self.adress = adress | |||
| 15 | self.port = 9999 | |||
| 16 | self.channels = channels | |||
| 17 | print(self.channels) | |||
| 18 | self.vtype = vtype | |||
| 19 | print(self.vtype) | |||
| 20 | ||||
| 21 | def model(self): | |||
| 22 | return 'test_device' | |||
| 23 | ||||
| 24 | def connect(self): | |||
| 25 | print('Connecting to device @%s:%s...' %(self.adress, self.port)) | |||
| 26 | time.sleep(1) | |||
| 27 | print(' --> Ok') | |||
| 28 | ||||
| 29 | print(self.model()) | |||
| 30 | ||||
| 31 | def getValue(self): | |||
| 32 | mes = "" | |||
| 33 | for ch in self.channels: | |||
| 34 | mes = mes + str(numpy.random.rand()) + '\t' |