Git Product home page Git Product logo

oscope-scpi's People

Contributors

corecode avatar sgoadhouse avatar udif avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

oscope-scpi's Issues

Add function to set trigger

Consider adding following function (working for Keysight DSO-X 2004A and DSO-X 3034A, not tested for other oscis):

def set_trigger(self, mode='EDGE', sweep_mode='NORMal', noise_reject_filter='ON', channel=1,
                    slope='POSitive', level=10):
        '''Sets a trigger with all needed subcommands, default is the setup needed for a rising
        edge measurement with trigger level at 10 (Volt) on Channel 1,
        see Keysight Command Expert for details.

        :param mode: trigger mode, can be e.g. EDGE, GLITch or PATTern, defaults to 'EDGE'
        :type mode: str, optional
        :param sweep_mode: can be AUTO or NORMal, defaults to 'NORMal'
        :type sweep_mode: str, optional
        :param noise_reject_filter: can be 'ON' or 'OFF', defaults to 'ON'
        :type noise_reject_filter: str, optional
        :param channel: choose a channel from 1 to 4, defaults to 1
        :type channel: int, optional
        :param slope: can be POSitive, NEGative, EITHer or ALTernate, defaults to 'POSitive'
        :type slope: str, optional
        :param level: defines which level has to be met to trigger at all, defaults to 10
        :type level: int, optional
        :return: response of the trigger-query
        :rtype: str
        '''
        # pylint: disable=too-many-arguments
        # all 7 optional arguments are needed here to set the trigger respectively
        # Setting the trigger mode, can be e.g. EDGE, GLITch or PATTern
        self.write_raw(f':TRIGger:MODE {mode}')
        # Selects the trigger sweep mode (called "Mode" on the front panel)
        # In auto trigger mode, the trigger will be forced if the specified conditions are not met.
        # In normal trigger mode, the trigger will never be forced and a trigger will only
        # occur if the specified conditions are met.
        self.write_raw(f':TRIGger:SWEep {sweep_mode}')
        # Turns the noise reject filter off and on
        self.write_raw(f':TRIGger:NREJect {noise_reject_filter}')
        # Setting the channel source that produces the trigger
        self.write_raw(f':TRIGger:{mode}:SOURce CHANnel{channel}')
        # Sets the trigger level for the active trigger source
        self.write_raw(f':TRIGger:{mode}:LEVel {level}')
        if mode == 'EDGE':
            # Specifies the slope of the trigger-edge: POSitive, NEGative, EITHer or ALTernate
            self.write_raw(f':TRIGger:EDGE:SLOPe {slope}')
        if mode == 'GLITch':
            # Sets the minimum pulse width duration to 1 ms (filters out short pulses)
            self.write_raw(':TRIGger:GLITch:Greaterthan 1 MS')
        response = self.query_raw(':TRIGger?')
        return response

add a function to wait until osci finished the momentary measurement

Consider adding a function to wait until osci stopped its measurement:

    def wait_until_stopped(self, max_seconds=20, warn=True):
        '''Queries for the running status of run-control until the osci is in state stopped.
        Does this for a maximum number of seconds, afterwards it leaves the function to not query
        forever.

        :param max_seconds: define how long to wait max, defaults to 20
        :type max_seconds: int or str, optional
        :param warn: decide, if a warning shall be logged after time is over, defaults to True
        :type warn: bool
        :return: if it stopped after condition change or after maximum number of seconds
        :rtype: bool
        '''
        # Wait a maximum number of seconds to prevent looping forever
        for i in range(int(max_seconds)):
            try:
                operation_register = int(self.query_raw(':OPERegister:CONDition?'))
            except VisaIOError:
                time.sleep(1)
                continue
            # We need the value from bit 3 of operation register
            # It tells us if the oscilloscope is running (not stopped)
            running = bool((operation_register >> 3) & 1)
            if not running:
                logger.info(f'Osci: Stopped after {i} seconds.')
                return True
            time.sleep(1)
        if warn:
            logger.warn(f'Osci: Waited {max_seconds}s to switch to status "stop", did not work.')
        return False

Can't get oscope to work, fails right on open

Hi,

I can't get oscope to work at all.

Using bare pyvisa seems to work fine:

(udif) 4:06pm udif@udif-ce7 udif/oscope-scpi> python3
Python 3.8.3 | packaged by conda-forge | (default, Jun  1 2020, 17:43:00) 
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyvisa as visa
>>> rm = visa.ResourceManager('@py')
>>> l=rm.list_resources()
>>> l
('ASRL/dev/ttyS0::INSTR', 'ASRL/dev/ttyACM1::INSTR', 'ASRL/dev/ttyACM0::INSTR', 'USB0::10893::5988::MY0000000::0::INSTR')
>>> inst=rm.open_resource(l[3])
>>> print(inst.query("*IDN?"))
KEYSIGHT TECHNOLOGIES,DSO-X 3034T,MY0000000,07.20.2017102614

(In this github issue I have erased the true S/N, beginning with MYxxxxxxx, and replaced it with MY0000000).

When using oscope-scpi, I get errors.
I have the prerequisites:

