Python-based instrument control - Page 1
Forum section: electronics / testgear

author: alex.forencich
author_rank: Frequent Contributor
timestamp: March 05, 2014, 07:40:30 am
content: There seems to be a growing interest on the forum in terms of cross-platform, extensible instrument control that isn't tied to a specific vendor. I have been working for some time on a collection of Python scripts that make up a cross-platform instrument control solution called Python IVI.http://github.com/alexforencich/python-iviThe idea is to create an abstraction layer that makes using various instruments straightforward, based on the IVI standard. Python IVI can then leverage Python VXI11, Python USBTMC, PySerial, and Linux GPIB to communicate with instruments. Python VXI11 is a pure Python VXI11 driver for LAN based instruments while Python USBTMC leverages PyUSB for instruments that support USBTMC. Everything except Linux GPIB support is cross-platform and has been tested in Linux, Windows, and Mac OS. Python IVI is also written so that it will work correctly in both Python 2 and Python 3.Python IVI is desgined so that it is easy to extend its functionality either with additional instrument control protocols (say, serial to GPIB devices like the Prologix units) or additional instruments.Currently, Python IVI supports a number of different instrument families - Agilent Infiniivision and Infiniium oscilloscopes, Agilent and Tektronix programmable power supplies, HP spectrum analyzers, Tektronix AWGs, and a number of other odds and ends. Things like waveform and screenshot readout are supported for most instruments.I would love for Python IVI to support a wide range of instruments, especially Rigol oscilloscopes. Unfortunately, I cannot write drivers for instruments that I do not have access to, so I would like to call upon anyone who is interested in extensible instrument control to lend a hand.If anyone here finds Python IVI useful and wishes to contribute, I would me more than happy to include your changes in Python IVI so that it can become an even more useful tool.

author: fake-name
author_rank: Regular Contributor
timestamp: March 05, 2014, 08:13:36 am
content: I use python a lot, and have access to both a DS4000 and DS1000Z oscilloscope.If I get a chance, I'll have a poke around. This is a cool project!

author: wiss
author_rank: Frequent Contributor
timestamp: March 18, 2014, 10:44:13 pm
content: Just got my gpib-card last week and started to play around a bit with python, I'll check this out!

author: alex.forencich
author_rank: Frequent Contributor
timestamp: March 18, 2014, 10:47:43 pm
content: Quote from: wiss on March 18, 2014, 10:44:13 pmNice! I presume you got a PCI GPIB card, then? What operating system are you using? If you're running linux, then Python IVI has support for using the linux-gpib python wrapper. I'm not sure what will work for windows, though. You may need to install the NI software and PyVISA. It's probably about time for me to add support for PyVISA to Python IVI to support that sort of setup.

author: psycho0815
author_rank: Regular Contributor
timestamp: March 19, 2014, 12:30:01 pm
content: looks not bad. i'll have a look at the documentation on how to write drivers. If it's not too much hassle, i might see what i can do about drivers for the rigol ds1052e and dg1022.

author: wiss
author_rank: Frequent Contributor
timestamp: March 19, 2014, 02:11:34 pm
content: Quote from: alex.forencich on March 18, 2014, 10:47:43 pmYup, Gentoo-Linux, no labview, I have only been talking to my multimeters but I do have a HP oscope, Philips counter and HP generator also.Are there any friendly GUI-widgets for like trend-plots and stuff somewhere?I'm using the matplotlib window now.

author: alex.forencich
author_rank: Frequent Contributor
timestamp: March 19, 2014, 05:32:26 pm
content: Quote from: fake-name on March 05, 2014, 08:13:36 amQuote from: fake-name on March 05, 2014, 08:13:36 amWriting drivers is not all that complicated. The hard part is just the sheer number of commands that each instrument supports. There is some documentation included with Python IVI that describes how to create a new driver.If you want to write some drivers for Python IVI, you should fork the repo and commit your changes to that, then send me a pull request.If you have any questions, feel free to ask by posting here or posting on the Python IVI google group.

author: alex.forencich
author_rank: Frequent Contributor
timestamp: March 19, 2014, 05:40:47 pm
content: Quote from: wiss on March 19, 2014, 02:11:34 pmWell, there might not be drivers yet for all of your equipment, but feel free to contribute if you have the time because I'm sure they will be useful to someone else.Right now Python IVI is just an abstraction layer that tries to provide common interfaces to similar instruments (e.g. for any scope, you should be able to do scope.channels.measurement.fetch_waveform() to read out the waveform data). There is no explicit support for graphing and logging, but these are rather simple operations to implement in python, especially if you want to do something more complicated (e.g. multiple instruments, conditional logging, etc.). Unfortunately I can't point you to anything other than matplotlib for plotting. Generally what I do is dump a csv file (or similar) and then process that separately, either in Excel/OpenOffice/LibreOffice or with another python script. No sense in a bug in the graphing portion of the script nixing the data before it's saved on disk.

author: wiss
author_rank: Frequent Contributor
timestamp: March 19, 2014, 06:04:34 pm
content: Quote from: alex.forencich on March 19, 2014, 05:40:47 pmI guess that implementing the DMM-class will be the startQuoteI'm very fond of the trend-plot on the 34461, which I do not have at home, seems like "trivial" to implement using PC/gpib. That I do not intend for saving data but rather real time viewing.

author: alex.forencich
author_rank: Frequent Contributor
timestamp: March 19, 2014, 06:19:01 pm
content: Quote from: wiss on March 19, 2014, 06:04:34 pmWhich DMM are you using?Quote from: wiss on March 19, 2014, 06:04:34 pmYeah, it should be pretty easy to implement. I have been mulling over a few GUI type extensions as well, but I do not think they belong in Python IVI directly. A separate package that imports Python IVI, sure.One thing that would be really nice is an offline scope trace viewer that supports all of the standard measurements, cursors, zooming, scaling, etc. as well as processing plugins for DSP filtering, serial decoding, clock recovery, line code removal for 8b/10b and 64b/66b, high level decoding (ethernet frames, etc.), single trace eye diagram generation, etc. The sort of stuff the Infiniium scopes can do (especially if you pay $$$$ for the decoding plugins), but with more flexibility and extensibility. It could even capture data in more-or-less realtime from a scope (or multiple scopes, even) with Python IVI as a back-end, as a step up from using VNC. That sort of thing would definitely be enough for a separate project. I think the sigrok project may do some of this, but I have not looked at that project in some time.

