Blame view

instruments/TPG261.py 9.16 KB
91efd0ebc   mer0m   Add files via upload
1
2
3
4
5
6
7
  from abstract_instrument import abstract_instrument
  import serial
  
  #==============================================================================
  
  ALL_VAL_TYPE = ['PRE']
  ALL_CHANNELS = ['1']
9058343c5   bmarechal   some minor fixes
8
  ADDRESS = "/dev/ttyS0"
91efd0ebc   mer0m   Add files via upload
9
10
11
12
  
  #==============================================================================
  
  class TPG261(abstract_instrument):
348049517   bmarechal   replace 4 spaces ...
13
14
15
16
  	def __init__(self, channels, vtypes, address):
  		self.address = address
  		self.channels = channels
  		self.vtypes = vtypes
91efd0ebc   mer0m   Add files via upload
17

348049517   bmarechal   replace 4 spaces ...
18
19
  	def model(self):
  		return "PfeifferTPG261"
91efd0ebc   mer0m   Add files via upload
20

348049517   bmarechal   replace 4 spaces ...
21
22
23
24
25
26
  	def connect(self):
  		print('Connecting to device @%s...' %(self.address))
  		self.TPG = MaxiGauge(self.address)
  		print('  --> Ok')
  		print(self.model())
  		self.configure()
bb6b08041   bmarechal   Add configure method
27

348049517   bmarechal   replace 4 spaces ...
28
29
  	def configure(self):
  		pass
91efd0ebc   mer0m   Add files via upload
30

348049517   bmarechal   replace 4 spaces ...
31
32
33
34
  	def getValue(self):
  		self.read()
  		return "%s
  "%self.ps[0].pressure
91efd0ebc   mer0m   Add files via upload
35

348049517   bmarechal   replace 4 spaces ...
36
37
  	def read(self):
  		self.ps = self.TPG.pressures()
91efd0ebc   mer0m   Add files via upload
38

348049517   bmarechal   replace 4 spaces ...
39
40
  	def disconnect(self):
  		self.TPG.disconnect()
91efd0ebc   mer0m   Add files via upload
41

348049517   bmarechal   replace 4 spaces ...
42
43
  	def send(self, command):
  		pass
91efd0ebc   mer0m   Add files via upload
44
45
46
47
48
49
50
  
  
  
  
  # from Philipp Klaus, philipp.l.klaus AT web.de PfeifferVacuum.py
  
  class MaxiGauge (object):
