class Ber225(object): def __init__(self, port='/dev/ttyUSB0', addr=0): # clr turns off power self.gpib = PUGpib(port=port, addr=addr, clr=False, eos=3, ser_timeout=0.4, gpib_timeout=0.9) #self.chk_ok() def la(self, a): ''' Program amps limit ''' if a < 0 or a > 0.005: raise ValueError("Bad current %f" % a) s = 'L%0.4fM' % (a / 1000.) print s self.gpib.snd(s) def set_volt(self, v): ''' Program volts A "K" indicates a kilovolt limit and an "M" or "U" indicates a milliamp or microamp limit, respectively. The syntax is: "L{numeric string}K" Kilovolt Limit (All models) "L{numeric string}M" Milliamp Limit (All models except 30kV & 50kV)) "L{numeric string}U" Microamp Limit (Models 225- 30R & 225-50R only) 3.4.1 PROGRAMMING THE HIGH VOLTAGE OUTPUT ("P") "P {numeric string}K" Px.xxxxK (For 1kV, 3kV and 5kV models) 3.4.1.1 PROGRAMMING THE OUTPUT VOLTAGE AS A PERCENTAGE "P (numeric string) %K" The actual high voltage output will not change to a newly programmed value after a program command has been issued until the unit also receives a device trigger bus command or the "G" command string (see sections 3.3.4 and 3.4.3). ''' if v < 0 or v > 5000: raise ValueError("Bad voltage %f" % v) self.gpib.snd('P%0.4fK' % (v / 1000.)) # as percent #def pp(self, vp): # pass def g(self): ''' 3.4.3 ENTERING THE CURRENT PROGRAMMING & LIMIT VALUES ("G") When timing is not important, the "G" may be appended to the programming or limit command as shown below: Pxx.xxxKG Lx.xxxxMG ''' self.gpib.snd('G') apply = g def z(self): ''' 3.4.4 SHUTTING THE HIGH VOLTAGE OUTPUT OFF ("Z") The user may turn off the high voltage output without affecting the currently active programmed value. The syntax is: "Z" the single ASCII character This has the same effect as executing the device clear bus command ''' self.gpib.snd('Z') off = z def r(self): ''' 3.4.5 RESTORING THE HIGH VOLTAGE OUTPUT ("R") The high voltage output may be turned back on to the currently active programming value after having been shut off by a user command "Z" or by a trip due to overload. The sytax is: "R" the single ASCII character The high voltage output will return to the value that was programmed before the shut down. If the output was turned off by an overload trip, the cause of the overload should be corrected before trying to restore the output voltage or the trip will occur again. ''' self.gpib.snd('R') def t0(self): ''' 3.4.8 TRIGGERING METER READINGS OF THE OUTPUT ("T") Each unit has the capability to perform meter readings of its output voltage and current. The user may trigger a reading of the output voltage, the output current or both. The syntax is: "T {numeric}" Where {numeric} is the single ASCII character for 0, 1 or 2 and: T0: Triggers a measurement of the output voltage and current T1: Triggers a measurement of the output current only After receiving one of the "T" commands, the unit will return a character string containing output status (Normal, Tripped or Shutdown) and voltage and/or current readings. The numerical formats are those used to enter voltage and current values. Below are the "T" commands with some typical strings that are returned to the GPIB controlled in response: T0 "N Vxx.xxxK Ix.xxxxM" Note: These strings are, or are not, followed T1 "S Vx.xxxxK" by Line Terminators CR/LF depending T2 "T Ixxx.xxU" upon the chosen setting of switch S9, Position A6 (see section 3.2) A leading "N" in the string means that the output is on. A leading "S" means that the output was shut down by the user with a "Z" command or a device clear bus command. A leading "T" means that the output was tripped due to an overload detection. Also: "V" in the string means voltage "I" in the string means current "K" in the string means kilovolts "M" in the string means milliamps "U" in the string means microamps T0 N Vxx.xxxK Ix.xxxxM T1 S Vx.xxxxK T2 T Ixxx.xxU N V0.0349K I0.0009M T V0.0006K I0.0007M ''' s = self.gpib.snd_rcv('T0') # N V0.0349K I0.0009M m = re.match(r'N V(.*)K I(.*)M', s) if m: # raw in kV, mA # convert to V, A return (1000 * float(m.group(1)), float(m.group(2)) / 1000.) # T V0.0006K I0.0007M m = re.match(r'T V(.*)K I(.*)M', s) if m: return (1000 * float(m.group(1)), float(m.group(2)) / 1000.) raise Exception(s) def m(self): # sometimes the first one freezes # why? # ah yeah something to do with spoll ''' After receiving the "M" command, the unit will return a character string with its model number, output polarity setting and software revision. In the returned string, the "+225.03 re0.8" would denote a positive high voltage output from 0 to +3kV and the use of revision 0.8 software. Mine: M: +225.05 RE0.8 "+225.0.5" 225-0.5R set to positive output polarity "-225.30" 225-30R set to negative polarity ''' #print 'M: %s' % self.gpib.snd_rcv('M') #b.gpib.snd('M') #print 'M: %s' % b.gpib.ser.readline() s = self.gpib.snd_rcv('M') # +225.05 RE0.8 m = re.match(r'(.)(.*) (.*)', s) if not m: raise Exception(s) polarity = m.group(1) model = m.group(2) fw = m.group(3) return (polarity, model, fw) model = m def chk_ok(self): spoll = self.gpib.spoll() # No commands issued yet if spoll & 0x80: return if spoll & 0x20: raise Exception('spoll 0x%02x: invalid command' % spoll) if spoll & 0x08: raise Exception('spoll 0x%02x: tripped' % spoll) if spoll & 0x04: raise Exception('spoll 0x%02x: OV' % spoll) if spoll & 0x02: raise Exception('spoll 0x%02x: OC' % spoll)
class K2750(object): def __init__(self, port='/dev/ttyUSB0', clr=True, ident=True): self.gpib = PUGpib(port=port, addr=16, clr=clr, eos=3, ser_timeout=1.0, gpib_timeout=0.9) self.func = None self.vendor = None self.model = None self.sn = None if ident: vendor, model = self.ident() if (vendor, model) != ('KEITHLEY INSTRUMENTS INC.', 'MODEL 2750'): raise ValueError('Bad instrument: %s, %s' % (vendor, model)) def ident(self): # just vendor, model return self.ident_ex()[0:2] def ident_ex(self): ''' Returns the manufacturer, model number, serial number, and firmware revision levels of the unit. ['KEITHLEY INSTRUMENTS INC.', 'MODEL 2750', '0967413', 'A07 /A01'] ''' ret = self.gpib.sendrecv_str("*IDN?").split(',') self.vendor = ret[0] self.model = ret[1] sn = ret[2] fw = ret[3] return (self.vendor, self.model, sn, fw) def card_sn(self): return self.gpib.sendrecv_str("SYSTem:CARD1:SNUMber?") def tim_int(self): '''Query timer interval''' return float(self.gpib.snd_rcv('TRIGger:TIMer?')) def local(self): '''Go to local mode''' # Error -113 self.gpib.snd('GTL') def set_beep(self, en): ''' You can disable the beeper for limits and continuity tests. However, when limits or CONT is again selected, the beeper will automatically enable. ''' if en: self.gpib.snd("SYSTEM:BEEPER OFF") else: self.gpib.snd("SYSTEM:BEEPER ON") def error(self): '''Get next error from queue''' return self.gpib.snd_rcv("SYSTEM:ERROR?") def errors(self): ret = [] while True: e = self.error() if e == '0,"No error"': return ret ret.append(e) def volt_dc_ex(self): if self.func != 'VOLT:DC': self.gpib.snd(":FUNC 'VOLT:DC'") time.sleep(0.20) self.func = 'VOLT:DC' raw = self.gpib.snd_rcv(":DATA?") m = volt_dc_re.match(raw) if not m: raise Exception("Bad reading: %s" % (raw, )) vdc = float(m.group(1)) secs = float(m.group(2)) rdng = float(m.group(3)) return {"VDC": vdc, "SECS": secs, "RDNG#": rdng} def volt_dc(self): return self.volt_dc_ex()["VDC"] def curr_dc_ex(self): if self.func != 'CURR:DC': self.gpib.snd(":FUNC 'CURR:DC'") # Seems to take at least 0.1 sec # had problems with 0.15 time.sleep(0.20) self.func = 'CURR:DC' raw = self.gpib.snd_rcv(":DATA?") m = curr_dc_re.match(raw) if not m: raise Exception("Bad reading: %s" % (raw, )) adc = float(m.group(1)) secs = float(m.group(2)) rdngn = float(m.group(3)) return {"ADC": adc, "SECS": secs, "RDNG#": rdngn} def curr_dc(self): return self.curr_dc_ex()["ADC"] def res_ex(self): if self.func != 'RES': self.gpib.snd(":FUNC 'RES'") # Seems to take at least 0.1 sec # had problems with 0.15 time.sleep(0.20) self.func = 'RES' raw = self.gpib.snd_rcv(":DATA?") m = res_re.match(raw) if not m: raise Exception("Bad reading: %s" % (raw, )) adc = m.group(1) if adc.find('OHM') >= 0: adc = float(adc.replace('OHM', '')) else: adc = float('inf') secs = float(m.group(2)) rdngn = float(m.group(3)) return {"ADC": adc, "SECS": secs, "RDNG#": rdngn} def res(self): return self.res_ex()["ADC"]
class K2750(object): def __init__(self, port='/dev/ttyUSB0', clr=True, ident=True): self.gpib = PUGpib(port=port, addr=16, clr=clr, eos=3, ser_timeout=1.0, gpib_timeout=0.9) self.func = None self.vendor = None self.model = None self.sn = None if ident: vendor, model = self.ident() if (vendor, model) != ('KEITHLEY INSTRUMENTS INC.', 'MODEL 2750'): raise ValueError('Bad instrument: %s, %s' % (vendor, model)) def ident(self): # just vendor, model return self.ident_ex()[0:2] def ident_ex(self): ''' Returns the manufacturer, model number, serial number, and firmware revision levels of the unit. ['KEITHLEY INSTRUMENTS INC.', 'MODEL 2750', '0967413', 'A07 /A01'] ''' ret = self.gpib.sendrecv_str("*IDN?").split(',') self.vendor = ret[0] self.model = ret[1] sn = ret[2] fw = ret[3] return (self.vendor, self.model, sn, fw) def card_sn(self): return self.gpib.sendrecv_str("SYSTem:CARD1:SNUMber?") def tim_int(self): '''Query timer interval''' return float(self.gpib.snd_rcv('TRIGger:TIMer?')) def local(self): '''Go to local mode''' # Error -113 self.gpib.snd('GTL') def set_beep(self, en): ''' You can disable the beeper for limits and continuity tests. However, when limits or CONT is again selected, the beeper will automatically enable. ''' if en: self.gpib.snd("SYSTEM:BEEPER OFF") else: self.gpib.snd("SYSTEM:BEEPER ON") def error(self): '''Get next error from queue''' return self.gpib.snd_rcv("SYSTEM:ERROR?") def errors(self): ret = [] while True: e = self.error() if e == '0,"No error"': return ret ret.append(e) def volt_dc_ex(self): if self.func != 'VOLT:DC': self.gpib.snd(":FUNC 'VOLT:DC'") time.sleep(0.20) self.func = 'VOLT:DC' raw = self.gpib.snd_rcv(":DATA?") m = volt_dc_re.match(raw) if not m: raise Exception("Bad reading: %s" % (raw,)) vdc = float(m.group(1)) secs = float(m.group(2)) rdng = float(m.group(3)) return {"VDC": vdc, "SECS": secs, "RDNG#": rdng} def volt_dc(self): return self.volt_dc_ex()["VDC"] def curr_dc_ex(self): if self.func != 'CURR:DC': self.gpib.snd(":FUNC 'CURR:DC'") # Seems to take at least 0.1 sec # had problems with 0.15 time.sleep(0.20) self.func = 'CURR:DC' raw = self.gpib.snd_rcv(":DATA?") m = curr_dc_re.match(raw) if not m: raise Exception("Bad reading: %s" % (raw,)) adc = float(m.group(1)) secs = float(m.group(2)) rdngn = float(m.group(3)) return {"ADC": adc, "SECS": secs, "RDNG#": rdngn} def curr_dc(self): return self.curr_dc_ex()["ADC"] def res_ex(self): if self.func != 'RES': self.gpib.snd(":FUNC 'RES'") # Seems to take at least 0.1 sec # had problems with 0.15 time.sleep(0.20) self.func = 'RES' raw = self.gpib.snd_rcv(":DATA?") m = res_re.match(raw) if not m: raise Exception("Bad reading: %s" % (raw,)) adc = m.group(1) if adc.find('OHM') >= 0: adc = float(adc.replace('OHM', '')) else: adc = float('inf') secs = float(m.group(2)) rdngn = float(m.group(3)) return {"ADC": adc, "SECS": secs, "RDNG#": rdngn} def res(self): return self.res_ex()["ADC"]
class K2750(object): def __init__(self, port='/dev/ttyUSB0', clr=True): self.gpib = PUGpib(port=port, addr=16, clr=clr, eos=3, ser_timeout=1.0, gpib_timeout=0.9) self.func = None self.volt_dc_re = None self.curr_dc_re = None def tim_int(self): '''Query timer interval''' return float(self.gpib.snd_rcv('TRIGger:TIMer?')) def local(self): '''Go to local mode''' # Error -113 self.gpib.snd('GTL') def set_beep(self, en): ''' You can disable the beeper for limits and continuity tests. However, when limits or CONT is again selected, the beeper will automatically enable. ''' if en: self.gpib.snd("SYSTEM:BEEPER OFF") else: self.gpib.snd("SYSTEM:BEEPER ON") def error(self): '''Get next error from queue''' return self.gpib.snd_rcv("SYSTEM:ERROR?") def errors(self): ret = [] while True: e = self.error() if e == '0,"No error"': return ret ret.append(e) def volt_dc_ex(self): if self.func != 'VOLT:DC': self.gpib.snd(":FUNC 'VOLT:DC'") time.sleep(0.20) self.func = 'VOLT:DC' if self.volt_dc_re is None: # -1.25629986E-02VDC,+2319.404SECS,+10155RDNG# # -3.47094010E-06VDC,+4854.721SECS,+20115RDNG# self.volt_dc_re = re.compile("(.*)VDC,(.*)SECS,(.*)RDNG#") raw = self.gpib.snd_rcv(":DATA?") m = self.volt_dc_re.match(raw) if not m: raise Exception("Bad reading: %s" % (raw, )) vdc = float(m.group(1)) secs = float(m.group(2)) rdng = float(m.group(3)) return {"VDC": vdc, "SECS": secs, "RDNG#": rdng} def volt_dc(self): return self.volt_dc_ex()["VDC"] def curr_dc_ex(self): if self.func != 'CURR:DC': self.gpib.snd(":FUNC 'CURR:DC'") # Seems to take at least 0.1 sec # had problems with 0.15 time.sleep(0.20) self.func = 'CURR:DC' if self.curr_dc_re is None: # -4.15096054E-07ADC,+5064.727SECS,+22239RDNG# self.curr_dc_re = re.compile("(.*)ADC,(.*)SECS,(.*)RDNG#") raw = self.gpib.snd_rcv(":DATA?") m = self.curr_dc_re.match(raw) if not m: raise Exception("Bad reading: %s" % (raw, )) adc = float(m.group(1)) secs = float(m.group(2)) rdngn = float(m.group(3)) return {"ADC": adc, "SECS": secs, "RDNG#": rdngn} def curr_dc(self): return self.curr_dc_ex()["ADC"]
class K2750(object): def __init__(self, port='/dev/ttyUSB0', clr=True): self.gpib = PUGpib(port=port, addr=16, clr=clr, eos=3, ser_timeout=1.0, gpib_timeout=0.9) self.func = None self.volt_dc_re = None self.curr_dc_re = None def tim_int(self): '''Query timer interval''' return float(self.gpib.snd_rcv('TRIGger:TIMer?')) def local(self): '''Go to local mode''' # Error -113 self.gpib.snd('GTL') def set_beep(self, en): ''' You can disable the beeper for limits and continuity tests. However, when limits or CONT is again selected, the beeper will automatically enable. ''' if en: self.gpib.snd("SYSTEM:BEEPER OFF") else: self.gpib.snd("SYSTEM:BEEPER ON") def error(self): '''Get next error from queue''' return self.gpib.snd_rcv("SYSTEM:ERROR?") def errors(self): ret = [] while True: e = self.error() if e == '0,"No error"': return ret ret.append(e) def volt_dc_ex(self): if self.func != 'VOLT:DC': self.gpib.snd(":FUNC 'VOLT:DC'") time.sleep(0.20) self.func = 'VOLT:DC' if self.volt_dc_re is None: # -1.25629986E-02VDC,+2319.404SECS,+10155RDNG# # -3.47094010E-06VDC,+4854.721SECS,+20115RDNG# self.volt_dc_re = re.compile("(.*)VDC,(.*)SECS,(.*)RDNG#") raw = self.gpib.snd_rcv(":DATA?") m = self.volt_dc_re.match(raw) if not m: raise Exception("Bad reading: %s" % (raw,)) vdc = float(m.group(1)) secs = float(m.group(2)) rdng = float(m.group(3)) return {"VDC": vdc, "SECS": secs, "RDNG#": rdng} def volt_dc(self): return self.volt_dc_ex()["VDC"] def curr_dc_ex(self): if self.func != 'CURR:DC': self.gpib.snd(":FUNC 'CURR:DC'") # Seems to take at least 0.1 sec # had problems with 0.15 time.sleep(0.20) self.func = 'CURR:DC' if self.curr_dc_re is None: # -4.15096054E-07ADC,+5064.727SECS,+22239RDNG# self.curr_dc_re = re.compile("(.*)ADC,(.*)SECS,(.*)RDNG#") raw = self.gpib.snd_rcv(":DATA?") m = self.curr_dc_re.match(raw) if not m: raise Exception("Bad reading: %s" % (raw,)) adc = float(m.group(1)) secs = float(m.group(2)) rdngn = float(m.group(3)) return {"ADC": adc, "SECS": secs, "RDNG#": rdngn} def curr_dc(self): return self.curr_dc_ex()["ADC"]