author: wiss
author_rank: Frequent Contributor
timestamp: March 19, 2014, 07:10:33 pm
content: Quote from: alex.forencich on March 19, 2014, 06:19:01 pmPrema 6001 and Keithley 192QuoteYes, like a labview widget thingie library.

author: wiss
author_rank: Frequent Contributor
timestamp: March 19, 2014, 10:26:54 pm
content: Quote from: wiss on March 19, 2014, 07:10:33 pmIt looks like the linux-gpib is written for SCPI-instruments, that have the ask concept, neither of my multimeters do it that way. Maybe there should be a linux-gpib-scpi class?To read something from the prema I send "VDR3L1PFS0" and when doing a read I get "+1.000001E+1VDR3A0T4S0Q0MOP0D0B0" back, as far as I understand from the manual that is the only way to communicate and don't really fit the "ask"-model.

author: alex.forencich
author_rank: Frequent Contributor
timestamp: March 19, 2014, 10:46:01 pm
content: Quote from: wiss on March 19, 2014, 10:26:54 pmWell, what is missing? As far as I understand it, the basic operations on the bus are 'read' and 'write', while 'ask ' is just a shortcut that calls 'write' and then 'read'. This is how the VXI-11 and USBTMC fdrivers work, anyway, and they're supposed to be equivalent to GPIB. You can also read just a specific number of characters, if reading more than that causes problems. It looks like when you read, you get a measurement, plus a bunch of status information. I imagine you get a similar string if you read without issuing a write call first. I think you're going to have to do a bit of creative parsing to get all of the status information organized, but I don't think a rewrite of the underlying library is required. Take a peek at the power meter drivers in Python IVI, agilent436A and agilent437B. They aren't terribly complete, but they have a very non-SCPI like interface.

author: zapta
author_rank: Super Contributor
timestamp: March 20, 2014, 06:55:07 am
content: Quote from: alex.forencich on March 05, 2014, 07:40:30 amDo you have screenshots?I am designing a simple battery current monitor and possibly Python IVI can provide the realtime display and gui.

author: alex.forencich
author_rank: Frequent Contributor
timestamp: March 20, 2014, 07:05:09 am
content: Python IVI is only an interface layer, there is no GUI component to it. You could use python IVI to read data from your instruments and then use matplotlib or similar to graph the data. I am not sure what the best real-time plotting solution would be, unfortunately.

author: wiss
author_rank: Frequent Contributor
timestamp: March 20, 2014, 07:23:32 pm
content: Quote from: alex.forencich on March 19, 2014, 10:46:01 pmI can not read without first having sent a command and when I do read a new measurement will be taken, the prema will block for one second in continuous mode (1 Hz update is the default) per read, and probably if set to measure on read will trigger a new measurement.What I'm thinking now is to... <>... hum, good! The front-panel buttons on the prema locks (apart from the "LOCAL" button) </>that there is a set of variables in the prema-dmm class holding the last read configuration and returning those values when a client request information. If a user changes the settings the information of course will be invalid. I guess that for SCPI-instruments the information is taken from the instrument directly?

author: alex.forencich
author_rank: Frequent Contributor
timestamp: March 20, 2014, 07:48:41 pm
content: Quote from: wiss on March 20, 2014, 07:23:32 pmHmm, that's interesting that it forces a measurement when you read. There is no way to read without taking a measurement, just to get all of the status information?Most of the SCPI type drivers also cache everything in local variables. The caching means that multiple reads of the same parameter will only result in one actual query to the instrument. It's assumed that nobody is monkeying around with the instrument while it is being controlled remotely. If you want to ensure this isn't a problem, enable the local lockout. If you don't want to make this assumption, then you can turn off caching or clear the cache (either set instrument.driver_operation.cache = False to disable the cache, or call instrument.driver_operation.invalidate_all_attributes() to clear the cache). Take a look at the existing drivers to see how the caching system is set up. It's pretty simple, and the cache check methods actually look at the call stack so you don't have to pass in the property name every time you need to check or update the cache, unless you are updating the cache for a different property. You will notice that on some drivers, setting certain properties will invalidate several others.The caching is probably reasonable for your instrument. I'm just wondering what the best implementation would be. You may have to have two 'master methods' - one to set all of the proper settings and take a measurement, and one to take a dummy measurement and then read in all of the settings. Unless you can find a way to read the settings without taking a measurement, anyway. The danger of forcing a measurement is that if it's set to take a triggered measurement, you may get a rather unexpected timeout and then possibly leave the instrument in a strange state (waiting for trigger). This may or may not be a problem with your meter, though.

author: wiss
author_rank: Frequent Contributor
timestamp: March 20, 2014, 08:07:43 pm
content: Ithinkthis is the only way, the gpib-section in the manual is only a few pages... but on the other hand I've only got like 3 evenings of experienceI'm thinking of taking a dummy VDC reading in "initialize" and then update the cache on every read or software change.

author: alex.forencich
author_rank: Frequent Contributor
timestamp: March 20, 2014, 08:13:21 pm
content: I would say take a dummy reading on the first read. No sense in taking a dummy reading on init if nothing is ever read. Also, enough experimentation could find a way to skip the dummy read, but you never know.

author: wiss
author_rank: Frequent Contributor
timestamp: March 20, 2014, 09:04:24 pm
content: This dummy-read will be the first point where the non-presences of the instrument will be noticed (like GPIB-cable fell out), therefore I'd like to have it in the "fopen"-routine.