348049517   bmarechal   replace 4 spaces ...
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  	def __init__(self, serialPort, baud=9600, debug=False):
  		self.debug=debug
  		try:
  			self.connection = serial.Serial(serialPort, baudrate=baud, timeout=0.2)
  		except serial.serialutil.SerialException as se:
  			raise MaxiGaugeError(se)
  		#self.send(C['ETX']) ### We might reset the connection first, but it doesn't really matter:
  
  	def checkDevice(self):
  		message = "The Display Contrast is currently set to %d (out of 20).
  " % self.displayContrast()
  		message += "Keys since MaxiGauge was switched on: %s (out of 1,2,3,4,5).
  " % ", ".join( map (str, self.pressedKeys()) )
  		return message
  
  	def pressedKeys(self):
  		keys = int(self.send('TKB',1)[0])
  		pressedKeys = []
  		for i in [4,3,2,1,0]: # It's got 5 keys
  			if keys/2**i == 1:
  				pressedKeys.append(i+1)
  				keys = keys%2**i
  		pressedKeys.reverse()
  		return pressedKeys
  
  	def displayContrast(self,newContrast=-1):
  		if newContrast == -1: return int(self.send('DCC',1)[0])
  		else: return int(self.send('DCC,%d' % (newContrast,) ,1)[0])
  
  	def pressures(self):
  		return [self.pressure(i+1) for i in range(1)]
  
  	def pressure(self, sensor):
  		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)
  		try:
  			r = reading[0].split(',')
  			status = int(r[0])
  			pressure = float(r[-1])
  		except:
  			raise MaxiGaugeError("Problem interpreting the returned line:
  %s" % reading)
  		return PressureReading(sensor, status, pressure)
  
  	def debugMessage(self, message):
  		if self.debug: print(repr(message))
  
  	def send(self, mnemonic, numEnquiries = 0):
  		self.connection.flushInput()
  		self.write(mnemonic+LINE_TERMINATION)
  		#if mnemonic != C['ETX']: self.read()
  		#self.read()
  		self.getACQorNAK()
  		response = []
  		for i in range(numEnquiries):
  			self.enquire()
  			response.append(self.read())
  		return response
  
  	def write(self,what):
  		self.debugMessage(what)
  		self.connection.write(what)
  
  	def enquire(self):
  		self.write(C['ENQ'])
  
  	def read(self):
  		data = ""
  		while True:
  			x = self.connection.read()
  			self.debugMessage(x)
  			data += x
  			if len(data)>1 and data[-2:]==LINE_TERMINATION:
  				break
  		return data[:-len(LINE_TERMINATION)]
  
  	def getACQorNAK(self):
  		returncode = self.connection.readline()
  		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.
  		#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.')
  		if len(returncode)>2 and returncode[-3] == C['NAK']:
  			self.enquire()
  			returnedError = self.read()
  			error = str(returnedError).split(',' , 1)
  			print repr(error)
  			errmsg = { 'System Error': ERR_CODES[0][int(error[0])] , 'Gauge Error': ERR_CODES[1][int(error[1])] }
  			raise MaxiGaugeNAK(errmsg)
  		#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.')
  		# if no exception raised so far, the interface is just fine:
  		return returncode[:-(len(LINE_TERMINATION)+1)]
  
  	def disconnect(self):
  		#self.send(C['ETX'])
  		if hasattr(self, 'connection') and self.connection: self.connection.close()
  
  	def __del__(self):
  		self.disconnect()
91efd0ebc   mer0m   Add files via upload
151
152
  
  class PressureReading(object):
348049517   bmarechal   replace 4 spaces ...
153
154
155
156
157
158
  	def __init__(self, id, status, pressure):
  		if int(id) not in range(1,7): raise MaxiGaugeError('Pressure Gauge ID must be between 1-6')
  		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())
  		self.status = int(status)
  		self.pressure = float(pressure)
91efd0ebc   mer0m   Add files via upload
159

348049517   bmarechal   replace 4 spaces ...
160
161
  	def statusMsg(self):
  		return PRESSURE_READING_STATUS[self.status]
91efd0ebc   mer0m   Add files via upload
162

348049517   bmarechal   replace 4 spaces ...
163
164
165
  	def __repr__(self):
  		return "Gauge #%d: Status %d (%s), Pressure: %f mbar
  " % (self.id, self.status, self.statusMsg(), self.pressure)
91efd0ebc   mer0m   Add files via upload
166
167
168
169
170
  
  
  ### ------ now we define the exceptions that could occur ------
  
  class MaxiGaugeError(Exception):
348049517   bmarechal   replace 4 spaces ...
171
  	pass
91efd0ebc   mer0m   Add files via upload
172
173
  
  class MaxiGaugeNAK(MaxiGaugeError):
348049517   bmarechal   replace 4 spaces ...
174
  	pass
91efd0ebc   mer0m   Add files via upload
175
176
  
  ### ------- Control Symbols as defined on p. 81 of the english
348049517   bmarechal   replace 4 spaces ...
177
  ###		manual for the Pfeiffer Vacuum TPG256A  -----------
