Fri, 14 Dec 2007 00:21:47 +0100
several updates to the gpib module
""" gpib: create serial connection to GPIB-USB device (ProLogix is the only supported device for now). """ import serial from serial.serialutil import SerialException import time class ConnectionError(Exception): pass GPIB_CONTROLLER = 1 GPIB_DEVICE = 0 # IEEE 488.2 Status Byte constants MAV = 0x10 # Message AVailable: bit 4 of the Status Byte ESB = 0x20 # Event Status Bit: bit 5 of the Status Byte MSS = 0x40 # Master Summary Status bit: bit 6 of the Status Byte (NOT # sent in response to a serial poll) RQS = 0x40 # Request Service: bit 6 of the Status Byte (when sent in # response to a serial poll) # SESR constants (Standard Event Status Register) PON = 0x80 # Power On: Power has been turned On since last register # read access URQ = 0x40 # User Request: the user has activated some device control # (whatever the Remote Local state is) CME = 0x20 # Command Error EXE = 0x10 # Execution Error DDE = 0x08 # Device Dependant Error QYE = 0x04 # QuerY Error (attempt to read data while Output Queue is # empty, or data in the OQ was lost) RQC = 0x02 # Request Control: tell the CiC that the device wants to # become the CiC OPC = 0x01 # Operation Complete: device has completed any pending # operation (ready to accept new commands). This bit is # generated in response to a OPC command. ##################### # HP3562A constants # GPIB buffer size is 3x80 characters lines # HP3562A Status Byte RQS = 0x40 # Request Service: when sent in response to a serial poll ERR = 0x20 # ERRor: GPIB error RDY = 0x10 #ReaDY: ready to accept GPIB commands class GPIB(object): _retries = 15 def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1, address=0, mode=1): """ Create a new GPIB controller for the Prologix USB-GPIB device located on serial device 'device'. """ self._cnx = serial.Serial(port=device, baudrate=baudrate, timeout=timeout) self._timeout = timeout self.set_mode(mode) self.set_address(address) def set_address(self, address): """ Set the address of the GPIB device: - if the device is the Controller In Charge, this is the address of the device commands are sent to, - if the device is in GPIB_DEVICE mode, this is its address. """ self._set_cmd('addr', address) self._adress = address def set_mode(self, mode): """ Set GPIB device mode to 'mode': - GPIB_CONTROLLER: set the device as the Controller In Charge on the GPIB bus - GPIB_DEVICE: set the device as a standard GPIB device on the bus. """ self._set_cmd('mode', mode) self._mode = mode def set_controler(self): """ Set GPIB device the Controller In Charge on the GPIB bus. """ self.set_mode(1) def set_device(self): """ Set the GPIB device as a simple device on the GPIB bus. """ self.set_mode(0) def send_command(self, cmd): """ Send the specified GPIB command on the bus (must be the CIC), and read the answer. """ assert self._mode == 1 self._cnx.write(cmd+'\r') time.sleep(self._timeout) # required? ret = self._cnx.readlines() return ''.join(ret) def check_srq(self): """ Check the SRQ line """ assert self._mode == 1, "must be the Controller In Charge" self._cnx.write('++srq\r') ret = self._cnx.readline().strip() if ret: return bool(int(ret)) return None def poll(self): """ Poll every address, and return a dictionnary {add: status, ...} """ assert self._mode == 1, "must be the Controller In Charge" dico = {} for add in range(31): self._cnx.write('++spoll %d\r'%i) ret = self._cnx.readline().strip() if ret: dico[i] = int(ret) return dico def _read(self): for i in range(self._retries): rdata = self._cnx.readline() if rdata.strip() != "": break time.sleep(self._timeout) return rdata def _set_cmd(self, cmd, value): self._cnx.write('++%s %d\r'%(cmd, value)) self._cnx.write('++%s\r'%(cmd)) rval = self._read().strip() if not rval.isdigit() or int(rval) != value: raise ConnectionError("Can't set GPIB %s to %s [ret=%s]"%(cmd, value, repr(rval)))