Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add methods in powersupplies.rigol, scopes.rigol #100

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions instrumental/driver_info.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Auto-generated 2019-05-06T16:23:11.970004
# Auto-generated 2019-09-19T15:55:57.247343
from collections import OrderedDict

driver_info = OrderedDict([
Expand Down Expand Up @@ -35,9 +35,9 @@
('funcgenerators.rigol', {
'params': ['visa_address'],
'classes': [],
'imports': [],
'imports': ['visa'],
'visa_info': {
'DG800': ('Rigol Technologies', ['DG812']),
'DG800': ('Rigol Technologies', ['DG811', 'DG812']),
},
}),
('funcgenerators.tektronix', {
Expand Down Expand Up @@ -131,6 +131,14 @@
'GPD_3303S': ('GW INSTEK', ['GPD-3303S']),
},
}),
('powersupplies.rigol', {
'params': ['visa_address'],
'classes': [],
'imports': ['pyvisa', 'visa'],
'visa_info': {
'DP700': ('RIGOL TECHNOLOGIES', ['DP711', 'DP712']),
},
}),
('scopes.agilent', {
'params': ['visa_address'],
'classes': ['DSO_1000'],
Expand All @@ -139,6 +147,14 @@
'DSO_1000': ('Agilent Technologies', ['DSO1024A']),
},
}),
('scopes.rigol', {
'params': ['visa_address'],
'classes': [],
'imports': ['pyvisa', 'visa'],
'visa_info': {
'DS1000Z': ('RIGOL TECHNOLOGIES', ['DS1054Z']),
},
}),
('scopes.tektronix', {
'params': ['visa_address'],
'classes': ['MSO_DPO_2000', 'MSO_DPO_4000', 'TDS_1000', 'TDS_200', 'TDS_2000', 'TDS_3000'],
Expand Down
45 changes: 28 additions & 17 deletions instrumental/drivers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,34 +452,40 @@ def write(self, message, *args, **kwds):

>>> inst.write('source{}:value {}', channel, value)
"""
full_message = message.format(*args, **kwds)
full_message = fmt = message.format(*args, **kwds)
if self._in_transaction:
if full_message[0] != ':':
full_message = ':' + full_message
if fmt[0] != ':':
full_message = ':' + fmt
self._message_queue.append(full_message)
else:
self._rsrc.write(full_message)
self._rsrc.write(fmt)

def query(self, message, *args, **kwds):
"""Query the instrument's VISA resource with `message`

Flushes the message queue if called within a transaction.
"""
full_message = fmt = message.format(*args, **kwds)
if self._in_transaction:
self._flush_message_queue() # TODO: combine query with this message?
return self._rsrc.query(message.format(*args, **kwds))
if fmt[0] != ':':
full_message = ':' + fmt
self._message_queue.append(full_message)
else:
return self._rsrc.query(fmt)

@contextlib.contextmanager
def transaction(self):
"""Transaction context manager to auto-chain VISA messages

Queues individual messages written with the `write()` method and sends them all at once,
joined by ';'. Messages are actually sent (1) when a call to `query()` is made and (2)
upon the end of transaction.
Queues individual messages written with the `write()` and `query()` methods and sends them
all at once, joined by ';'. Messages are sent upon the end of the transaction.

This is especially useful when using higher-level functions that call `write()` or
`query()`, as it lets you combine multiple logical operations into a single message,
which can be faster than sending lots of little messages.

This is especially useful when using higher-level functions that call `write()`, as it lets
you combine multiple logical operations into a single message (if only using writes), which
can be faster than sending lots of little messages.
Note that all query() calls need to return a string for the transaction. This is important
when using a Facet since it is possible to make a Facet return an object.

Be cognizant that a visa resource's write and query methods are not transaction-aware, only
VisaMixin's are. If you need to call one of these methods (e.g. write_raw), make sure you
Expand All @@ -490,9 +496,10 @@ def transaction(self):
>>> with myinst.transaction():
... myinst.write('A')
... myinst.write('B')
... myinst.query('C?') # Query forces flush. Writes "A;B" and queries "C?"
... myinst.write('D')
... myinst.write('E') # End of transaction block, writes "D;E"
... myinst.query('C?')
... myinst.query('D?')
... myinst.write('E') # End of transaction block, writes "A;B;C?;D?;E"
>>> print(myinst.response) # Shows the responses of "C?" and "D?" as a tuple
"""
self._start_transaction()
yield
Expand All @@ -502,17 +509,21 @@ def _start_transaction(self):
self._message_queue = []

def _end_transaction(self):
self._flush_message_queue()
self.response = self._flush_message_queue()
self._message_queue = None # signals end of transaction

def _flush_message_queue(self):
"""Write all queued messages at once"""
if not self._in_transaction:
return
message = ';'.join(self._message_queue)
self._rsrc.write(message)
self._message_queue = []

if message.find('?') != -1:
return self._rsrc.query(message).split(';')
else:
self._rsrc.write(message)

@property
def _in_transaction(self):
return getattr(self, '_message_queue', None) is not None
Expand Down
2 changes: 1 addition & 1 deletion instrumental/drivers/powermeters/newport.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ def attenuator_enabled(self):
val = self.write('A?')
return bool(val)

def get_valid_power(self, max_attempts=10, polling_interval=0.1*u.s)):
def get_valid_power(self, max_attempts=10, polling_interval=0.1*u.s):
"""Returns a valid power reading

This convience function will try to measure a valid power up to a
Expand Down
12 changes: 4 additions & 8 deletions instrumental/drivers/powersupplies/rigol.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import pyvisa
import re

_INST_PARAMS_ = ['visa_address']
_INST_VISA_INFO_ = {
_INST_PARAMS = ['visa_address']
_INST_VISA_INFO = {
'DP700': ('RIGOL TECHNOLOGIES', ['DP711', 'DP712']),
}

Expand Down Expand Up @@ -53,6 +53,8 @@ class DP700(RigolPowerSupply, VisaMixin):
current_protection_state = SCPI_Facet('SOURce:CURRent:PROTection:STATe', convert=OnOffState)
output = SCPI_Facet('OUTPut:STATe', convert=OnOffState)
beeper = SCPI_Facet('SYSTem:BEEPer', convert=OnOffState)
measured_voltage = SCPI_Facet('MEASure:VOLTage', convert=float, readonly=True, units='A')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a typo here, units should be volts

measured_current = SCPI_Facet('MEASure:CURRent', convert=float, readonly=True, units='A')

@property
def manufacturer(self):
Expand All @@ -74,12 +76,6 @@ def version(self):
_, _, _, version = self.query('*IDN?').rstrip().split(',', 4)
return version

def get_measured_voltage(self):
return Q_(self.query(':MEASure:VOLTage?'), ureg.volt)

def get_measured_current(self):
return Q_(self.query(':MEASure:CURRent?'), ureg.ampere)

@current_protection_state.setter
def current_protection_state(self, val):
val = int(bool(val))
Expand Down
24 changes: 21 additions & 3 deletions instrumental/drivers/scopes/rigol.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import visa
from pyvisa.constants import InterfaceType
import numpy as np
from pint import UndefinedUnitError
from pint import UndefinedUnitError, UnitRegistry
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't look like this new import is used anywhere

from . import Scope
from .. import VisaMixin, SCPI_Facet, Facet
from ..util import visa_context
Expand All @@ -20,8 +20,8 @@
import numpy as np
from struct import unpack

_INST_PARAMS_ = ['visa_address']
_INST_VISA_INFO_ = {
_INST_PARAMS = ['visa_address']
_INST_VISA_INFO = {
'DS1000Z': ('RIGOL TECHNOLOGIES', ['DS1054Z']),
}

Expand Down Expand Up @@ -62,6 +62,9 @@ class RigolScope(Scope, VisaMixin):
A base class for Rigol Technologies Scopes
"""

probe1 = SCPI_Facet(':CHANnel1:PROBe', convert=float)
scale1 = SCPI_Facet(':CHANnel1:SCALe', convert=float)
timebase_main_scale = SCPI_Facet(':TIMebase:MAIN:SCALe', convert=float)
yinc = SCPI_Facet(':WAVeform:YINCrement', convert=float)
yref = SCPI_Facet(':WAVeform:YREFerence', convert=float)
yorig = SCPI_Facet(':WAVeform:YORigin', convert=float)
Expand Down Expand Up @@ -102,6 +105,18 @@ def beeper(self, val):
val = int(bool(val))
self.write('SYSTem:BEEPer %s' % OnOffState(val).name)

@property
def display_data(self):
return self._rsrc.query_binary_values(':DISPlay:DATA? ON,OFF,PNG', datatype='B', container=bytes)

@property
def ppulses_min(self):
return self.query(':MEASure:STATistic:ITEM? MINimum,PPULses')

@property
def ppulses_max(self):
return self.query(':MEASure:STATistic:ITEM? MAXimum,PPULses')

@property
def vmax_averages(self):
return self.query(':MEASure:STATistic:ITEM? AVERages,VMAX')
Expand All @@ -118,6 +133,9 @@ def vmin_averages(self):
def vmin(self):
return self.query(':MEASure:ITEM? VMIN')

def autoscale(self):
self.write(':AUToscale')

def get_data(self):
self.write(':WAV:SOUR CHAN1')
time.sleep(1)
Expand Down