author: alex.forencich
author_rank: Frequent Contributor
timestamp: March 21, 2014, 07:12:04 am
content: Well, whatever you think works best. The DiCon fiber optic switch driver does something along those lines; it queries the switch configuration (system:config?) on initialization to figure out what modules are installed and populate all of the proper fields accordingly.Also, I just finished reworking how Python IVI uses the instrument interface. If the ask, ask_raw, read, and/or write calls are missing, they will be emulated. The only required calls are now read_raw and write_raw. So if a custom interface is required, all it has to do is implement those two functions, and then it can be passed to Python IVI in place of a resource string. This might be useful for uncommon interfaces. It also means that you should now be able to use Python IVI with PyVISA, simply by passing a PyVISA instrument to Python IVI in place of the resource string. Unfortunately, I am unable to test this at the moment as I do not have an accessible installation of NI VISA.

author: alex.forencich
author_rank: Frequent Contributor
timestamp: March 21, 2014, 09:33:03 pm
content: I just got my Scientific Linux VM working again, and I properly implemented PyVISA support. Now, if you have PyVISA installed, Python IVI will fall back on PyVISA if other communication interfaces are not installed. It is also possible to tell Python IVI to prefer PyVISA, in which case it will try PyVISA first and then fall back on other options.

author: awallin
author_rank: Frequent Contributor
timestamp: March 22, 2014, 09:24:18 am
content: FWIW, some notes on how to use GPIB under linux, tested with two different NI devices (USB and PCI-E card)http://www.anderswallin.net/2013/11/gpib-on-linux/I've also used a time-interval counter through Ethernet based LXI, but I fail to remember the python library name...

author: Noise Floor
author_rank: Regular Contributor
timestamp: March 22, 2014, 06:09:40 pm
content: Quote from: alex.forencich on March 20, 2014, 07:05:09 amNumPy + Matplotlib?

author: alex.forencich
author_rank: Frequent Contributor
timestamp: March 25, 2014, 05:10:35 am
content: Quote from: Noise Floor on March 22, 2014, 06:09:40 pmThat would be one solution. Not sure how well matplotlib works for real-time plotting, though.There was a mention of Kst on another post here for plotting logged data. It looks like a pretty promising solution. I will look in to putting together a sample logging script that can be used with Kst, as that could be a very powerful combination.

author: hochopeper
author_rank: Unknown
timestamp: March 25, 2014, 12:09:39 pm
content: For realtime plots I think the new plotting library being developed mainly by the continuum.io folks ...http://bokeh.pydata.orgBokeh has client server architecture and realtime plotting appears to be on the agenda for improvements. This should I hope (I've not used it yet) allow the GUI of the plot operate independently of the data acquisition.

author: alex.forencich
author_rank: Frequent Contributor
timestamp: March 26, 2014, 08:20:51 am
content: Quote from: hochopeper on March 25, 2014, 12:09:39 pmThat looks like it could be pretty interesting as well. Unfortunately, it seems the AUR package for Arch Linux is broken, so I have not been able to install it yet.I think I'm going to start by taking a look at Kst - it seems to have some sort of real-time capability. I will look in to writing a basic logging script for my 34401A this week.

author: mrflibble
author_rank: Super Contributor
timestamp: March 27, 2014, 10:09:37 pm
content: Quote from: alex.forencich on March 26, 2014, 08:20:51 amI'd have to agree on the choice of kst. Bokeh looks sorta cute, but"yes, we are working on improvements for real-time"!="works well in real-time". If you want bokeh-like pretty-plot functionality but significantly more awesome++ (IMO), then it's ggplot2 time. And I noticed that ggplot2 now also works from python, for example through rpy. w00t! So I'll be checking that one for low update rate high quality plots, which just happen to also be highly pdf exportable with zero extra effort.And for high update rate & large amounts of data & real time goodness kst indeed looks promising.And thank you very much Mr Alex sir, for python-ivi and python-vxi11.Today I received my DSA815-TG, and got it python scripted in < 30 mins from T_out_of_box.I also made a little script based on your python-vxi11 that automates rikey_dsa calls, so execute script ==> install the 10 Hz RBW license (*).(*)Or any of the other licenses you care for. I just used the 10 Hz RBW license to test the procedure. Worked in one go! Well, two goes. Had to remove the minus characters from the license key that rikey_dsa spits out.So far I like python-vxi11, and will use it in future scripts. Haven't really used the ivi side of it yet. I'll probably try to extend some random class for use with the DSA815-TG, and see how that goes. Oh yeah, one thing I noticed: the timeouts are hardcoded? Or did I miss the magic method?

author: alex.forencich
author_rank: Frequent Contributor
timestamp: March 28, 2014, 03:19:27 am
content: Quote from: mrflibble on March 27, 2014, 10:09:37 pmKst does look pretty good, I have been using it to look at a couple of scope traces that I saved in csv format and it appears to work quite nicely. I have not had a chance to try out real-time plotting yet, though.If you want to work on a python-ivi driver for the Rigol DSA units, that would be excellent. Actually, the spectrum analyzer base class is not completely finished at the moment, not much more than the base class is implemented. The basic functionality is covered, though. Finishing that off is on my to-do list. Also, the IVI spectrum analyzer spec doesn't include tracking generators, so I will have to find a way to add that functionality in somehow. I have an HP 8595E with a tracking generator that I would like to support completely. I would suggest working off of the Agilent 8590E driver. You may just need to substitute the proper commands from the Rigol programmer's manual to get most of it working.In terms of setting timeouts, that is certainly possible. If you're using vxi11 directly, then you can just set instr.timeout to what you need. Right now the units are in ms, but I suppose that could be changed to seconds. If you're using vxi11 through python-ivi, the vxi11 instance will be called _interface so you can just set instr._interface.timeout to what you need.

