Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
en:python-ivi:writing-drivers [2013/07/22 04:39]
alex
en:python-ivi:writing-drivers [2013/07/22 06: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>​
 +
 +