Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
en:python-ivi:writing-drivers [2013/07/22 02:39] alexen:python-ivi:writing-drivers [2013/07/22 04:17] (current) alex
Line 1: Line 1:
-====== Writing New Python-IVI Drivers ======+====== Writing New Python IVI Drivers ======
  
 Note: this page is under construction Note: this page is under construction
Line 17: Line 17:
 Test the interface and identity query by instantiating your driver and connecting to the instrument by running something like this in ipython: Test the interface and identity query by instantiating your driver and connecting to the instrument by running something like this in ipython:
  
-<code>+<code python>
 import ivi import ivi
 mso = ivi.agilent.agilentMSO7104A("TCPIP0::192.168.1.104::INSTR") mso = ivi.agilent.agilentMSO7104A("TCPIP0::192.168.1.104::INSTR")
Line 28: Line 28:
  
 Finally, you need to go write python code for all of the functions that the instrument supports. Take a look at some ''_get''/''_set'' pairs for some of the existing drivers to see the format. It's rather straightforward but quite tedious.   Finally, you need to go write python code for all of the functions that the instrument supports. Take a look at some ''_get''/''_set'' pairs for some of the existing drivers to see the format. It's rather straightforward but quite tedious.  
 +
 +===== Driver Template =====
 +
 +This is a sample template driver that incorporates all of the major components.  It is drawn from the Agilent 7000 series driver.  
 +
 +<code python>
 +"""
 +
 +Python Interchangeable Virtual Instrument Library
 +
 +Copyright (c) 2012 Alex Forencich
 +
 +Permission is hereby granted, free of charge, to any person obtaining a copy
 +of this software and associated documentation files (the "Software"), to deal
 +in the Software without restriction, including without limitation the rights
 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 +copies of the Software, and to permit persons to whom the Software is
 +furnished to do so, subject to the following conditions:
 +
 +The above copyright notice and this permission notice shall be included in
 +all copies or substantial portions of the Software.
 +
 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 +THE SOFTWARE.
 +
 +"""
 +
 +import struct
 +
 +from .. import ivi
 +from .. import scope
 +
 +AcquisitionTypeMapping = {
 +        'normal': 'norm',
 +        'peak_detect': 'peak',
 +        'high_resolution': 'hres',
 +        'average': 'aver'}
 +# more instrument-specific sets and mappings
 +
 +class agilent7000(ivi.Driver, scope.Base, scope.TVTrigger,
 +                scope.GlitchTrigger, scope.WidthTrigger, scope.AcLineTrigger,
 +                scope.WaveformMeasurement, scope.MinMaxWaveform,
 +                scope.ContinuousAcquisition, scope.AverageAcquisition,
 +                scope.SampleMode, scope.AutoSetup):
 +    "Agilent InfiniiVision 7000 series IVI oscilloscope driver"
 +    
 +    def __init__(self, *args, **kwargs):
 +        self._analog_channel_name = list()
 +        self._analog_channel_count = 4
 +        self._digital_channel_name = list()
 +        self._digital_channel_count = 16
 +        self._channel_label = list()
 +        # other per-channel instrument-specific variables that are
 +        # referenced in _init_channels
 +        
 +        super(agilent7000, self).__init__(*args, **kwargs)
 +        
 +        self._instrument_id = 'AGILENT TECHNOLOGIES'
 +        self._analog_channel_name = list()
 +        self._analog_channel_count = 4
 +        self._digital_channel_name = list()
 +        self._digital_channel_count = 16
 +        self._channel_count = 20
 +        self._bandwidth = 1e9
 +        # initialize other instrument-specific variables
 +        
 +        self._identity_description = "Agilent InfiniiVision 7000 series IVI oscilloscope driver"
 +        self._identity_identifier = ""
 +        self._identity_revision = ""
 +        self._identity_vendor = ""
 +        self._identity_instrument_manufacturer = "Agilent Technologies"
 +        self._identity_instrument_model = ""
 +        self._identity_instrument_firmware_revision = ""
 +        self._identity_specification_major_version = 4
 +        self._identity_specification_minor_version = 1
 +        self._identity_supported_instrument_models =['DSO7012A','DSO7014A','DSO7032A',
 +                'DSO7034A','DSO7052A','DSO7054A','DSO7104A','MSO7012A','MSO7014A','MSO7032A',
 +                'MSO7034A','MSO7052A','MSO7054A','MSO7104A','DSO7012B','DSO7014B','DSO7032B',
 +                'DSO7034B','DSO7052B','DSO7054B','DSO7104B','MSO7012B','MSO7014B','MSO7032B',
 +                'MSO7034B','MSO7052B','MSO7054B','MSO7104B']
 +        
 +        self.channels._add_property('label',
 +                        self._get_channel_label,
 +                        self._set_channel_label)
 +        # other instrument specific properties
 +        
 +        self._init_channels()
 +    
 +    def initialize(self, resource = None, id_query = False, reset = False, **keywargs):
 +        "Opens an I/O session to the instrument."
 +        
 +        self._channel_count = self._analog_channel_count + self._digital_channel_count
 +        
 +        super(agilent7000, self).initialize(resource, id_query, reset, **keywargs)
 +        
 +        # interface clear
 +        if not self._driver_operation_simulate:
 +            self._clear()
 +        
 +        # check ID
 +        if id_query and not self._driver_operation_simulate:
 +            id = self.identity.instrument_model
 +            id_check = self._instrument_id
 +            id_short = id[:len(id_check)]
 +            if id_short != id_check:
 +                raise Exception("Instrument ID mismatch, expecting %s, got %s", id_check, id_short)
 +        
 +        # reset
 +        if reset:
 +            self.utility.reset()
 +        
 +    
 +    def _load_id_string(self):
 +        if self._driver_operation_simulate:
 +            self._identity_instrument_manufacturer = "Not available while simulating"
 +            self._identity_instrument_model = "Not available while simulating"
 +            self._identity_instrument_firmware_revision = "Not available while simulating"
 +        else:
 +            lst = self._ask("*IDN?").split(",")
 +            self._identity_instrument_manufacturer = lst[0]
 +            self._identity_instrument_model = lst[1]
 +            self._identity_instrument_firmware_revision = lst[3]
 +            self._set_cache_valid(True, 'identity_instrument_manufacturer')
 +            self._set_cache_valid(True, 'identity_instrument_model')
 +            self._set_cache_valid(True, 'identity_instrument_firmware_revision')
 +    
 +    def _get_identity_instrument_manufacturer(self):
 +        if self._get_cache_valid():
 +            return self._identity_instrument_manufacturer
 +        self._load_id_string()
 +        return self._identity_instrument_manufacturer
 +    
 +    def _get_identity_instrument_model(self):
 +        if self._get_cache_valid():
 +            return self._identity_instrument_model
 +        self._load_id_string()
 +        return self._identity_instrument_model
 +    
 +    def _get_identity_instrument_firmware_revision(self):
 +        if self._get_cache_valid():
 +            return self._identity_instrument_firmware_revision
 +        self._load_id_string()
 +        return self._identity_instrument_firmware_revision
 +    
 +    def _utility_disable(self):
 +        pass
 +    
 +    def _utility_error_query(self):
 +        error_code = 0
 +        error_message = "No error"
 +        if not self._driver_operation_simulate:
 +            error_code, error_message = self._ask(":system:error?").split(',')
 +            error_code = int(error_code)
 +            error_message = error_message.strip(' "')
 +        return (error_code, error_message)
 +    
 +    def _utility_lock_object(self):
 +        pass
 +    
 +    def _utility_reset(self):
 +        if not self._driver_operation_simulate:
 +            self._write("*RST")
 +            self.driver_operation.invalidate_all_attributes()
 +    
 +    def _utility_reset_with_defaults(self):
 +        self._utility_reset()
 +    
 +    def _utility_self_test(self):
 +        code = 0
 +        message = "Self test passed"
 +        if not self._driver_operation_simulate:
 +            code = int(self._ask("*TST?"))
 +            if code != 0:
 +                message = "Self test failed"
 +        return (code, message)
 +    
 +    def _utility_unlock_object(self):
 +        pass
 +    
 +    def _init_channels(self):
 +        super(agilent7000, self)._init_channels()
 +        
 +        self._channel_name = list()
 +        self._channel_label = list()
 +        # init per-channel instrument-specific variables
 +        
 +        for i in range(self._channel_count):
 +            self._channel_name.append("channel%d" % (i+1))
 +            self._channel_label.append("%d" % (i+1))
 +            # init per-channel instrument-specific variables
 +        
 +        self.channels._set_list(self._channel_name)
 +    
 +    def _get_acquisition_start_time(self):
 +        pos = 0
 +        if not self._driver_operation_simulate and not self._get_cache_valid():
 +            pos = float(self._ask(":timebase:position?"))
 +            self._set_cache_valid()
 +        self._acquisition_start_time = pos - self._get_acquisition_time_per_record() * 5 / 10
 +        return self._acquisition_start_time
 +    
 +    def _set_acquisition_start_time(self, value):
 +        value = float(value)
 +        value = value + self._get_acquisition_time_per_record() * 5 / 10
 +        if not self._driver_operation_simulate:
 +            self._write(":timebase:position %e" % value)
 +        self._acquisition_start_time = value
 +        self._set_cache_valid()
 +    
 +    # more definitions
 +    
 +</code>
 +
 +