author: alex.forencich
author_rank: Frequent Contributor
timestamp: March 31, 2014, 08:27:22 am
content: Alright, here is some example logging code for use with Kst. There are a few variables at the top - file_name, sample_period, and sample_count - as well as the call to Python IVI to connect to the instrument. Configure these as necessary. This script does not actually configure the instrument for whatever measurement you need; all it does is read samples from a multimeter. So you can either configure the meter manually before starting the script, or you can add code after the ivi call to set up the measurement. The samples (along with a timestamp) are written to a csv file. Before starting, the script also writes out an xml file for Kst. Now, the XML file that it writes is a bit hacked together, I just saved one out of Kst and hen stripped out a bunch of stuff, so it might not be terribly ideal. But it worked for the limited testing I have done so far. To use this thing, start the script in python, then open up the generated .kst file in Kst. As the data is collected, Kst will automatically load and display the new data points. The script will stop automatically after collecting the specified number of samples. It should also stp if there is an error communicating with the instrument, or if the script is interrupted with ctrl c.The timing loop is set up so that the script attempts to 'make up for lost time' if there is a mis-timed sample somewhere. However, I am not sure if the time calls will have the same resolution on all platforms.Code:import iviimport timedmm = ivi.agilent.agilent34401A("TCPIP::192.168.1.105::gpib,22::INSTR")file_name = 'log'sample_period = 2.0sample_count = 100fp = open(file_name '.csv', 'w')kp = open(file_name '.kst', 'w')kp.write("""<?xml version="1.0" encoding="UTF-8"?><kst version="2.0"><data><source reader="ASCII file" file="{0}.csv"><properties vector="INDEX" interpretation="1" delimiters="#" columntype="2" columndelimiter="," headerstart="1" fields="0" readfields="true" usedot="true" columnwidthisconst="false" readunits="false" units="0" limitFileBuffer="false" limitFileBufferSize="0" useThreads="0" asciiTimeFormat="hh:mm:ss.zzz" dataRate="1" offsetDateTime="false" offsetFileDate="false" offsetRelavive="true" dateTimeOffset="2014-03-24T22:16:59" relativeOffset="0"/></source></data><variables><datavector file="{0}.csv" field="time" start="0" count="15985" skip="-1" doAve="false" startUnits="" rangeUnits="" initialVNum="1" initialXNum="25"/><datavector file="{0}.csv" field="sample" start="0" count="15985" skip="-1" doAve="false" startUnits="" rangeUnits="" initialVNum="2" initialXNum="37"/></variables><objects/><relations><curve xvector="time (V1)" yvector="sample (V2)" color="#0000ff" headcolor="#008000" barfillcolor="#000000" haslines="true" linewidth="0" linestyle="0" haspoints="false" pointtype="3" pointdensity="0" pointsize="12" hasbars="false" ignoreautoscale="false" hashead="false" headtype="0" initialCNum="1"/></relations><graphics><view name="View &1" width="1470" height="633" color="#ffffff" style="1"><plot tiedxzoom="false" tiedyzoom="false" leftlabelvisible="true" bottomlabelvisible="true" rightlabelvisible="true" toplabelvisible="true" globalfont="Sans,10,-1,5,50,0,0,0,0,0" globalfontscale="16" globalfontcolor="#000000" showlegend="true" hidebottomaxislabel="false" hidetopaxislabel="false" hideleftaxislabel="false" hiderightaxislabel="false" numberaxislabelscale="true" initialPlotNum="1" name="Plot"><relativesize width="1" height="1" centerx="0.5" centery="0.5" posx="0" posy="0" leftx="0" lefty="1" rightx="1" righty="1" fixaspect="false" lockpostodata="false"/><cartesianrender name="Cartesian Plot" type="1"><relation tag="sample vs time (C1)"/></cartesianrender></plot></view></graphics></kst>""".format(file_name))kp.close()fp.write("time, sample\n")target_time = time.time() sample_periodfor sample in range(sample_count):last_sample_time = time.time()sample_value = dmm.measurement.read(1)print(sample_value)fp.write("%f, %g\n" % (last_sample_time, sample_value))fp.flush()offset = target_time - time.time()if offset > 0:time.sleep(offset)target_time = sample_period

author: mrflibble
author_rank: Super Contributor
timestamp: April 01, 2014, 02:36:34 am
content: I've been mucking about with kst a bit as well. Getting a simple plot working was totally trivial, but for things like a DataMatrix I find the available documentation and examples frustratingly lacking in detail. IhopeI am just blind and unable to find the right docs. But what I could find (KstBook.pdf or some such) does not do the trick for me. "Use this incomplete example and it will work". Yes, except for all the other instances and 45987 permutations of those instances where it doesn't. "You can use xml files." Oh cool! Any docs on that? "Docs? What now?"Do you happen to have an example of a datasource (defined in xml or kstscript or whatever) using an ascii file for the matrix data. Or at this point, anything that works at all?Like I said, simple plot, too easy. Datasource + datamatrix according to the docs ... nope.Mostly I am confuzled by the "[MATRIX,size-or-something,0,0,1,1]" part of it. That I can understand reading the docs. Except that it doesn't work as advertised.Oh another thing that maybe you know ... is there any way to "overwrite" old datapoints in real time? To get a sort of oscilloscope display as it were. I suppose you could do that by just resetting the data + refreshing the plot, but that seems a bit lame.At the moment I can get a spectral waterfall plot with a static matrix as data. I can also grab the spectrum from the DSA815. Oh if only certain documentation didn't suck so bad, then I could do a waterfall plot from the DSA815 in real-time. Grrrrr.I'll get back to it later, but for now I am fed up with this.

author: alex.forencich
author_rank: Frequent Contributor
timestamp: April 01, 2014, 03:40:07 am
content: I have not looked at any Kst documentation so far, actually. All I did was put together something decent in the Kst GUI, then I saved the xml file and played around with it. But I wasn't trying to do anything more complicated than a single curve of one variable, so this might not be the best strategy for everyone.It's not surprising the documentatio is bad, that tends to happen a lot with open source projects. For Pyton IVI, am trying to mitigate this issue to some extent by merging the documentation with the code as much as possible, but it remains to be seen how well this will work. And this is certainly not the best solution for every project.I would suggest trying to save an XML file from Kst, and then playing around with that file and reloading it. It may be faster to figure out how the application works by actually running it than from looking at outdated and/or incomplete documentaion.

author: Noise Floor
author_rank: Regular Contributor
timestamp: May 22, 2014, 01:31:24 am
content: Quote from: mrflibble on April 01, 2014, 02:36:34 amI too have been playing with Kst and have the same complaint. However this is par for the course for projects like this, if it catches on, documentation will eventually improve.Alex F., any thought on starting a GitHub project around this?

