Mon, 17 Dec 2007 18:58:00 +0100
some code refactoring and several improvements in gpib_plotter (should be more robust & quicker)
gpib.py | file | annotate | diff | comparison | revisions | |
gpib_plotter.py | file | annotate | diff | comparison | revisions |
--- a/gpib.py Mon Dec 17 18:57:18 2007 +0100 +++ b/gpib.py Mon Dec 17 18:58:00 2007 +0100 @@ -9,143 +9,56 @@ 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. +class Constants(object): + def __init__(self): + self.constants = {} + self.descriptions = {} + self.rev_constants = {} + for v, k, m in self._constants: + self.k = v + self.constants[v] = k + self.rev_constants[k] = v + self.descriptions[v] = m + + def __getitem__(self, k): + if isinstance(k, basestring): + return self.rev_constants[k] + else: + return self.constants[k] -##################### -# 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, + def get_description(self, k): + if isinstance(k, basestring): + k = self.rev_constants[k] + return self.descriptions[k] + - - 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 +class MODE(Constants): + _constants = [(1, "CONTROLLER", "Set device as Controller in Charge"), + (0, "DEVICE", "Set device as simple listener"), + ] +# TODO +# class STATUS_BYTE(Constants): +# # 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) +# class SESR(Constants): +# # 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. - 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))) -
--- a/gpib_plotter.py Mon Dec 17 18:57:18 2007 +0100 +++ b/gpib_plotter.py Mon Dec 17 18:58:00 2007 +0100 @@ -2,7 +2,9 @@ import time import gpib -class GPIBplotter(gpib.GPIB): +import gpib +from prologix import GPIB +class GPIBplotter(GPIB): _replies={ "OE": "0", "OH": "0,0,10000,7500", @@ -13,7 +15,7 @@ "OS": "24", } def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1, - address=0): + address=5): super(GPIBplotter, self).__init__(device, baudrate, timeout, address, mode=0) def load_plot(self, wait_timeout=0): @@ -35,27 +37,34 @@ self._cnx.timeout = wait_timeout firstloop = True + newdata = False while i<self._retries: l = self._cnx.readline().strip() if firstloop: self._cnx.timeout = self._timeout firstloop = False if l == "": - i += 1 - if i == (self._retries-1): + if i == 0:# > (self._retries/2): + # ie. we just received new stuffs (i is reset in the else block) for k, v in replies.items(): - eres = res.strip() + # check wether we should reply smthg + eres = res.replace('\n', '').strip() if eres.endswith(k) or eres.endswith(k+';') or eres.endswith(k+';OE'): self._cnx.write("%s"%v) if k == "OS": replies[k] = "16" break self._cnx.write('\r') - if i > self._retries/2: - time.sleep(self._timeout) + #time.sleep(0.1) + i += 1 else: - res += l + "\n" + if not res: + print "Plotting..." + res += l + '\n' i = 0 + #time.sleep(0.1) + if res: + print "DONE (received %d characters)"%len(res) return res if __name__ == '__main__': @@ -105,7 +114,7 @@ loop = True nloop = 0 while loop: - plot = plotter.load_plot(wait_timeout=1) + plot = plotter.load_plot(wait_timeout=0.1) if options.verbose: sys.stderr.write('.') if plot: