gpib.py

Fri, 14 Dec 2007 00:21:47 +0100

author
David Douard <david.douard@logilab.fr>
date
Fri, 14 Dec 2007 00:21:47 +0100
changeset 9
3b50c46fca56
parent 7
2e2742648546
child 12
a04bea92c509
permissions
-rw-r--r--

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)))
    

mercurial