author: alex.forencich
author_rank: Frequent Contributor
timestamp: May 22, 2014, 01:54:25 am
content: Quote from: Noise Floor on May 22, 2014, 01:31:24 amAround what? Scripts for writing out Kst files? General python-based data logging? Combination of the two? Give me a nice projct name and I'll throw up a repo.Unfortunately, my time has been almost completely devoted to a few other projects the past few weeks (fyi: the Altera reference design for PCIe gen 3 SUCKS, I found 3 different bugs in it already), and they Python instrument control stuff is currently on the back burner.

author: Noise Floor
author_rank: Regular Contributor
timestamp: May 22, 2014, 02:40:59 am
content: Quote from: alex.forencich on May 22, 2014, 01:54:25 amIgnore my comment, I now noticed your signature.I hear you on having to many projects, this falls in the "nice to do" category.

author: alex.forencich
author_rank: Frequent Contributor
timestamp: May 22, 2014, 03:14:40 am
content: Quote from: Noise Floor on May 22, 2014, 02:40:59 amNo worries. Actually, the instrument control stuff is something that we're looking in to using for taking some measurements on some experimental photonic switching chips (we have two different ones we're hoping to work with soon, one MEMS based and one silicon photonics based). Taking measurements of these switches requires coordinating not only the signal sources, sinks, and routing, but also changing the switch configuration itself, so it's a pretty complicated interfacing issue. The idea is to use Python to control the test equipment as well as an FPGA to drive the DUT. So even if it's on the back burner for the moment, it's going to pick up again once we're gearing up to test one of the switches.

author: miguelvp
author_rank: Super Contributor
timestamp: May 20, 2015, 07:28:44 am
content: Waking up this thread.So in:https://www.eevblog.com/forum/testgear/new-rigol-ds1054z-oscilloscope/msg675845/#msg675845Bingo found this link for the DS1000z series to perform a screen capture.Quote from: bingo600 on May 18, 2015, 07:11:40 pmI did try it on my DS2000 scope but I guess it doesn't have telnet capabilities. So I did stumble on alex.forencich's vxi11 and I substitute it and I was able to do the capture on my DS2000, but it took 2 minutes and 40 seconds per capture.https://www.eevblog.com/forum/testgear/new-rigol-ds1054z-oscilloscope/msg676102/#msg676102So I used wireshark to check what is going on, and for some reason it doesn't like to read large packets and I did modified the script again so it wouldn't go past the MTU size of 1514 bytes and:QuoteAnd it took just 4 seconds (I know it says 3 but a wireshark capture shows it was 3.98 seconds).So here is the newest version of the script:Code:__author__ = 'RoGeorge'## Modified to work with DS2000 by miguelvp# using vxi11 by Alex Forencich and Michael Walle# https://github.com/alexforencich/python-vxi11#import vxi11import timeimport sysimport osimport Imageimport StringIOfrom datetime import datetime# Update the next lines for your own default settings:path_to_save = ""IP_DS2000 = "192.168.1.6"expected_len = 1152067TMC_header_len = 11terminator_len = 2company = 0model = 1serial = 2# Check parametersscript_name = os.path.basename(sys.argv)# Print usageprintprint "Usage:"print " " + script_nameprintprint "This program capture the image displayed"print " by a Rigol DS2000 series oscilloscope, then save it on the computer"print " as a PNG file with a timestamp in the file name."printprint " The program is using LXI protocol, so the computer"print " must have LAN connection with the oscilloscope."print " USB and/or GPIB connections are not used by this software."printprint " No VISA, IVI or Rigol drivers are needed."print# Create/check if 'path' exists# Check network response (ping)response = os.system("ping -n 1 -w 20 " + IP_DS2000 + " > nul")if response != 0:printprint "No response pinging " + IP_DS2000print "Check network cables and settings."print "You should be able to ping the oscilloscope."sys.exit("ERROR")# Open a VXI11 sessioninstr = vxi11.Instrument(IP_DS2000)instrument_id = instr.ask("*IDN?")# Check if instrument is set to accept LAN commandsif instrument_id == "command error":print instrument_idprint "Check the oscilloscope settings."print "Utility -> IO Setting -> LAN Set"sys.exit("ERROR")# Check if instrument is indeed a Rigol DS2000 seriesid_fields = instrument_id.split(",")if (id_fields != "RIGOL TECHNOLOGIES") or \(id_fields[:3] != "DS2"):printprint "ERROR: No Rigol from series DS2000 found at ", IP_DS2000sys.exit("ERROR")print "Instrument ID:"print instrument_id# Prepare filename as C:\MODEL_YYYY-MM-DD_HH.MM.SStimestamp = time.strftime("%Y-%m-%d_%H.%M.%S", time.localtime())filename = path_to_save + id_fields + "_" + timestamp# Ask for an oscilloscope display print screeninstr.write_raw("display:data?")# Time transfer durationstarttime = datetime.now()# Get TMC Headerbuff = instr.read_raw(TMC_header_len)# Initialize previous progress so we only update on changesprevious_progress = -1;# Read only 1420 bytes at a time until done, a bigger amount stalls the rpc and makes the transfer slowwhile len(buff) < expected_len:tmp = instr.read_raw(1420)if len(tmp) == 0:breakbuff += tmp# Compute and print progress barprogress = 100 - (expected_len - len(buff))*100/expected_lenif (previous_progress != progress):sys.stdout.write('\rReceiving: [{0}] {1}%'.format('#'*(progress/10)+' '*(10-progress/10), progress))sys.stdout.flush()previous_progress = progress# Print delta time in secondscurrenttime = datetime.now()delta = currenttime - starttimeprintprint "Read took", delta.seconds, "seconds"# Strip TMC Blockheader and terminator bytesbuff = buff[TMC_header_len:-terminator_len]# Save as PNGim = Image.open(StringIO.StringIO(buff))im.save(filename + ".png", "PNG")print "Saved file:", filename + ".png"# Save as BMP# scr_file = open(filename + ".bmp", "wb")# scr_file.write(buff)# scr_file.close()# print "Saved file:", filename + ".bmp"# Close Instrumentinstr.close()It has a progress bar and allSo it's40 times fasterthan the 160 seconds it was taking before and it's even faster than saving it to a thumb drive!Thank you Alex for providing thisIf you notice I did change the raw read to 1420 at a time instead of:Code:buff = instr.ask_raw("display:data?", expected_len)So I decided to change vxi11.py open from:Code:self.max_recv_size = min(max_recv_size, 1073741824)to:Code:self.max_recv_size = min(max_recv_size, 1420)and I can revert back the code and achieve the same speed, but I do like the progress bar so I think I'll keep mine like it is and changed the size in both places.Since you support other protocols other than VXI-11 over TCP I guess I'll leave it up to you to do the change to have the right MTU per protocol, but for TCPIP it seems 1420 is the best, if I use 1421 it causes extra TCP continuation packets and it stalls the transfer but with 1420 it's just perfect!Wireshark happy:Capture PNG:Thank you again alex.forencich!!

