some code refactoring and several improvements in gpib_plotter (should be more robust & quicker)

Mon, 17 Dec 2007 18:58:00 +0100

author
David Douard <david.douard@logilab.fr>
date
Mon, 17 Dec 2007 18:58:00 +0100
changeset 12
a04bea92c509
parent 11
3ccb0023cf41
child 13
78e3e839658b

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:

mercurial