(udif) 3:57pm udif@udif-ce7 udif/oscope-scpi> pip list | grep PyVISA
PyVISA                 1.11.3
PyVISA-py              0.5.2
(udif) 4:04pm udif@udif-ce7 udif/oscope-scpi> python
Python 3.8.3 | packaged by conda-forge | (default, Jun  1 2020, 17:43:00) 
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from oscope_scpi import Oscilloscope
>>> instr = Oscilloscope('USB0::10893::5988::MY0000000::0::INSTR')
>>> instr = instr.getBestClass()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Vols/vol_design10/lynx/users/udif/oscope-scpi/oscope_scpi/oscilloscope.py", line 114, in getBestClass
    superduper.open()
  File "/Vols/vol_design10/lynx/users/udif/oscope-scpi/oscope_scpi/scpi.py", line 94, in open
    self._inst.clear()
  File "/home/udif/.conda/envs/udif/lib/python3.8/site-packages/pyvisa/resources/resource.py", line 397, in clear
    self.visalib.clear(self.session)
  File "/home/udif/.conda/envs/udif/lib/python3.8/site-packages/pyvisa_py/highlevel.py", line 191, in clear
    return self.handle_return_value(session, sess.clear())
  File "/home/udif/.conda/envs/udif/lib/python3.8/site-packages/pyvisa/highlevel.py", line 251, in handle_return_value
    raise errors.VisaIOError(rv)
pyvisa.errors.VisaIOError: VI_ERROR_NSUP_OPER (-1073807257): The given session or object reference does not support this operation.

I don't have much experience with VISA, so please excuse me if this is something trivial I've missed.
As can be seen from the logs, I'm using Keysight DSOX3034T connected through USB on a clean CentOS 7.9 install.

Any help would be appreciated.

Thanks,
Udi

Stopping an indefinite trigger

I'm having issues with my USB-connected DSOX3034T where a poorly-defined trigger event leaves the scope waiting indefinitely for a trigger.
It seems that while it is waiting for the trigger, it no longer responds to SCPI commands.
Even sending a modeStop() doesn't help getting it out of the trigger.

I assume this doesn't happen with Ethernet or GPIB based interfaces, but I want to be sure it's a univeral thing and not an issue with my setup.

This is a huge issue for me because it means I cannot work remotely in a reliable way.
I also witnessed cases where the DSOX completely ignores USB input, even when it is not waiting for a trigger (and I can fully use the GUI), and even worse, there was a case when it simply lost its USB device (did not even appear in an lsusb scan).
In both cases the only solution was a manual power off/power on sequence.
The trigger issue on top is still the worst, because it is consistent, while those below were random and happened less frequently.

Add functions to configure both axis

Consider adding functions for configuring x- and y-axis:

    def configure_x_axis(self, position: float = 4.9, horizontal_time: int = 10):
        '''Configures the horizontal x-axis to the correct range and position.
        It is only possible to configure it in this order, otherwise an error is raised.

        :param position: interval between trigger and reference point in seconds, defaults to 4.9
        :type position: int, optional
        :param horizontal_time: full-scale horizontal time in seconds, defaults to 10
        :type horizontal_time: int, optional
        :raises ValueError: If writing of Position wasn't successful
        :raises ValueError: If writing of Range wasn't successful
        '''
        # sets the full-scale horizontal time range in seconds for the main window
        self.write_raw(f':TIMebase:RANGe {horizontal_time}')
        if float(self.query_raw(':TIMebase:RANGe?')) != float(horizontal_time):
            raise ValueError('Osci: Timebase:RANGe not set successful!')
        # sets the time interval between trigger event and display reference point on the screen
        self.write_raw(f':TIMebase:POSition {position}')
        if float(self.query_raw(':TIMebase:POSition?')) != float(position):
            raise ValueError('Osci: TIMebase:POSition not set successful!')

    def configure_y_axis(self, channel: int, v_range: int, v_offset: int=0):
        '''Defines the full-scale vertical axis (8 parts) of the selected channel.

        :param channel: choose a channel from 1 to 4
        :type channel: int
        :param v_range: defines the vertical range, e.g. 8 for 1A/
        :type v_range: int
        :param v_offset: defines the vertical offset from the center screen to the bottom,
                         defaults to 0
        :type v_offset: int
        '''
        self.write_raw(f':CHANnel{channel}:RANGe {v_range}')
        if float(self.query_raw(f':CHANnel{channel}:RANGe?')) != float(v_range):
            raise ValueError('Osci: CHANnel:RANGe not set successful!')
        self.write_raw(f':CHANnel{channel}:OFFSet {v_offset}')
        if float(self.query_raw(f':CHANnel{channel}:OFFSet?')) != float(v_offset):
            raise ValueError('Osci: CHANnel:OFFSet not set successful!')

problem with specific version of numpy

Setup.py specifies exact version of numpy.

'numpy==1.19.5'

is there a strong reason why? It causes problems with the conflict resolution and cannot be installed on python 3.10+ because that is not compatible with the numpy-1.19.5 at all.

Can we have instead this boundary?

'numpy>=1.19.5'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.