author: alex.forencich
author_rank: Frequent Contributor
timestamp: May 20, 2015, 07:34:28 am
content: Nice work! Is there any issue with just doing instr.max_recv_size = 1420 and then using the standard read call?Edit: never mind, I just looked at the code for python-vxi11. I wonder if I need to add a max_block_size parameter so that this will be done automatically in read_raw. Also, are you sure the screenshots are always exactly the same size?

author: miguelvp
author_rank: Super Contributor
timestamp: May 20, 2015, 07:48:28 am
content: As for the screenshots, on the ds2000 they are always the same:But on the DS1000Z it seems it has an extra byte at the end.I didn't try the instr.max_recv_size = 1420 I guess that would work too, I just found your python project yesterday so I didn't dig that much into itEdit: I guess I could just parse the blockheader and figure out the size of what to read.

author: alex.forencich
author_rank: Frequent Contributor
timestamp: May 20, 2015, 08:00:59 am
content: There is actually some code to do that in python-ivi, see read_ieee_block. It deals with parsing the header correctly and then reading out the correct number of bytes. However, it does try to read it all in one shot, so it seems that an additional parameter to specify the maximum read size would be a good idea.

author: miguelvp
author_rank: Super Contributor
timestamp: May 20, 2015, 08:07:14 am
content: That's awesome, thanks.One question, why are the timeouts set to 10 seconds? I did change them locally to 1 second and it works fine._timeout & _lock_timeout

author: alex.forencich
author_rank: Frequent Contributor
timestamp: May 20, 2015, 08:13:28 am
content: Actually, the timeouts should probably be extended quite a bit. I have to remember to change the timeout setting to a minute or so when yanking screenshots from a few older instruments (namely my 8593E SA) through my GPIB to LAN box. The default right now was just something that seemed reasonable at the time. I would say that it's probably a better idea to extend those timeouts as much as is reasonable as it's better to have to wait a while for a timeout than to get a timeout during a large transfer. With something like python-ivi, this could even be changed at run time for specific commands. This is a major issue with the USBTMC side of things as getting a timeout during a transfer usually requires rebooting the instrument to recover.

author: miguelvp
author_rank: Super Contributor
timestamp: May 20, 2015, 09:12:36 am
content: Maybe the high timeouts are needed due to the overhead of using large read sizes.Didn't look at the code and it's late, but splitting the reads to smaller sub chunks will require smaller timeouts, right?

author: gmb42
author_rank: Frequent Contributor
timestamp: May 20, 2015, 11:20:14 am
content: FWIW, to anonymise Wireshark captures have a look atTraceWrangler.

author: alex.forencich
author_rank: Frequent Contributor
timestamp: May 20, 2015, 03:56:45 pm
content: It should never timeout during normal operation.

author: VintageNut
author_rank: Frequent Contributor
timestamp: May 20, 2015, 07:00:44 pm
content: I have written short demo python programs for Keithley 2230-30-1 power supply, Keithley 236 and 237 SMUs for transistor curve tracing and Keithley 3706A with 3720 switch card. These were all efforts to get a particular instrument behavior characterized and/or take readings.I have a Keithley model 7001 on the way that will receive the python treatment for nanovolt measurements.

author: bingo600
author_rank: Super Contributor
timestamp: May 20, 2015, 08:57:06 pm
content: Quote from: miguelvp on May 20, 2015, 07:28:44 amGreat find(debugging)Now i'll have to install VXI-11 , also because i know Alex might have improved the linux-gpib support/Bingo

author: eas
author_rank: Frequent Contributor
timestamp: July 24, 2015, 09:37:18 pm
content: Quote from: VintageNut on May 20, 2015, 07:00:44 pmDid you create IVI instrument drivers for any of these? If so, do you mind sharing them somewhere? I have started working with some K2000 and K2700 DMMs and would like to see how much can be reused, particularly for switch control. Right now I'm just issuing SCPI commands over VXI-11 (I'm using an ICS 8065).

author: VintageNut
author_rank: Frequent Contributor
timestamp: July 25, 2015, 07:09:00 pm
content: I did not create any driver(s). I just send SCPI commands via PyVisa which is via NI Visa. I use Python 2.7

author: eas
author_rank: Frequent Contributor
timestamp: July 26, 2015, 07:03:54 am
content: Thanks for the clarification.

