Commit b383042b0b63956ce4dceb15409f0c45415fa0e6
1 parent
6a7849f48a
Exists in
master
-
Showing 1 changed file with 3 additions and 3 deletions Inline Diff
instruments/TPG261.py
from abstract_instrument import abstract_instrument | 1 | 1 | from abstract_instrument import abstract_instrument | |
import serial | 2 | 2 | import serial | |
3 | 3 | |||
#============================================================================== | 4 | 4 | #============================================================================== | |
5 | 5 | |||
ALL_VAL_TYPE = ['PRE'] | 6 | 6 | ALL_VAL_TYPE = ['PRE'] | |
ALL_CHANNELS = ['1'] | 7 | 7 | ALL_CHANNELS = ['1'] | |
ADRESS = "/dev/ttyS0" | 8 | 8 | ADRESS = "/dev/ttyS0" | |
9 | 9 | |||
#============================================================================== | 10 | 10 | #============================================================================== | |
11 | 11 | |||
class TPG261(abstract_instrument): | 12 | 12 | class TPG261(abstract_instrument): | |
def __init__(self, channels, vtypes, adress): | 13 | 13 | def __init__(self, channels, vtypes, adress): | |
self.adress = adress | 14 | 14 | self.adress = adress | |
self.channels = channels | 15 | 15 | self.channels = channels | |
self.vtypes = vtypes | 16 | 16 | self.vtypes = vtypes | |
17 | 17 | |||
def model(self): | 18 | 18 | def model(self): | |
return "PfeifferTPG261" | 19 | 19 | return "PfeifferTPG261" | |
20 | 20 | |||
def connect(self): | 21 | 21 | def connect(self): | |
print('Connecting to device @%s...' %(self.adress)) | 22 | 22 | print('Connecting to device @%s...' %(self.adress)) | |
self.TPG = MaxiGauge(self.adress) | 23 | 23 | self.TPG = MaxiGauge(self.adress) | |
print(' --> Ok') | 24 | 24 | print(' --> Ok') | |
print(self.model()) | 25 | 25 | print(self.model()) | |
self.configure() | 26 | 26 | self.configure() | |
27 | 27 | |||
def configure(self): | 28 | 28 | def configure(self): | |
pass | 29 | 29 | pass | |
30 | 30 | |||
def getValue(self): | 31 | 31 | def getValue(self): | |
self.read() | 32 | 32 | self.read() | |
return "%s\n"%self.ps[0].pressure | 33 | 33 | return "%s\n"%self.ps[0].pressure | |
34 | 34 | |||
def read(self): | 35 | 35 | def read(self): | |
self.ps = self.TPG.pressures() | 36 | 36 | self.ps = self.TPG.pressures() | |
37 | 37 | |||
def disconnect(self): | 38 | 38 | def disconnect(self): | |
self.TPG.disconnect() | 39 | 39 | self.TPG.disconnect() | |
40 | 40 | |||
def send(self, command): | 41 | 41 | def send(self, command): | |
pass | 42 | 42 | pass | |
43 | 43 | |||
44 | 44 | |||
45 | 45 | |||
46 | 46 | |||
# from Philipp Klaus, philipp.l.klaus AT web.de PfeifferVacuum.py | 47 | 47 | # from Philipp Klaus, philipp.l.klaus AT web.de PfeifferVacuum.py | |
48 | 48 | |||
class MaxiGauge (object): | 49 | 49 | class MaxiGauge (object): | |
def __init__(self, serialPort, baud=9600, debug=False): | 50 | 50 | def __init__(self, serialPort, baud=9600, debug=False): | |
self.debug=debug | 51 | 51 | self.debug=debug | |
try: | 52 | 52 | try: | |
self.connection = serial.Serial(serialPort, baudrate=baud, timeout=0.2) | 53 | 53 | self.connection = serial.Serial(serialPort, baudrate=baud, timeout=0.2) | |
except serial.serialutil.SerialException as se: | 54 | 54 | except serial.serialutil.SerialException as se: | |
raise MaxiGaugeError(se) | 55 | 55 | raise MaxiGaugeError(se) | |
#self.send(C['ETX']) ### We might reset the connection first, but it doesn't really matter: | 56 | 56 | #self.send(C['ETX']) ### We might reset the connection first, but it doesn't really matter: | |
57 | 57 | |||
def checkDevice(self): | 58 | 58 | def checkDevice(self): | |
message = "The Display Contrast is currently set to %d (out of 20).\n" % self.displayContrast() | 59 | 59 | message = "The Display Contrast is currently set to %d (out of 20).\n" % self.displayContrast() | |
message += "Keys since MaxiGauge was switched on: %s (out of 1,2,3,4,5).\n" % ", ".join( map (str, self.pressedKeys()) ) | 60 | 60 | message += "Keys since MaxiGauge was switched on: %s (out of 1,2,3,4,5).\n" % ", ".join( map (str, self.pressedKeys()) ) | |
return message | 61 | 61 | return message | |
62 | 62 | |||
def pressedKeys(self): | 63 | 63 | def pressedKeys(self): | |
keys = int(self.send('TKB',1)[0]) | 64 | 64 | keys = int(self.send('TKB',1)[0]) | |
pressedKeys = [] | 65 | 65 | pressedKeys = [] | |
for i in [4,3,2,1,0]: # It's got 5 keys | 66 | 66 | for i in [4,3,2,1,0]: # It's got 5 keys | |
if keys/2**i == 1: | 67 | 67 | if keys/2**i == 1: | |
pressedKeys.append(i+1) | 68 | 68 | pressedKeys.append(i+1) | |
keys = keys%2**i | 69 | 69 | keys = keys%2**i | |
pressedKeys.reverse() | 70 | 70 | pressedKeys.reverse() | |
return pressedKeys | 71 | 71 | return pressedKeys | |
72 | 72 | |||
def displayContrast(self,newContrast=-1): | 73 | 73 | def displayContrast(self,newContrast=-1): | |
if newContrast == -1: return int(self.send('DCC',1)[0]) | 74 | 74 | if newContrast == -1: return int(self.send('DCC',1)[0]) | |
else: return int(self.send('DCC,%d' % (newContrast,) ,1)[0]) | 75 | 75 | else: return int(self.send('DCC,%d' % (newContrast,) ,1)[0]) | |
76 | 76 | |||
def pressures(self): | 77 | 77 | def pressures(self): | |
return [self.pressure(i+1) for i in range(1)] | 78 | 78 | return [self.pressure(i+1) for i in range(1)] | |
79 | 79 | |||
def pressure(self, sensor): | 80 | 80 | def pressure(self, sensor): | |
if sensor < 1 or sensor >6: raise MaxiGaugeError('Sensor can only be between 1 and 6. You choose ' + str(sensor)) | 81 | 81 | if sensor < 1 or sensor >6: raise MaxiGaugeError('Sensor can only be between 1 and 6. You choose ' + str(sensor)) | |
reading = self.send('PR%d' % sensor, 1) ## reading will have the form x,x.xxxEsx <CR><LF> (see p.88) | 82 | 82 | reading = self.send('PR%d' % sensor, 1) ## reading will have the form x,x.xxxEsx <CR><LF> (see p.88) | |
try: | 83 | 83 | try: | |
r = reading[0].split(',') | 84 | 84 | r = reading[0].split(',') | |
status = int(r[0]) | 85 | 85 | status = int(r[0]) | |
pressure = float(r[-1]) | 86 | 86 | pressure = float(r[-1]) | |
except: | 87 | 87 | except: | |
raise MaxiGaugeError("Problem interpreting the returned line:\n%s" % reading) | 88 | 88 | raise MaxiGaugeError("Problem interpreting the returned line:\n%s" % reading) | |
return PressureReading(sensor, status, pressure) | 89 | 89 | return PressureReading(sensor, status, pressure) | |
90 | 90 | |||
def debugMessage(self, message): | 91 | 91 | def debugMessage(self, message): | |
if self.debug: print(repr(message)) | 92 | 92 | if self.debug: print(repr(message)) | |
93 | 93 | |||
def send(self, mnemonic, numEnquiries = 0): | 94 | 94 | def send(self, mnemonic, numEnquiries = 0): | |
self.connection.flushInput() | 95 | 95 | self.connection.flushInput() | |
self.write(mnemonic+LINE_TERMINATION) | 96 | 96 | self.write(mnemonic+LINE_TERMINATION) | |
#if mnemonic != C['ETX']: self.read() | 97 | 97 | #if mnemonic != C['ETX']: self.read() | |
#self.read() | 98 | 98 | #self.read() | |
self.getACQorNAK() | 99 | 99 | self.getACQorNAK() | |
response = [] | 100 | 100 | response = [] | |
for i in range(numEnquiries): | 101 | 101 | for i in range(numEnquiries): | |
self.enquire() | 102 | 102 | self.enquire() | |
response.append(self.read()) | 103 | 103 | response.append(self.read()) | |
return response | 104 | 104 | return response | |
105 | 105 | |||
def write(self,what): | 106 | 106 | def write(self,what): | |
self.debugMessage(what) | 107 | 107 | self.debugMessage(what) | |
self.connection.write(what) | 108 | 108 | self.connection.write(what) | |
109 | 109 | |||
def enquire(self): | 110 | 110 | def enquire(self): | |
self.write(C['ENQ']) | 111 | 111 | self.write(C['ENQ']) | |
112 | 112 | |||
def read(self): | 113 | 113 | def read(self): | |
data = "" | 114 | 114 | data = "" | |
while True: | 115 | 115 | while True: | |
x = self.connection.read() | 116 | 116 | x = self.connection.read() | |
self.debugMessage(x) | 117 | 117 | self.debugMessage(x) | |
data += x | 118 | 118 | data += x | |
if len(data)>1 and data[-2:]==LINE_TERMINATION: | 119 | 119 | if len(data)>1 and data[-2:]==LINE_TERMINATION: | |
break | 120 | 120 | break | |
return data[:-len(LINE_TERMINATION)] | 121 | 121 | return data[:-len(LINE_TERMINATION)] | |
122 | 122 | |||
def getACQorNAK(self): | 123 | 123 | def getACQorNAK(self): | |
returncode = self.connection.readline() | 124 | 124 | returncode = self.connection.readline() | |
self.debugMessage(returncode) | 125 | 125 | self.debugMessage(returncode) | |
## The following is usually expected but our MaxiGauge controller sometimes forgets this parameter... That seems to be a bug with the DCC command. | 126 | 126 | ## The following is usually expected but our MaxiGauge controller sometimes forgets this parameter... That seems to be a bug with the DCC command. | |
#if len(returncode)<3: raise MaxiGaugeError('Only received a line termination from MaxiGauge. Was expecting ACQ or NAK.') | 127 | 127 | #if len(returncode)<3: raise MaxiGaugeError('Only received a line termination from MaxiGauge. Was expecting ACQ or NAK.') | |
if len(returncode)<3: self.debugMessage('Only received a line termination from MaxiGauge. Was expecting ACQ or NAK.') | 128 | 128 | if len(returncode)<3: self.debugMessage('Only received a line termination from MaxiGauge. Was expecting ACQ or NAK.') | |
if len(returncode)>2 and returncode[-3] == C['NAK']: | 129 | 129 | if len(returncode)>2 and returncode[-3] == C['NAK']: | |
self.enquire() | 130 | 130 | self.enquire() | |
returnedError = self.read() | 131 | 131 | returnedError = self.read() | |
error = str(returnedError).split(',' , 1) | 132 | 132 | error = str(returnedError).split(',' , 1) | |
print repr(error) | 133 | 133 | print repr(error) | |
errmsg = { 'System Error': ERR_CODES[0][int(error[0])] , 'Gauge Error': ERR_CODES[1][int(error[1])] } | 134 | 134 | errmsg = { 'System Error': ERR_CODES[0][int(error[0])] , 'Gauge Error': ERR_CODES[1][int(error[1])] } | |
raise MaxiGaugeNAK(errmsg) | 135 | 135 | raise MaxiGaugeNAK(errmsg) | |
#if len(returncode)>2 and returncode[-3] != C['ACQ']: raise MaxiGaugeError('Expecting ACQ or NAK from MaxiGauge but neither were sent.') | 136 | 136 | #if len(returncode)>2 and returncode[-3] != C['ACQ']: raise MaxiGaugeError('Expecting ACQ or NAK from MaxiGauge but neither were sent.') | |
if len(returncode)>2 and returncode[-3] != C['ACQ']: self.debugMessage('Expecting ACQ or NAK from MaxiGauge but neither were sent.') | 137 | 137 | if len(returncode)>2 and returncode[-3] != C['ACQ']: self.debugMessage('Expecting ACQ or NAK from MaxiGauge but neither were sent.') | |
# if no exception raised so far, the interface is just fine: | 138 | 138 | # if no exception raised so far, the interface is just fine: | |
return returncode[:-(len(LINE_TERMINATION)+1)] | 139 | 139 | return returncode[:-(len(LINE_TERMINATION)+1)] | |
140 | 140 | |||
def disconnect(self): | 141 | 141 | def disconnect(self): | |
#self.send(C['ETX']) | 142 | 142 | #self.send(C['ETX']) | |
if hasattr(self, 'connection') and self.connection: self.connection.close() | 143 | 143 | if hasattr(self, 'connection') and self.connection: self.connection.close() | |
144 | 144 | |||
def __del__(self): | 145 | 145 | def __del__(self): | |
self.disconnect() | 146 | 146 | self.disconnect() | |
147 | 147 | |||
class PressureReading(object): | 148 | 148 | class PressureReading(object): | |
def __init__(self, id, status, pressure): | 149 | 149 | def __init__(self, id, status, pressure): | |
if int(id) not in range(1,7): raise MaxiGaugeError('Pressure Gauge ID must be between 1-6') | 150 | 150 | if int(id) not in range(1,7): raise MaxiGaugeError('Pressure Gauge ID must be between 1-6') | |
self.id = int(id) | 151 | 151 | self.id = int(id) | |
if int(status) not in PRESSURE_READING_STATUS.keys(): raise MaxiGaugeError('The Pressure Status must be in the range %s' % PRESSURE_READING_STATUS.keys()) | 152 | 152 | if int(status) not in PRESSURE_READING_STATUS.keys(): raise MaxiGaugeError('The Pressure Status must be in the range %s' % PRESSURE_READING_STATUS.keys()) | |
self.status = int(status) | 153 | 153 | self.status = int(status) | |
self.pressure = float(pressure) | 154 | 154 | self.pressure = float(pressure) | |
155 | 155 | |||
def statusMsg(self): | 156 | 156 | def statusMsg(self): | |
return PRESSURE_READING_STATUS[self.status] | 157 | 157 | return PRESSURE_READING_STATUS[self.status] | |
158 | 158 | |||
def __repr__(self): | 159 | 159 | def __repr__(self): | |
return "Gauge #%d: Status %d (%s), Pressure: %f mbar\n" % (self.id, self.status, self.statusMsg(), self.pressure) | 160 | 160 | return "Gauge #%d: Status %d (%s), Pressure: %f mbar\n" % (self.id, self.status, self.statusMsg(), self.pressure) | |
161 | 161 | |||
162 | 162 | |||
### ------ now we define the exceptions that could occur ------ | 163 | 163 | ### ------ now we define the exceptions that could occur ------ | |
164 | 164 | |||
class MaxiGaugeError(Exception): | 165 | 165 | class MaxiGaugeError(Exception): | |
pass | 166 | 166 | pass | |
167 | 167 | |||
class MaxiGaugeNAK(MaxiGaugeError): | 168 | 168 | class MaxiGaugeNAK(MaxiGaugeError): | |
pass | 169 | 169 | pass | |
170 | 170 | |||
### ------- Control Symbols as defined on p. 81 of the english | 171 | 171 | ### ------- Control Symbols as defined on p. 81 of the english | |
### manual for the Pfeiffer Vacuum TPG256A ----------- | 172 | 172 | ### manual for the Pfeiffer Vacuum TPG256A ----------- | |
C = { | 173 | 173 | C = { | |
'ETX': "\x03", # End of Text (Ctrl-C) Reset the interface | 174 | 174 | 'ETX': "\x03", # End of Text (Ctrl-C) Reset the interface | |
'CR': "\x0D", # Carriage Return Go to the beginning of line | 175 | 175 | 'CR': "\x0D", # Carriage Return Go to the beginning of line | |
'LF': "\x0A", # Line Feed Advance by one line | 176 | 176 | 'LF': "\x0A", # Line Feed Advance by one line | |
'ENQ': "\x05", # Enquiry Request for data transmission | 177 | 177 | 'ENQ': "\x05", # Enquiry Request for data transmission | |
'ACQ': "\x06", # Acknowledge Positive report signal | 178 | 178 | 'ACQ': "\x06", # Acknowledge Positive report signal | |
'NAK': "\x15", # Negative Acknowledge Negative report signal | 179 | 179 | 'NAK': "\x15", # Negative Acknowledge Negative report signal | |
'ESC': "\x1b", # Escape | 180 | 180 | 'ESC': "\x1b", # Escape | |
} | 181 | 181 | } | |
182 | 182 | |||
LINE_TERMINATION=C['CR']+C['LF'] # CR, LF and CRLF are all possible (p.82) | 183 | 183 | LINE_TERMINATION=C['CR']+C['LF'] # CR, LF and CRLF are all possible (p.82) | |
184 | 184 | |||
### Mnemonics as defined on p. 85 | 185 | 185 | ### Mnemonics as defined on p. 85 | |
M = [ | 186 | 186 | M = [ | |
'BAU', # Baud rate Baud rate 95 | 187 | 187 | 'BAU', # Baud rate Baud rate 95 | |
'CAx', # Calibration factor Sensor x Calibration factor sensor x (1 ... 6) 92 | 188 | 188 | 'CAx', # Calibration factor Sensor x Calibration factor sensor x (1 ... 6) 92 | |
'CID', # Measurement point names Measurement point names 88 | 189 | 189 | 'CID', # Measurement point names Measurement point names 88 | |
'DCB', # Display control Bargraph Bargraph 89 | 190 | 190 | 'DCB', # Display control Bargraph Bargraph 89 | |
'DCC', # Display control Contrast Display control contrast 90 | 191 | 191 | 'DCC', # Display control Contrast Display control contrast 90 | |
'DCD', # Display control Digits Display digits 88 | 192 | 192 | 'DCD', # Display control Digits Display digits 88 | |
'DCS', # Display control Screensave Display control screensave 90 | 193 | 193 | 'DCS', # Display control Screensave Display control screensave 90 | |
'DGS', # Degas Degas 93 | 194 | 194 | 'DGS', # Degas Degas 93 | |
'ERR', # Error Status Error status 97 | 195 | 195 | 'ERR', # Error Status Error status 97 | |
'FIL', # Filter time constant Filter time constant 92 | 196 | 196 | 'FIL', # Filter time constant Filter time constant 92 | |
'FSR', # Full scale range of linear sensors Full scale range of linear sensors 93 | 197 | 197 | 'FSR', # Full scale range of linear sensors Full scale range of linear sensors 93 | |
'LOC', # Parameter setup lock Parameter setup lock 91 | 198 | 198 | 'LOC', # Parameter setup lock Parameter setup lock 91 | |
'NAD', # Node (device) address for RS485 Node (device) address for RS485 96 | 199 | 199 | 'NAD', # Node (device) address for RS485 Node (device) address for RS485 96 | |
'OFC', # Offset correction Offset correction 93 | 200 | 200 | 'OFC', # Offset correction Offset correction 93 | |
'OFC', # Offset correction Offset correction 93 | 201 | 201 | 'OFC', # Offset correction Offset correction 93 | |
'PNR', # Program number Program number 98 | 202 | 202 | 'PNR', # Program number Program number 98 | |
'PRx', # Status, Pressure sensor x (1 ... 6) Status, Pressure sensor x (1 ... 6) 88 | 203 | 203 | 'PRx', # Status, Pressure sensor x (1 ... 6) Status, Pressure sensor x (1 ... 6) 88 | |
'PUC', # Underrange Ctrl Underrange control 91 | 204 | 204 | 'PUC', # Underrange Ctrl Underrange control 91 | |
'RSX', # Interface Interface 94 | 205 | 205 | 'RSX', # Interface Interface 94 | |
'SAV', # Save default Save default 94 | 206 | 206 | 'SAV', # Save default Save default 94 | |
'SCx', # Sensor control Sensor control 87 | 207 | 207 | 'SCx', # Sensor control Sensor control 87 | |
'SEN', # Sensor on/off Sensor on/off 86 | 208 | 208 | 'SEN', # Sensor on/off Sensor on/off 86 | |
'SPx', # Set Point Control Source for Relay xThreshold value setting, Allocation 90 | 209 | 209 | 'SPx', # Set Point Control Source for Relay xThreshold value setting, Allocation 90 | |
'SPS', # Set Point Status A,B,C,D,E,F Set point status 91 | 210 | 210 | 'SPS', # Set Point Status A,B,C,D,E,F Set point status 91 | |
'TAI', # Test program A/D Identify Test A/D converter identification inputs 100 | 211 | 211 | 'TAI', # Test program A/D Identify Test A/D converter identification inputs 100 | |
'TAS', # Test program A/D Sensor Test A/D converter measurement value inputs 100 | 212 | 212 | 'TAS', # Test program A/D Sensor Test A/D converter measurement value inputs 100 | |
'TDI', # Display test Display test 98 | 213 | 213 | 'TDI', # Display test Display test 98 | |
'TEE', # EEPROM test EEPROM test 100 | 214 | 214 | 'TEE', # EEPROM test EEPROM test 100 | |
'TEP', # EPROM test EPROM test 99 | 215 | 215 | 'TEP', # EPROM test EPROM test 99 | |
'TID', # Sensor identification Sensor identification 101 | 216 | 216 | 'TID', # Sensor identification Sensor identification 101 | |
'TKB', # Keyboard test Keyboard test 99 | 217 | 217 | 'TKB', # Keyboard test Keyboard test 99 | |
'TRA', # RAM test RAM test 99 | 218 | 218 | 'TRA', # RAM test RAM test 99 | |
'UNI', # Unit of measurement (Display) Unit of measurement (pressure) 89 | 219 | 219 | 'UNI', # Unit of measurement (Display) Unit of measurement (pressure) 89 | |
'WDT', # Watchdog and System Error Control Watchdog and system error control 101 | 220 | 220 | 'WDT', # Watchdog and System Error Control Watchdog and system error control 101 | |
] | 221 | 221 | ] | |
222 | 222 | |||
223 | 223 | |||
### Error codes as defined on p. 97 | 224 | 224 | ### Error codes as defined on p. 97 | |
ERR_CODES = [ | 225 | 225 | ERR_CODES = [ | |
{ | 226 | 226 | { | |
0: 'No error', | 227 | 227 | 0: 'No error', | |
1: 'Watchdog has responded', | 228 | 228 | 1: 'Watchdog has responded', |