quarchCalibration 1.1.26__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. quarchCalibration/BK9832B.py +627 -0
  2. quarchCalibration/Docs/CHANGES.rst +113 -0
  3. quarchCalibration/Docs/Makefile +20 -0
  4. quarchCalibration/Docs/__init__.py +0 -0
  5. quarchCalibration/Docs/_build/doctrees/CHANGES.doctree +0 -0
  6. quarchCalibration/Docs/_build/doctrees/environment.pickle +0 -0
  7. quarchCalibration/Docs/_build/doctrees/readme.doctree +0 -0
  8. quarchCalibration/Docs/_build/doctrees/source/changelog.doctree +0 -0
  9. quarchCalibration/Docs/_build/html/.buildinfo +4 -0
  10. quarchCalibration/Docs/_build/html/CHANGES.html +198 -0
  11. quarchCalibration/Docs/_build/html/_sources/CHANGES.rst.txt +75 -0
  12. quarchCalibration/Docs/_build/html/_sources/readme.rst.txt +38 -0
  13. quarchCalibration/Docs/_build/html/_sources/source/changelog.rst.txt +1 -0
  14. quarchCalibration/Docs/_build/html/_static/alabaster.css +703 -0
  15. quarchCalibration/Docs/_build/html/_static/basic.css +925 -0
  16. quarchCalibration/Docs/_build/html/_static/custom.css +1 -0
  17. quarchCalibration/Docs/_build/html/_static/doctools.js +156 -0
  18. quarchCalibration/Docs/_build/html/_static/documentation_options.js +13 -0
  19. quarchCalibration/Docs/_build/html/_static/file.png +0 -0
  20. quarchCalibration/Docs/_build/html/_static/language_data.js +199 -0
  21. quarchCalibration/Docs/_build/html/_static/minus.png +0 -0
  22. quarchCalibration/Docs/_build/html/_static/plus.png +0 -0
  23. quarchCalibration/Docs/_build/html/_static/pygments.css +83 -0
  24. quarchCalibration/Docs/_build/html/_static/searchtools.js +574 -0
  25. quarchCalibration/Docs/_build/html/_static/sphinx_highlight.js +154 -0
  26. quarchCalibration/Docs/_build/html/genindex.html +98 -0
  27. quarchCalibration/Docs/_build/html/objects.inv +6 -0
  28. quarchCalibration/Docs/_build/html/readme.html +128 -0
  29. quarchCalibration/Docs/_build/html/search.html +117 -0
  30. quarchCalibration/Docs/_build/html/searchindex.js +1 -0
  31. quarchCalibration/Docs/_build/html/source/changelog.html +198 -0
  32. quarchCalibration/Docs/conf.py +59 -0
  33. quarchCalibration/Docs/make.bat +35 -0
  34. quarchCalibration/Docs/readme.rst +38 -0
  35. quarchCalibration/Docs/source/changelog.rst +1 -0
  36. quarchCalibration/ET2260.py +209 -0
  37. quarchCalibration/Keithley_DMM6500_control.py +623 -0
  38. quarchCalibration/Keysight_AC6804B_control.py +623 -0
  39. quarchCalibration/PowerModuleCalibration.py +607 -0
  40. quarchCalibration/QTL1944_06_hd_plus_ppm.py +1858 -0
  41. quarchCalibration/QTL1944_hd_ppm.py +1756 -0
  42. quarchCalibration/QTL2347_pcie.py +1157 -0
  43. quarchCalibration/QTL2525_sff.py +948 -0
  44. quarchCalibration/QTL2536_6_way_switchbox.py +101 -0
  45. quarchCalibration/QTL2582_3ph_ac.py +1046 -0
  46. quarchCalibration/QTL2621_2ch_mezz.py +961 -0
  47. quarchCalibration/QTL2626_4ch_mezz.py +783 -0
  48. quarchCalibration/QTL2628_ext_mezz_dimm.py +796 -0
  49. quarchCalibration/QTL2631_ext_mezz.py +771 -0
  50. quarchCalibration/QTL2631_pcie.py +802 -0
  51. quarchCalibration/QTL2673_edsff.py +855 -0
  52. quarchCalibration/QTL2843_iec_ac.py +1052 -0
  53. quarchCalibration/QTL3216_pcie.py +1061 -0
  54. quarchCalibration/__init__.py +10 -0
  55. quarchCalibration/__main__.py +3 -0
  56. quarchCalibration/_version.py +1 -0
  57. quarchCalibration/acHelpers.py +183 -0
  58. quarchCalibration/ac_pam.py +1156 -0
  59. quarchCalibration/calibrationConfig.py +27 -0
  60. quarchCalibration/calibrationUtil.py +533 -0
  61. quarchCalibration/deviceHelpers.py +125 -0
  62. quarchCalibration/elpaSine.py +456 -0
  63. quarchCalibration/keithley_2460_control.py +972 -0
  64. quarchCalibration/pamCommon.py +554 -0
  65. quarchCalibration/pamHelpers.py +36 -0
  66. quarchCalibration/threePhaseSwitchBox.py +218 -0
  67. quarchcalibration-1.1.26.dist-info/METADATA +143 -0
  68. quarchcalibration-1.1.26.dist-info/RECORD +70 -0
  69. quarchcalibration-1.1.26.dist-info/WHEEL +5 -0
  70. quarchcalibration-1.1.26.dist-info/top_level.txt +1 -0