author: chaugen1
author_rank: Newbie
timestamp: April 18, 2016, 02:39:38 pm
content: Sorry to wake up an old thread. Can start a new one if necessary.I would love to contribute to this project. I am working on a driver for the Agilent U2701A USB Modular Oscilloscope and would be happy to share once I have it done and tested.In the meantime, I need some help. I have usbtmc installed and it can see the instrument but when I try to ask it for anything, PyUSB throws up a "Error 32: Pipe Error"Here is output: first the device as seen from PyUSB:Code:DEVICE ID 0957:2818 on Bus 002 Address 005 =================bLength : 0x12 (18 bytes)bDescriptorType : 0x1 DevicebcdUSB : 0x200 USB 2.0bDeviceClass : 0x0 Specified at interfacebDeviceSubClass : 0x0bDeviceProtocol : 0x0bMaxPacketSize0 : 0x40 (64 bytes)idVendor : 0x0957idProduct : 0x2818bcdDevice : 0x100 Device 1.0iManufacturer : 0x1 Agilent TechnologiesiProduct : 0x2 Agilent U2701A/U2702AiSerialNumber : 0x3 MY********bNumConfigurations : 0x1CONFIGURATION 1: 100 mA ==================================bLength : 0x9 (9 bytes)bDescriptorType : 0x2 ConfigurationwTotalLength : 0x61 (97 bytes)bNumInterfaces : 0x1bConfigurationValue : 0x1iConfiguration : 0x0bmAttributes : 0xc0 Self PoweredbMaxPower : 0x32 (100 mA)INTERFACE 0: Reserved ==================================bLength : 0x9 (9 bytes)bDescriptorType : 0x4 InterfacebInterfaceNumber : 0x0bAlternateSetting : 0x0bNumEndpoints : 0x4bInterfaceClass : 0x0 ReservedbInterfaceSubClass : 0x0bInterfaceProtocol : 0x0iInterface : 0x0ENDPOINT 0x81: Interrupt IN ==========================bLength : 0x7 (7 bytes)bDescriptorType : 0x5 EndpointbEndpointAddress : 0x81 INbmAttributes : 0x3 InterruptwMaxPacketSize : 0x40 (64 bytes)bInterval : 0x1ENDPOINT 0x1: Interrupt OUT ==========================bLength : 0x7 (7 bytes)bDescriptorType : 0x5 EndpointbEndpointAddress : 0x1 OUTbmAttributes : 0x3 InterruptwMaxPacketSize : 0x40 (64 bytes)bInterval : 0x1ENDPOINT 0x82: Bulk IN ===============================bLength : 0x7 (7 bytes)bDescriptorType : 0x5 EndpointbEndpointAddress : 0x82 INbmAttributes : 0x2 BulkwMaxPacketSize : 0x200 (512 bytes)bInterval : 0x0ENDPOINT 0x2: Bulk OUT ===============================bLength : 0x7 (7 bytes)bDescriptorType : 0x5 EndpointbEndpointAddress : 0x2 OUTbmAttributes : 0x2 BulkwMaxPacketSize : 0x200 (512 bytes)bInterval : 0x0INTERFACE 0, 1: Reserved ===============================bLength : 0x9 (9 bytes)bDescriptorType : 0x4 InterfacebInterfaceNumber : 0x0bAlternateSetting : 0x1bNumEndpoints : 0x6bInterfaceClass : 0x0 ReservedbInterfaceSubClass : 0x0bInterfaceProtocol : 0x0iInterface : 0x0ENDPOINT 0x81: Interrupt IN ==========================bLength : 0x7 (7 bytes)bDescriptorType : 0x5 EndpointbEndpointAddress : 0x81 INbmAttributes : 0x3 InterruptwMaxPacketSize : 0x40 (64 bytes)bInterval : 0x1ENDPOINT 0x1: Interrupt OUT ==========================bLength : 0x7 (7 bytes)bDescriptorType : 0x5 EndpointbEndpointAddress : 0x1 OUTbmAttributes : 0x3 InterruptwMaxPacketSize : 0x40 (64 bytes)bInterval : 0x1ENDPOINT 0x82: Bulk IN ===============================bLength : 0x7 (7 bytes)bDescriptorType : 0x5 EndpointbEndpointAddress : 0x82 INbmAttributes : 0x2 BulkwMaxPacketSize : 0x200 (512 bytes)bInterval : 0x0ENDPOINT 0x2: Bulk OUT ===============================bLength : 0x7 (7 bytes)bDescriptorType : 0x5 EndpointbEndpointAddress : 0x2 OUTbmAttributes : 0x2 BulkwMaxPacketSize : 0x200 (512 bytes)bInterval : 0x0ENDPOINT 0x83: Isochronous IN ========================bLength : 0x7 (7 bytes)bDescriptorType : 0x5 EndpointbEndpointAddress : 0x83 INbmAttributes : 0x1 IsochronouswMaxPacketSize : 0x40 (64 bytes)bInterval : 0x1ENDPOINT 0x3: Isochronous OUT ========================bLength : 0x7 (7 bytes)bDescriptorType : 0x5 EndpointbEndpointAddress : 0x3 OUTbmAttributes : 0x1 IsochronouswMaxPacketSize : 0x40 (64 bytes)bInterval : 0x1And here is what I get when I try to probe it:Code:>>> import usbtmc>>> instr = usbtmc.Instrument(0x0957,0x2818)>>> print(instr.ask("*IDN?"))Traceback (most recent call last):File "<stdin>", line 1, in <module>File "build/bdist.linux-x86_64/egg/usbtmc/usbtmc.py", line 607, in askFile "build/bdist.linux-x86_64/egg/usbtmc/usbtmc.py", line 587, in writeFile "build/bdist.linux-x86_64/egg/usbtmc/usbtmc.py", line 467, in write_rawFile "build/bdist.linux-x86_64/egg/usbtmc/usbtmc.py", line 341, in openFile "build/bdist.linux-x86_64/egg/usbtmc/usbtmc.py", line 677, in clearFile "/usr/local/lib/python2.7/dist-packages/usb/core.py", line 1043, in ctrl_transferself.__get_timeout(timeout))File "/usr/local/lib/python2.7/dist-packages/usb/backend/libusb1.py", line 883, in ctrl_transfertimeout))File "/usr/local/lib/python2.7/dist-packages/usb/backend/libusb1.py", line 595, in _checkraise USBError(_strerror(ret), ret, _libusb_errno)usb.core.USBError: [Errno 32] Pipe error>>>Anyone have any thoughts on this?Thanks so much.