91efd0ebc   mer0m   Add files via upload
178
179
  C = {
    'ETX': "\x03", # End of Text (Ctrl-C)   Reset the interface
348049517   bmarechal   replace 4 spaces ...
180
181
182
183
    'CR':  "\x0D", # Carriage Return		Go to the beginning of line
    'LF':  "\x0A", # Line Feed			  Advance by one line
    'ENQ': "\x05", # Enquiry				Request for data transmission
    'ACQ': "\x06", # Acknowledge			Positive report signal
91efd0ebc   mer0m   Add files via upload
184
185
186
187
188
189
190
191
    'NAK': "\x15", # Negative Acknowledge   Negative report signal
    'ESC': "\x1b", # Escape
  }
  
  LINE_TERMINATION=C['CR']+C['LF'] # CR, LF and CRLF are all possible (p.82)
  
  ### Mnemonics as defined on p. 85
  M = [
348049517   bmarechal   replace 4 spaces ...
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
    'BAU', # Baud rate						   Baud rate									95
    'CAx', # Calibration factor Sensor x		 Calibration factor sensor x (1 ... 6)		92
    'CID', # Measurement point names			 Measurement point names					  88
    'DCB', # Display control Bargraph			Bargraph									 89
    'DCC', # Display control Contrast			Display control contrast					 90
    'DCD', # Display control Digits			  Display digits							   88
    'DCS', # Display control Screensave		  Display control screensave				   90
    'DGS', # Degas							   Degas										93
    'ERR', # Error Status						Error status								 97
    'FIL', # Filter time constant				Filter time constant						 92
    'FSR', # Full scale range of linear sensors  Full scale range of linear sensors		   93
    'LOC', # Parameter setup lock				Parameter setup lock						 91
    'NAD', # Node (device) address for RS485	 Node (device) address for RS485			  96
    'OFC', # Offset correction				   Offset correction							93
    'OFC', # Offset correction				   Offset correction							93
    'PNR', # Program number					  Program number							   98
    'PRx', # Status, Pressure sensor x (1 ... 6) Status, Pressure sensor x (1 ... 6)		  88
    'PUC', # Underrange Ctrl					 Underrange control						   91
    'RSX', # Interface						   Interface									94
    'SAV', # Save default						Save default								 94
    'SCx', # Sensor control					  Sensor control							   87
    'SEN', # Sensor on/off					   Sensor on/off								86
    '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
    '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
    'TDI', # Display test						Display test								 98
    'TEE', # EEPROM test						 EEPROM test								 100
    'TEP', # EPROM test						  EPROM test								   99
    'TID', # Sensor identification			   Sensor identification					   101
    'TKB', # Keyboard test					   Keyboard test								99
    'TRA', # RAM test							RAM test									 99
    'UNI', # Unit of measurement (Display)	   Unit of measurement (pressure)			   89
    'WDT', # Watchdog and System Error Control   Watchdog and system error control		   101
91efd0ebc   mer0m   Add files via upload
226
227
228
229
230
231
  ]
  
  
  ### Error codes as defined on p. 97
  ERR_CODES = [
    {
348049517   bmarechal   replace 4 spaces ...
232
233
234
235
236
237
238
239
240
241
242
243
244
  		0: 'No error',
  		1: 'Watchdog has responded',
  		2: 'Task fail error',
  		4: 'IDCX idle error',
  		8: 'Stack overflow error',
  	   16: 'EPROM error',
  	   32: 'RAM error',
  	   64: 'EEPROM error',
  	  128: 'Key error',
  	 4096: 'Syntax error',
  	 8192: 'Inadmissible parameter',
  	16384: 'No hardware',
  	32768: 'Fatal error'
91efd0ebc   mer0m   Add files via upload
245
246
    } ,
    {
348049517   bmarechal   replace 4 spaces ...
247
248
249
250
251
252
253
254
255
256
257
258
259
  		0: 'No error',
  		1: 'Sensor 1: Measurement error',
  		2: 'Sensor 2: Measurement error',
  		4: 'Sensor 3: Measurement error',
  		8: 'Sensor 4: Measurement error',
  	   16: 'Sensor 5: Measurement error',
  	   32: 'Sensor 6: Measurement error',
  	  512: 'Sensor 1: Identification error',
  	 1024: 'Sensor 2: Identification error',
  	 2048: 'Sensor 3: Identification error',
  	 4096: 'Sensor 4: Identification error',
  	 8192: 'Sensor 5: Identification error',
  	16384: 'Sensor 6: Identification error',
91efd0ebc   mer0m   Add files via upload
260
261
262
263
264
265
266
267
268
269
270
271
272
    }
  ]
  
  ### pressure status as defined on p.88
  PRESSURE_READING_STATUS = {
    0: 'Measurement data okay',
    1: 'Underrange',
    2: 'Overrange',
    3: 'Sensor error',
    4: 'Sensor off',
    5: 'No sensor',
    6: 'Identification error'
  }