@@ -0,0 +1,627 @@
1
+ #import telnetlib
2
+ import socket
3
+ import time
4
+ import logging,os
5
+ import sys
6
+ from quarchCalibration.deviceHelpers import locateMdnsInstr
7
+ from quarchpy.user_interface import *
8
+
9
+
10
+ #'''
11
+ #Prints out a list of calibration instruments nicely onto the terminal, numbering each unit
12
+ #'''
13
+ #def listCalInstruments(scanDictionary):
14
+ # if (not scanDictionary):
15
+ # print ("No instruments found to display")
16
+ # else:
17
+ # x = 1
18
+ # for k, v in scanDictionary.items():
19
+ # # these items should all be Keithley 2460 SMUs
20
+ # # form of the value is 'Keithley 2460 #04412428._http._tcp.local.'
21
+ # # we want to extract name, serial number and ip address
22
+ # ip = k
23
+ # # if we recognise the device, pull out Keithley serial number
24
+ # if "Keithley 2460 " in v[:14]: # currently we don't get here without this being true, but that may not be the case in future
25
+ # id = v[:14] + "\t" + v[14:].split(".")[0] # ignore the name we've just matched, and take everything up to the first '.' this should be the serial number
26
+ # else:
27
+ # id = v # else we don't recognise the device, return the whole identifier unmodified
28
+ # print (str(x) + " - " + id + "\t" + ip)
29
+ # x += 1
30
+
31
+ #'''
32
+ #Allows the user to select a test instrument
33
+ #'''
34
+ #def userSelectCalInstrument(scanDictionary=None, scanFilterStr="2460", title=None, message=None, tableHeaders= None, additionalOptions = None, nice=False):
35
+ # #Initiate values. Originals must be stored for the case of a rescan.
36
+ # originalOptions = additionalOptions
37
+ # if User_interface.instance != None and User_interface.instance.selectedInterface == "testcenter":
38
+ # nice = False
39
+ # if message is None: message = "Select the calibration instrument to use:"
40
+ # if title is None: title = "Select a calibration instrument"
41
+ # while(True): #breaks when valid user input given
42
+ # # Scan first, if no list is supplied
43
+ # if (scanDictionary is None):
44
+ # printText ("Scanning for instruments...")
45
+ # scanDictionary = foundDevices = locateMdnsInstr(scanFilterStr)
46
+
47
+ # deviceList = []
48
+
49
+ # if nice: #prep data for nice list selection,
50
+ # if additionalOptions is None: additionalOptions = ["Rescan", "Quit"]
51
+ # if (not scanDictionary):
52
+ # deviceList.append(["No instruments found to display"])
53
+ # else:
54
+ # for k, v in scanDictionary.items():
55
+ # # these items should all be Keithley 2460 SMUs
56
+ # # form of the value is 'Keithley 2460 #04412428._http._tcp.local.'
57
+ # # we want to extract name, serial number and ip address
58
+ # ip = k
59
+ # # if we recognise the device, pull out Keithley serial number
60
+ # if "Keithley 2460 " in v[:14]: # currently we don't get here without this being true, but that may not be the case in future
61
+ # name =v[:14]
62
+ # serialNo = v[14:].split(".")[0]
63
+ # deviceList.append([name,serialNo,ip])
64
+ # else:
65
+ # id = v # else we don't recognise the device, return the whole identifier unmodified
66
+ # deviceList.append([ip + "=" + id + " " + ip])
67
+ # adOp = []
68
+ # for option in additionalOptions:
69
+ # adOp.append([option]*3)
70
+ # userStr = listSelection(title=title, message=message, selectionList=deviceList, tableHeaders=["Name","Serial","IP Address"], nice=nice, indexReq=True, additionalOptions=adOp)[3] #Address will allways be 3 in this format
71
+
72
+
73
+ # else: #Prep data for test center
74
+ # if (not scanDictionary):
75
+ # deviceList.append("1=No instruments found to display")
76
+ # else:
77
+
78
+ # x = 1
79
+ # for k, v in scanDictionary.items():
80
+ # # these items should all be Keithley 2460 SMUs
81
+ # # form of the value is 'Keithley 2460 #04412428._http._tcp.local.'
82
+ # # we want to extract name, serial number and ip address
83
+ # ip = k
84
+ # # if we recognise the device, pull out Keithley serial number
85
+ # if "Keithley 2460 " in v[:14]: # currently we don't get here without this being true, but that may not be the case in future
86
+ # id = v[:14] + "\t" + v[14:].split(".")[0] # ignore the name we've just matched, and take everything up to the first '.' this should be the serial number
87
+ # else:
88
+ # id = v # else we don't recognise the device, return the whole identifier unmodified
89
+ # deviceList.append(ip + "=" + id + "\t" + ip)
90
+ # x += 1
91
+ # if additionalOptions is None:
92
+ # additionalOptions = "Rescan=Rescan,Quit=Quit"
93
+ # deviceList = ",".join(deviceList)
94
+ # userStr = listSelection(title=title,message=message,selectionList=deviceList, additionalOptions=additionalOptions)
95
+
96
+
97
+
98
+ # # Process the user response
99
+ # if (userStr == 'q' or userStr.lower() in "quit"):
100
+ # return "quit"
101
+ # elif (userStr == 'r' or userStr.lower() in "rescan"):
102
+ # scanDictionary = None
103
+ # additionalOptions = originalOptions
104
+ # else:
105
+ # # Return the address string of the selected instrument
106
+ # return userStr
107
+
108
+ '''
109
+ Class for control of BK Precision 9832B AC Power Source for calibration purposes
110
+ '''
111
+ class BK9832B:
112
+
113
+ '''
114
+ Init the class
115
+ '''
116
+ def __init__(self, connectionString):
117
+ self.conString = connectionString
118
+ self.connection = None
119
+ self.idnString = "B&K PRECISION,9832B,"
120
+ self.BUFFER_SIZE = 1024
121
+ self.TIMEOUT = 120 #Changed to allow AIC calibration due to delay of meas:curr? when calibrating leakage.
122
+
123
+ '''
124
+ Open the connection to the instrument
125
+ '''
126
+ def openConnection (self, connectionString = None):
127
+ # Connect TCP
128
+ if (connectionString is not None):
129
+ self.conString = connectionString
130
+ self.connection = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
131
+ self.connection.settimeout(self.TIMEOUT)
132
+ logging.debug(os.path.basename(__file__) + ": opening connection: " + self.conString)
133
+ self.connection.connect((self.conString,5025))
134
+ # Clear errors, set to default state
135
+ response = self.sendCommand ("*RST") # The BK9832B does not list a *RST command, but it does not complain and this still clears the input buffer. it doesn't list *IDN? either but that works
136
+ # Send the IDN? command
137
+ response = self.sendCommandQuery ("*IDN?")
138
+ # Verify this looks like the expected instrument
139
+ if (response.find (self.idnString) == -1):
140
+ raise ValueError ("Connected device does not appear to be a BK9832B")
141
+
142
+ '''
143
+ Close the connection to the instrument
144
+ '''
145
+ def closeConnection (self):
146
+ logging.debug(os.path.basename(__file__) + ": closing connection to BK9832B ")
147
+ self.connection.close()
148
+
149
+ '''
150
+ Attempts to force close any existing (LAN) socket connections
151
+ '''
152
+ def closeDeadConnections (self):
153
+ deadSocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
154
+ deadSocket.settimeout(self.TIMEOUT)
155
+ deadSocket.connect((self.conString,5030))
156
+ deadSocket.close()
157
+
158
+
159
+ '''
160
+ Send a command to the instrument and return the response from the query
161
+ This should only be used for commands which expect a response
162
+ '''
163
+ def sendCommandQuery (self, commandString):
164
+ self.openConnection()
165
+ retries = 1
166
+ while retries < 5:
167
+ try:
168
+ # Send the command
169
+ startTime= int(round(time.time() * 1000))
170
+ logging.debug(os.path.basename(__file__) + ": sending command: " + commandString)
171
+ self.connection.send((commandString + "\r\n").encode('latin-1'))
172
+ # Read back the response data
173
+ resultStr = self.connection.recv(self.BUFFER_SIZE).decode("utf-8")
174
+ endTime = int(round(time.time() * 1000))
175
+ logging.debug(os.path.basename(__file__) + ": received: " + resultStr)
176
+ logging.debug(os.path.basename(__file__) + ": Time Taken : " + str(endTime-startTime) + " mS")
177
+ resultStr = resultStr.strip ('\r\n\t')
178
+ # If no response came back
179
+ if (resultStr is None or resultStr == ""):
180
+ raise ValueError ("The BK9832B did not return a response")
181
+ return resultStr
182
+ except socket.timeout:
183
+ logging.debug(os.path.basename(__file__) + ": BK9832B command timed out: " + commandString + ", closing connection and retrying")
184
+ # reset connections to BK9832B
185
+ self.closeDeadConnections()
186
+ # reopen connection to BK9832B
187
+ self.connection = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
188
+ self.connection.settimeout(self.TIMEOUT)
189
+ self.connection.connect((self.conString,5025))
190
+ # increment retry counter
191
+ retries = retries + 1
192
+ raise TimeoutError (os.path.basename(__file__) + ": timed out while expecting a response")
193
+
194
+
195
+ '''
196
+ Sends a command to the instrument where a response is not expected.
197
+ Status byte check is used to verify that the command does not flag an error
198
+ If an error is found, it will be flushed and the first error text returned
199
+ 'OK' is returned on success
200
+ '''
201
+ def sendCommand (self, commandString, expectedResponse = True):
202
+ retries = 1
203
+ while retries < 5:
204
+ try:
205
+ # Send the command
206
+ logging.debug(os.path.basename(__file__) + ": sending command: " + commandString)
207
+ self.connection.send((commandString + "\r\n").encode('latin-1'))
208
+ return "OK"
209
+ except socket.timeout:
210
+ logging.debug(os.path.basename(__file__) + ": BK9832B command timed out: " + commandString + ", closing connection and retrying")
211
+ # reset connections to BK9832B
212
+ self.closeDeadConnections()
213
+ # reopen connection to BK9832B
214
+ self.connection = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
215
+ self.connection.settimeout(self.TIMEOUT)
216
+ self.connection.connect((self.conString,5025))
217
+ # increment retry counter
218
+ retries = retries + 1
219
+ raise TimeoutError (os.path.basename(__file__) + ": timed out while sending command to BK9832B")
220
+
221
+ '''
222
+ Reset the instrument
223
+ '''
224
+ def reset (self):
225
+ result = self.sendCommand("*RST")
226
+ return result
227
+
228
+ '''
229
+ Enable/disable the outputs
230
+ '''
231
+ def setOutputEnable (self, enableState):
232
+ if (enableState == True):
233
+ result = self.sendCommand("OUTP ON")
234
+ else:
235
+ result = self.sendCommand("OUTP OFF")
236
+
237
+ return result
238
+
239
+ '''
240
+ Return the output enable state as a boolean
241
+ '''
242
+ def getOutputEnable (self):
243
+ result = self.sendCommandQuery ("OUTP?")
244
+ if (result == "ON"):
245
+ return True
246
+ elif (result == "OFF"):
247
+ return False
248
+ else:
249
+ raise ValueError("Unexpected response received: " + result)
250
+
251
+ '''
252
+ Set the output AC voltage limit, in volts
253
+ This limit applies to AC and AC+DC modes and limits based on the RMS output voltage.
254
+ voltValue should be a float, max value 306.0
255
+ '''
256
+ def setACVoltageLimit (self, voltValue):
257
+ try:
258
+ if float(voltValue) < 0 or float(voltValue) > 310:
259
+ raise ValueError("invalid voltage supplied to setACVoltageLimit, must be a float in range 0 to 306.0")
260
+ else:
261
+ return self.sendCommand("OUTP:LIM:VOLT:AC " + str(float(voltValue)))
262
+ except:
263
+ raise ValueError("invalid voltage supplied to setACVoltageLimit, must be a float in range 0 to 306.0")
264
+
265
+ '''
266
+ Return the ouput AC voltage limit in volts
267
+ '''
268
+ def getACVoltageLimit (self):
269
+ result = self.sendCommandQuery ("OUTP:LIM:VOLT:AC?")
270
+ return float(result)
271
+
272
+ '''
273
+ Set the upper DC voltage limit, in volts
274
+ This limit applies to AC and AC+DC modes and limits based on the RMS output voltage.
275
+ voltValue should be a float, value 0 - 427.0
276
+ '''
277
+ def setUpperDCVoltageLimit (self, voltValue):
278
+ try:
279
+ if float(voltValue) < 0 or float(voltValue) > 427:
280
+ raise ValueError("invalid voltage supplied to setUpperDCVoltageLimit, must be a float in range 0 to 427.0")
281
+ else:
282
+ return self.sendCommand("OUTP:LIM:VOLT:DC:POS " + str(float(voltValue)))
283
+ except:
284
+ raise ValueError("invalid voltage supplied to setUpperDCVoltageLimit, must be a float in range 0 to 427.0")
285
+
286
+ '''
287
+ Return the upper DC voltage limit in volts
288
+ '''
289
+ def getUpperDCVoltageLimit (self):
290
+ result = self.sendCommandQuery ("OUTP:LIM:VOLT:DC:POS?")
291
+ return float(result)
292
+
293
+ '''
294
+ Set the lower DC voltage limit, in volts
295
+ This limit applies to AC and AC+DC modes and limits based on the RMS output voltage.
296
+ voltValue should be a float, value -427.0 - 0
297
+ '''
298
+ def setLowerDCVoltageLimit (self, voltValue):
299
+ try:
300
+ if float(voltValue) < -427 or float(voltValue) > 0:
301
+ raise ValueError("invalid voltage supplied to setLowerDCVoltageLimit, must be a float in range 0 to 427.0")
302
+ else:
303
+ return self.sendCommand("OUTP:LIM:VOLT:DC:NEG " + str(float(voltValue)))
304
+ except:
305
+ raise ValueError("invalid voltage supplied to setLowerDCVoltageLimit, must be a float in range 0 to 427.0")
306
+
307
+ '''
308
+ Return the lower DC voltage limit in volts
309
+ '''
310
+ def getLowerDCVoltageLimit (self):
311
+ result = self.sendCommandQuery ("OUTP:LIM:VOLT:DC:NEG?")
312
+ return float(result)
313
+
314
+ '''
315
+ Switch the output mode
316
+ Set the waveform operation to output.
317
+ '''
318
+ def setOutputMode (self, modeString):
319
+ modeString = modeString.upper()
320
+ # validate modestring
321
+ if modeString in ["NORMAL","STEP","LIST","PULSE"]:
322
+ # set the mode
323
+ return self.sendCommand("OUTP:MOD " + modeString)
324
+ else:
325
+ raise ValueError ("Invalid mode type specified: " + modeString)
326
+
327
+ '''
328
+ Return the output mode
329
+ query the waveform operation to output
330
+ '''
331
+ def getOutputMode (self):
332
+ return self.sendCommandQuery("OUTP:MOD?");
333
+
334
+ #'''
335
+ #Changes the instrument into the specified measurement mode
336
+ #'''
337
+ #def setMeasurementMode (self, measModeString):
338
+ # measModeString = measModeString.upper()
339
+ # if (measModeString == "VOLT"):
340
+ # result = self.sendCommand("SENS:FUNC \"VOLT\"")
341
+ # elif (measModeString == "CURR"):
342
+ # result = self.sendCommand("SENS:FUNC \"CURR\"")
343
+ # else:
344
+ # raise ValueError ("Invalid mode type specified: " + measModeString)
345
+
346
+ # return result
347
+
348
+ #'''
349
+ #Return the current measurement mode as a string
350
+ #'''
351
+ #def getMeasurementMode (self):
352
+ # return self.sendCommandQuery("SENS:FUNC?").strip('\"')
353
+
354
+ #'''
355
+ #Changes the instrument into the specified source/output mode
356
+ #'''
357
+ #def setSourceMode (self, sourceModeString):
358
+ # sourceModeString = sourceModeString.upper()
359
+ # if sourceModeString in ["VOLT","CURR"]:
360
+ # result = self.sendCommand("SOUR:FUNC " + sourceModeString)
361
+ # else:
362
+ # raise ValueError ("Invalid mode type specified: " + sourceModeString)
363
+ # return result
364
+
365
+ #'''
366
+ #Return the source mode, as a string
367
+ #'''
368
+ #def getSourceMode (self):
369
+ # return self.sendCommandQuery("SOUR:FUNC?")
370
+
371
+ #'''
372
+ #Sets the number of measurements to be averaged together to return one voltage measurement
373
+ #'''
374
+ #def setAverageVoltageCount (self, measCount=1):
375
+ # self.sendCommand("VOLT:AVER:COUNT " + str(measCount))
376
+ # self.sendCommand("VOLT:AVER ON")
377
+
378
+ #'''
379
+ #Sets the number of measurements to be averaged together to return one current measurement
380
+ #'''
381
+ #def setAverageCurrentCount (self, measCount=1):
382
+ # self.sendCommand("CURR:AVER:COUNT " + str(measCount))
383
+ # self.sendCommand("CURR:AVER ON")
384
+
385
+ #'''
386
+ #Set the load/drain current to supply
387
+ #'''
388
+ #def setLoadCurrent (self, ampValue):
389
+ # #load current should always be negative
390
+ # if (ampValue <= 0):
391
+ # ampValue = -ampValue
392
+
393
+ # # set source current
394
+ # return self.sendCommand("SOUR:CURR -" + str(ampValue));
395
+
396
+
397
+ #'''
398
+ #Set the load/drain current range
399
+ #'''
400
+ #def setLoadCurrentRange(self, ampValue):
401
+ # # load current should always be negative
402
+ # if (ampValue <= 0):
403
+ # ampValue = -ampValue
404
+ # # set source current range
405
+ # val = self.sendCommand("SOUR:CURR:RANG " + str(ampValue));
406
+ # return val
407
+
408
+ #'''
409
+ #Set the load/drain current range to auto
410
+ #'''
411
+ #def setLoadCurrentRangeAuto(self):
412
+ # # set source current range to auto
413
+ # val = self.sendCommand("SOUR:CURR:RANG:AUTO ON");
414
+ # return val
415
+
416
+ #'''
417
+ #Sets the limit for the load current in Amps
418
+ #'''
419
+ #def setLoadCurrentLimit (self, ampValue):
420
+ # return self.sendCommand("SOUR:VOLT:ILIM " + str(ampValue));
421
+
422
+ #'''
423
+ #Gets the limit for the load current in Amps (float)
424
+ #'''
425
+ #def getLoadCurrentLimit (self):
426
+ # return self.sendCommandQuery("SOUR:VOLT:ILIM?");
427
+
428
+
429
+ #'''
430
+ #Gets the current load current, as set
431
+ #'''
432
+ #def getLoadCurrent (self):
433
+ # result = float((self.sendCommandQuery("SOUR:CURR?")))
434
+ # return -result
435
+
436
+ '''
437
+ Measures and returns a current value
438
+ '''
439
+ def measureACCurrent (self):
440
+ result = float((self.sendCommandQuery("MEAS:CURR:AC?")))
441
+ return result
442
+
443
+
444
+ '''
445
+ Sets the AC voltage range high or low
446
+ '''
447
+ def setACRange (self, range):
448
+ if str(range).upper() in ["HIGH","LOW"]:
449
+ return self.sendCommand("SOUR:VOLT:RANG " + str(range).upper())
450
+ else:
451
+ raise ValueError("invalid range supplied to setACRange")
452
+
453
+ '''
454
+ Gets the AC range
455
+ '''
456
+ def getACRange (self):
457
+ result = self.sendCommandQuery("SOUR:VOLT:RANG?")
458
+ return result
459
+
460
+ '''
461
+ Sets the AC output voltage in Volts
462
+ '''
463
+ def setACVoltage (self, voltValue):
464
+ try:
465
+ range = self.sendCommandQuery("SOUR:VOLT:RANG?")
466
+ if (range == "HIGH" and (float(voltValue) < 0 or float(voltValue) > 300)) or (range == "LOW" and (float(voltValue) < 0 or float(voltValue) > 150)):
467
+ raise ValueError("voltage parameter to setACVoltage is outside of the availabe range")
468
+ else:
469
+ return self.sendCommand("SOUR:VOLT:AC " + str(voltValue))
470
+ except:
471
+ raise ValueError("voltage parameter to setACVoltage is out of range: " + voltValue)
472
+
473
+
474
+ '''
475
+ Gets the AC ouput voltage value
476
+ '''
477
+ def getACVoltage (self):
478
+ result = float((self.sendCommandQuery("SOUR:VOLT:AC?")))
479
+ return result
480
+
481
+ '''
482
+ Measures the current load voltage value
483
+ '''
484
+ def measureACVoltage (self):
485
+ result = float(self.sendCommandQuery("MEAS:VOLT:AC?"))
486
+ return result
487
+
488
+ #'''
489
+ #Returns the status byte from the instrument (the result of the *STB? command)
490
+ #This is used to tell if the module is ready or has errored
491
+ #'''
492
+ #def getStatusByte (self, retries=4):
493
+ # tryCount = 0
494
+ # while tryCount <= retries:
495
+ # tryCount +=1
496
+ # # Read status byte
497
+ # resultStr = self.sendCommandQuery ("*STB?")
498
+ # # If we get junk, try again
499
+ # try:
500
+ # statInt = int(resultStr)
501
+ # return statInt
502
+ # except:
503
+ # logging.debug("BK9832B is not responding with valid data retry " + str(tryCount))
504
+
505
+ # #If we have reached here we have excepet on every try and should raise a value error
506
+ # logging.error("BK9832B is not responding with valid data : " + str(resultStr))
507
+ # raise ValueError ("BK9832B is not responding with valid data")
508
+
509
+ #def printInstrumentStatus (self):
510
+ # stat = self.getStatusByte ()
511
+ # if (stat&1 != 0):
512
+ # print ("Measurement Summary Flag Set")
513
+ # if (stat&2 != 0):
514
+ # print ("Reserved Flag 1 Set")
515
+ # if (stat&4 != 0):
516
+ # print ("Error Available Flag Set")
517
+ # if (stat&8 != 0):
518
+ # print ("Questionable Event Flag Set")
519
+ # if (stat&16 != 0):
520
+ # print ("Message Available Flag Set")
521
+ # if (stat&32 != 0):
522
+ # print ("Enabled Standard Event Flag Set")
523
+ # if (stat&64 != 0):
524
+ # print ("Enabled Summary Bit Flag Set")
525
+ # if (stat&128 != 0):
526
+ # print ("Enabled Operation event Flag Set")
527
+ # if (stat == 0):
528
+ # print ("Status flags are clear")
529
+
530
+ #'''
531
+ #Returns the Measurement Summary Bit of the status information
532
+ #'''
533
+ #def getStatusMsbFlag (self):
534
+ # stat = self.getStatusByte ()
535
+ # # Meas bit is LSb
536
+ # if (stat&1 != 0):
537
+ # return True
538
+ # else:
539
+ # return False;
540
+
541
+ #'''
542
+ #Returns the Question Summary Bit of the status information
543
+ #'''
544
+ #def getStatusQsbFlag (self):
545
+ # stat = self.getStatusByte ()
546
+ # # Meas bit is LSb
547
+ # if (stat&8 != 0):
548
+ # return True
549
+ # else:
550
+ # return False;
551
+
552
+ #'''
553
+ #Returns the Error Available Bit of the status information
554
+ #'''
555
+ #def getStatusEavFlag (self):
556
+ # stat = self.getStatusByte ()
557
+ # # Meas bit is LSb
558
+ # if (stat&4 != 0):
559
+ # return True
560
+ # else:
561
+ # return False;
562
+
563
+ #'''
564
+ #Gets the next error from the instrument in a nice text form
565
+ #'''
566
+ #def getNextError (self):
567
+ # errorStr = self.sendCommandQuery ("SYSTem:ERRor:NEXT?")
568
+ # return errorStr
569
+
570
+ #'''
571
+ #Clears all errors from the queue, so the status EAV flag is cleared
572
+ #'''
573
+ #def clearErrors (self):
574
+ # self.sendCommand (":SYSTem:CLEar")
575
+ # #loop = 0
576
+ # # Loop through and flush our all current errors
577
+ # #while (self.getStatusEavFlag () == True and loop < 10):
578
+ # # print (self.getNextError ())
579
+ # # loop += 1
580
+
581
+ #'''
582
+ #Sets the instrument to zero load current and returns the voltage
583
+ #Move to generic class?
584
+ #'''
585
+ #def measureNoLoadVoltage (self):
586
+ # self.setOutputEnable(False)
587
+ # self.setSourceMode("CURR")
588
+ # self.setLoadCurrent(0)
589
+ # self.setLoadVoltageLimit(15)
590
+ # self.setOutputEnable(True)
591
+ # return self.measureLoadVoltage()
592
+
593
+ #'''
594
+ #Sets the instrument load current
595
+ #Move to generic class?
596
+ #'''
597
+ #def setReferenceCurrent (self,value):
598
+ # if value >= 0:
599
+ # self.setOutputEnable(False)
600
+ # self.setSourceMode("CURR")
601
+ # self.setLoadVoltageLimit(15)
602
+ # self.setLoadCurrent(value)
603
+ # self.setOutputEnable(True)
604
+ # else:
605
+ # raise ValueError ("negative load current requested")
606
+
607
+ #'''
608
+ #Sets the instrument output voltage
609
+ #Move to generic class?
610
+ #'''
611
+ #def setReferenceVoltage (self,value,currentLimit="1e-1"):
612
+ # if value >= 0:
613
+ # self.setOutputEnable(False)
614
+ # self.setSourceMode("VOLT")
615
+ # self.setLoadCurrentLimit(currentLimit)
616
+ # self.setLoadVoltageLimit(15)
617
+ # self.setLoadVoltage(value)
618
+ # self.setOutputEnable(True)
619
+ # else:
620
+ # raise ValueError ("negative voltage requested") # this is possible but a bad idea unless we really want it
621
+
622
+ '''
623
+ Puts the into a safe state
624
+ Move to generic class?
625
+ '''
626
+ def disable (self):
627
+ self.setOutputEnable(False)