Beispiel #1
0
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)
Beispiel #2
0
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"]
Beispiel #3
0
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)
Beispiel #4
0
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"]
Beispiel #5
0
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"]
Beispiel #6
0
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"]