author: douardda
author_rank: Regular Contributor
timestamp: April 18, 2016, 05:48:11 pm
content: Quote from: hochopeper on March 25, 2014, 12:09:39 pmPeople looking for plotting libraries for python might be interested in pyqtgraph alsohttp://www.pyqtgraph.org/i haven't really used it for now but it looks very powerfulDavidEnvoyé de mon GT-N7105 en utilisant Tapatalk

author: bson
author_rank: Unknown
timestamp: April 18, 2016, 09:14:16 pm
content: Quote from: chaugen1 on April 18, 2016, 02:39:38 pmThe datasheet says USBTMC (GPIB tunneled over USB) but googling seems to suggest Agilent actually uses an FTDI serial port. If so you may need to add a device rule for that vid,pid to configure a serial port (canonically named /dev/ttyUSB<n>). If that works, use the serial port to talk to it, issuing the same SCPI commands or whatever it accepts. The drawback with this scheme is the device can't issue SRQs or otherwise asynchronously request the host's attention.

author: chaugen1
author_rank: Newbie
timestamp: April 18, 2016, 11:58:51 pm
content: Thanks for the feedback. I took a look and there is in fact no new device that shows up when I plug in the o-scope and checkls /dev. Out of curiosity, I took it apart and the USB controller is actually NXP ISP1583BS.Do any of you know if this controller is USBTMC compatible/capable?

author: bson
author_rank: Unknown
timestamp: April 19, 2016, 01:25:16 am
content: Perhaps you need a rule for it to create /dev/usbtmc for that vid,pid and a usbtmc driver? Not sure what the python code does and if it expects a driver.Did you follow the instructions for configuring udev?https://github.com/python-ivi/python-usbtmcWhat if you do "lsusb -t" to view the device tree, do you see the driver for it? Is the kernel usbtmc driver loaded (lsmod)? If not, try loading it after adding the device udev rules. Or try unloading it if it is.

author: KSP
author_rank: Regular Contributor
timestamp: October 03, 2016, 12:00:14 pm
content: Sorry to revive this thread once more, and sorry again if this is a repeat question as I have not trawled through all three pages of this threadBut does python-ivi require you to write ivi drivers for all devices used, or is it possible for an existing ivi-c or ivi-com driver to be used?I've had a little success with ivi-com drivers using the 'comtypes' module, but it is in no way seamless

author: alex.forencich
author_rank: Frequent Contributor
timestamp: February 15, 2017, 05:26:13 am
content: Quote from: chaugen1 on April 18, 2016, 02:39:38 pmThe U2701A should be USBTMC capable. However, it needs to be initialized first. If it comes up with idProduct 0x2818, it's in some sort of firmware update mode. The Agilent drivers then check the firmware version, possibly update it, then send a command to reset into the actual firmware. In this case, idProduct will be 0x2918 and it will operate as a USBTMC device. This needs to be emulated when the Agilent drivers are not present. At least, this is extrapolating from the U2723A that I have; I figure all of the Agilent instruments of that style all operate the same way.Support for the U2701A/U2702A is currently in the works, see:https://github.com/python-ivi/python-usbtmc/issues/31. I'm waiting on a wireshark trace with the boot sequence.

author: LEDPaul
author_rank: Newbie
timestamp: April 05, 2018, 02:02:04 pm
content: Just started to learn about Python-IVI. So far I wrote my own stuff, but to redo everything for each new machine is not really efficient. So probably better to use Python-IVI. Next machine I will add is probably the Agilent/Keysight 34465A DMM. It has some functions that the older models do not have, or I have not found it yet, or the support was not written yet. So I need to learn to expand it. I have some other machines that I probably can convert, but that will be later.Is this the place to best ask questions on Pyhthon-IVI or do that better on github?Also if anyone has some more complex examples on hot to use a dmm in python-ivi I would love to see that.

author: alm
author_rank: Super Contributor
timestamp: April 08, 2018, 10:09:16 am
content: I attached a script that I used to collect measurements from a DMM through Python-IVI at different integration times, so I could determine the noise (is it better to average 100 measurements with 1 s integration time, or 10 measurements with 10 s integration time?). This is the general pattern I have been using: ininit_func()I set up whatever instruments I want to use and set their range, function, etc, and inloop_func()I collect the measurements. If I need to do something else, I only have to modify these two functions.

author: LEDPaul
author_rank: Newbie
timestamp: April 23, 2018, 03:18:40 pm
content: I mannaged to get my 34465A working with python-ivi. I can measure the current at 200us interval and read 1000 or even 50k samples. To be able to do this I added some functions to python-IVI locally. Below the user code to read the current:Code:dmm = ivi.agilent.agilent34465A("USB0::0x2A8D::0x0101::MYxxxxxxxx::0::INSTR")dmm.configure('dc_current', 10e-3, 1e-9)dmm.advanced.auto_zero = 'once'dmm.advanced.aperture_time = 200e-6dmm.trigger.delay = 0.0dmm.trigger.source = 'bus'dmm.trigger.multi_point.configure(trigger_count=1,sample_count=1000,sample_trigger='TIM',sample_interval=200e-6)dmm.measurement.initiate()dmm.send_software_trigger()sleep(1000 * 200e-6)res = dmm.measurement.fetch_multi_point(1000 * 200e-6, 1000)code for the 34465A can be found here:https://github.com/phsdv/python-ivi

author: RoGeorge
author_rank: Super Contributor
timestamp: January 02, 2021, 06:46:08 pm
content: Just installed python-ivi and python-vxi11 these days fromhttps://github.com/python-ivi/python-iviand it works great, thank you!Also, found yesterday another repositoryhttps://github.com/alexforencich/python-ivi/And yet another branch with a pull request for Rigol oscilloscope drivers (I am not very good with git/github):https://github.com/ianrrees/python-ivi/I am looking for python-ivi drivers for Rigol DS1104Z (DS1000Z) oscilloscope and Rigol DG4202 (DG4000) generator.Not sure if there are any working python-ivi drivers for the above Rigol osc and generator, or which one to use. I have other questions, too, mainly regarding finding the latest python-ivi drivers, summarized in a separate topic:https://www.eevblog.com/forum/metrology/software-for-automated-testing-(scpi)/msg3397446/#msg3397446Any hints, please?