Problems Writing code for GPIB Py VISA   - Page 1
Forum section: electronics / projects

author: dazz1
author_rank: Frequent Contributor
timestamp: December 20, 2023, 09:52:54 pm
content: HiI have assembled Xyphro's excellent USB:GPIB adapter at this linkhttps://www.eevblog.com/forum/testgear/open-source-gpib-adapter/I now have the problem of writing code to make use of the adapters. I have decided to use Python and PyVISA. I am new to Python and GPIB.My target test equipment includes:WaveTek 2520 RF signal generator 200kHz-2.2GHzHP 3478A MultimeterHP 54645D 100MHz DSOElectro-Metrics EMC30 - an obsolete Mil-Spec emc receiverAll of these are notably ancient so for at least two of them, there is no point in asking questions like: "How do I program for my WaveTek 2520" when there is probably me and no-one else on the planet that want to run such an antique instrument over GPIB.I plan to use this thread as the place I ask generalised questions about specific problems I am, or likely, to have. I anticipate others like me will have questions of their own. I searched the internet for an active PYVISA forum, but none found.

author: dazz1
author_rank: Frequent Contributor
timestamp: December 20, 2023, 10:16:56 pm
content: I have started to program a test program in Python for my WaveTek 2520 RF Sig Gen.The first problem I have hit is buffering. The WaveTek includes a FIFO message buffer.The problem I have is aligning the GPIB commands with the buffer content. If I issue a command to read the ID string, the ID is loaded into the buffer. If anything is already in the buffer, that comes out ahead of the ID string.The code looks like this:Code:print("ID ")print(SigGen.write('ID ?'))print(SigGen.read())Note I have chosen not to use the query command.The first time I run this code after power up I get:Code:ID5D:\darren\My Documents\Electronics\GPIB USB Adapter\dazz\gpib_test_2_WvTk2520.py:24: UserWarning: read string doesn't end with termination charactersprint(SigGen.read())101-COMMAND HEADERIn this case, the "101-COMMAND HEADER is printed out. The contents of the buffer is not aligned with the read ID string command.The next time I ran the same code I got:Code:ID5WVTK/2520A,V81.1,F5.1Now the ID string is printed out because there is nothing ahead of it in the buffer. The read ID command is aligned with the ID string in the buffer.The WaveTek does not have a command to clear the buffer. The issue is further complicated by the STR function that allows a user to press a key on the front panel that generates a service request. Potentially messages can be randomly inserted into the buffer.Is there a recommended method of aligning buffered strings with the command that called for them?

author: alm
author_rank: Super Contributor
timestamp: December 20, 2023, 10:19:34 pm
content: My solution for this was to developpython-ividrivers, for examplethis driver for the HP 3456Awhich might be kind of similar to the HP 3478A. But if you're new to Python, I would not recommend it. It makes the code a lot more complicated and requires some familiarity with the IVI specification which is not worth it for a beginner.I would start by sending simple commands to the meter or signal gen (probably the simplest to program), and write functions like this:Code:def set_3478a_to_3v_dc(instr):instr.write("F1R0")def read_from_3478a(instr):response = instr.read()return float(response)rm = ...instr = rm....set_3478a(instr)while True:print(read_from_3478a(instr))Quote from: dazz1 on December 20, 2023, 10:16:56 pmI'm not familiar with this signal gen, but this reads like an error message to me. Should there be a space between 'ID' and '?'?

author: dazz1
author_rank: Frequent Contributor
timestamp: December 20, 2023, 10:51:14 pm
content: HiI have been doing exactly as you suggested, writing small test programs to try things out. The code sample provided above is a snippet from the test program.I wouldn't expect you, or anyone else, to be familiar with a dinosaur like the 2520. It dates back to late 1980s, so doesn't conform with the later standards on command format. In this case "ID ?" is correct. I know that from the manual, but the manual doesn't cover query and buffer alignment.The starting assumption was that issuing a read command would always return the desired string message. The 101-COMMAND HEADER message was something left in the message buffer from previous testing. It is not related to the ID command, and that is the problem. I issued a read ID command and got back a random message. I am thinking this is likely to be a problem on any instrument with a message buffer.Note that in response to any read command, I receive a digit and then the message.I have not figured out the purpose/significance of this yet.This appears to be the length of the string sent to the 2520, including the termination symbol ('\n')

author: alm
author_rank: Super Contributor
timestamp: December 20, 2023, 11:56:30 pm
content: I'd start with the HP 3478A. DMMs are simpler than scopes and in my experience HP equipment has been the most well behaved with GPIB, with Datron pretty close, but Keithley as more finicky. Sounds like Wavetek might be similar to Keithley.

author: caiser01
author_rank: Regular Contributor
timestamp: December 21, 2023, 02:38:30 am
content: Quote from: dazz1 on December 20, 2023, 10:16:56 pmThis is almost certainly an artifact of the xyphro firmware's Auto ID feature. If you have an older instrument, such as this WaveTek, that does not respond to the *IDN? query, and this WaveTek doesn't, an error will be generated on the instrument when the adapter automatically sends *IDN? at power up in an attempt to make a "pretty" VISA resource string. According to my reading of the Wavetek's manual, 101-COMMAND HEADER means "I don't recognize the command that was sent", which is as expected since it doesn't support *IDN?.You have three choices to get around this:1. Disable the Auto ID feature of the adapter using the method xyphro describes near the end of his GitHub README2. Throw in an extra read at the start of the program to read out the error message and just ignore it3. My personal preference: Use the VISA clear function to reset the instrument at the beginning of the program. This is preferred because it should reset the instrument to its power-on state, clear all buffers, etc.Also, since this an old, possibly quirky instrument, it may be necessary to change the default read termination behavior of the xyphro firmware. I have to do this for my HP 5385A frequency counter or else I can't read properly from it.Below is my attempt at a script to read the ID of the WaveTek 2520 that incorporates my recommendations from above. Please note: the sleep delays ARE necessary, especially after a VISA clear. I speak from experience...Code:import pyvisafrom sys import platformfrom time import sleepif platform == "linux" or platform == "linux2":# Linuxrm = pyvisa.ResourceManager("/usr/lib/librsvisa.so@ivi")elif platform == "darwin":# macOSrm = pyvisa.ResourceManager("/Library/Frameworks/RsVisa.framework/RsVisa@ivi")elif platform == "win32":# Windowsrm = pyvisa.ResourceManager()SigGen = rm.open_resource('YOUR_RESOURCE_STRING_HERE')# xyphro UsbGpib configuration# Configure read termination as Option 1 (EOI and \n)SigGen.control_in(0xa1, 0x40, 0, 0, 1)SigGen.write('!0101')# Wait to make sure configuration took effectsleep(1)# end xyphro UsbGpib configurationSigGen.timeout = 5000SigGen.write_termination = '\r'SigGen.read_termination = '\n'# Reset the instrument, wait for reset to completeSigGen.clear()sleep(1)print('Instrument ID:', SigGen.query('ID?'))# xyphro UsbGpib configuration# Configure read termination as Option 0 (EOI only)SigGen.control_in(0xa1, 0x40, 0, 0, 1)SigGen.write('!0100')# Wait to make sure configuration took effectsleep(1)# end xyphro UsbGpib configuration# Reset the instrument, wait for reset to completeSigGen.clear()sleep(1)# Return front panel to local controlSigGen.control_ren(pyvisa.constants.VI_GPIB_REN_ADDRESS_GTL)SigGen.close()rm.close()

author: dazz1
author_rank: Frequent Contributor
timestamp: December 21, 2023, 06:44:48 am
content: Quote from: caiser01 on December 21, 2023, 02:38:30 amThat makes perfect sense but my assertion that any dregs in the buffer get pulled out ahead of the expected string remain extant, until I find another cause.On closer reading the 2520 command should be "ID?", but "ID ?" also works. I am still skimming along the surface of GPIB and Python so simple things are not yet simple for me.Quote from: caiser01I haven't found a clear/reset type command for the 2520 yet but I will keep looking. It does allow me to set/recall settings, so I can put the 2520 into a defined state. A sample output is:Code:FREQUENCY 222.222 MHzFREQ STEP 50.0 kHzAMPLITUDE -10.0 dBmINTERNAL AM 100.0 %INTERNAL FM 80.0 kHzEXTERNAL AM 100.0 %EXTERNAL FM 235.0 kHzRF OUTPUT OFFMOD RATE 1000 HzMODULATION OFFAMP STEP 0.10 dBEXT PHASE 5.9 rads350-STORED SETTINGS ERRORThe recalled settings have an error, but I don't know which setting is faulty.Quote from: caiser01The termination is programmable. I can and have changed the termination to /n. That seems to work OK. I don't see corrupted output.Quote from: caiser01There are definitely some code snippets I can plagiarize from your code sample.Looking at the circuit design and the manuals, I think there is a high risk of finding querks. I have found the 2520 manual difficult to use as a look-up reference. I am writing a summary version.I am also writing a sample / test script that exercises all commands (there aren't too many of them) to seek out the querks and learn a bit about Python.

author: ch_scr
author_rank: Frequent Contributor
timestamp: December 21, 2023, 12:24:52 pm
content: To get a grip on the behaviour of an instrument, I find it a lot easier to use the interactive "pyVISA Shell" first, then write the script (knowing what the instrument expects).Here's a script that is about the absolute minimum to log data from a DMM, with ample comments. Even though it's written for a different instrument, you might find parts of it helpfull.

author: caiser01
author_rank: Regular Contributor
timestamp: December 21, 2023, 02:05:14 pm
content: Quote from: dazz1 on December 21, 2023, 06:44:48 amThere's not a clear command for the WaveTek 2520 and most very old instruments don't have one.I was suggesting using the VISA clear() function. That will execute a GPIB Device Clear (DC1) which is explicitly supported by the 2520 as stated on page 6-1 of the manual. That should clear the "dregs in the buffer" when executed at the beginning of the script before attempting any reads from or writes to the instrument.Code:# Reset the instrument, wait for reset to completeSigGen.clear()sleep(1)This is exactly what I do for my HP 5385A, which throws an error when powered on with the xyphro adapter connected because of the Auto ID feature. I run clear() which makes it reset and boot cleanly.

author: dazz1
author_rank: Frequent Contributor
timestamp: December 22, 2023, 06:52:24 am
content: Quote from: ch_scr on December 21, 2023, 12:24:52 pmThanks for the script. My test script is similar but less sophisticated.

author: dazz1
author_rank: Frequent Contributor
timestamp: December 22, 2023, 07:34:47 am
content: Quote from: caiser01 on December 21, 2023, 02:05:14 pmYes that is listed in the chapter intro, but not further on. If it does work, there is a good chance it will change the termination.The 2520 provides 3x ways of changing the termination and the termination can include 1,2 or 3 chars. The DIP switches are set to CR/LF/EOI, but I have set the termination to CR (/n) in software, so a DCI instruction, if it works, might change the termination to the DIP switch settings. The current setting survives power cycling but may revert to the DIP SW settings to a DCI instruction. I need to test for it.Is there a preferred termination in the GPIB world?Quote from: caiser01[codeWondering if it might be practical to use the eeprom on the adapter to store adjustable settings to manage the Auto ID feature. Something Xyphro could consider doing.

author: ch_scr
author_rank: Frequent Contributor
timestamp: December 22, 2023, 10:08:16 am
content: Quote from: dazz1 on December 22, 2023, 07:34:47 amAFAIK, it does just that? You can turn off the Auto-ID and it remembers that setting?Here's what he writes about it:Quote from: xyphro github repoSeems like it would be good to have a ready-made script to switch that, instead of every user having to fend for themself?

author: caiser01
author_rank: Regular Contributor
timestamp: December 22, 2023, 07:44:56 pm
content: Quote from: dazz1 on December 22, 2023, 07:34:47 amIt is indeed possible but I would not automatically assume that because...Quote from: dazz1 on December 22, 2023, 07:34:47 amDevice Clear (at least on old instruments) is generally about putting the instrument back to its power-on state and clearing all GPIB buffers, status, and flags. But since this WaveTek is a bit of an oddball, who knows?Quote from: dazz1 on December 22, 2023, 07:34:47 amYes, definitely, and if you find the 2520 termination setting is volatile, you could still make 'TRM' the first command you send following the call to VISA clear() to put it back the way you want it. It is generally good practice when writing code to communicate with instruments to never assume any settings or configurations carry over from one use to the next. That should all be in the initialization code for each instrument.Quote from: dazz1 on December 22, 2023, 07:34:47 am...but seriously, the inconsistency of expected termination sequences, especially with older instruments can be one of the most frustrating things about working with GPIB. An otherwise perfectly written program will cause the instrument to sit there angrily beeping and blinking annunciators at you for the sake of an incorrect termination sequence.My experience has been that since the 90s at least, instrument makers seem to have settled on newline (LF) as the most common terminator. With older instruments, it's down to reading the manual and experimenting. Some instruments want CR, some want LF, some want both. It's a mess and it's telling that WaveTek included *multiple* ways to change the termination sequence for the 2520.This is more of an issue when you have a single, traditional GPIB controller with multiple instruments hooked up. In that case, you need all the instruments to have at least compatible termination sequences. Since the xyphro adapter is one adapter per instrument, it's pretty easy to set unique termination sequences for each instrument. In object-oriented terms, each instrument can be its own object with its own properties, including termination.Briefly, for using an instrument with the xyphro adapter, just set the termination to whatever works best for that instrument. Don't worry too much over whether it's the same as other instruments or not.Quote from: dazz1 on December 22, 2023, 07:34:47 amIn my conversations with xyphro, he expressed a love/hate relationship with his Auto ID feature. I think he's open to ideas for changes and improvements. Why not flesh out your suggestion and submit an issue at GitHub?

author: dazz1
author_rank: Frequent Contributor
timestamp: December 22, 2023, 08:42:42 pm
content: I took a look at Xyphro instructions:QuoteI am on the bottom of the learning curve of, starting to learn, three things:PythonGPIB protocol and,GPIB WaveTek 2520 command setSo I wasn't expecting the adapter to care about terminations. Based on advice at this link:https://forums.ni.com/t5/Instrument-Control-GPIB-Serial/Default-GPIB-termination-character/td-p/242545EOI should be the default terminator. Given that is a hardwired control line, the adapter needs to know this.I am looking at all of this and thinking the adapters should be transparent and instrument agnostic. The GPIB controlling software should write/select the correct terminator at start-up. This will ensure that no matter which equipment the adapter is plugged into, it will be correctly configured by the controller for the instrument being controlled. eePROM has limited write cycles so what is needed is a method of reading the terminator setting, and only writing if it needs changing. This will significantly extend the life of the adapter.I have opened up the 2520 and set the termination to LF with DIP switches but I think I need to change that to EOI. I can still change the termination from the front panel or via GPIB but at least one command reverts to the DIP switch setting.

author: dazz1
author_rank: Frequent Contributor
timestamp: December 22, 2023, 08:50:30 pm
content: Quote from: caiser01Done that :https://github.com/xyphro/UsbGpib/issues/48Being able to read back the settings from the adapter will eliminate a potential source of trouble.

author: dazz1
author_rank: Frequent Contributor
timestamp: December 22, 2023, 08:58:27 pm
content: Quote from: caiser01OK I am going to go with EOI as my default termination. If that doesn't work for a specific instrument, use LF or whatever works.My instruments include a scope and EMC receiver with a scope-like output. Hopefully using EOI will avoid issues with byte data streams.

author: caiser01
author_rank: Regular Contributor
timestamp: December 22, 2023, 09:19:57 pm
content: Quote from: dazz1 on December 22, 2023, 08:42:42 pmA "normal" GPIB controller (like an NI or HP USB adapter or PCI card) doesn't care about read termination. Only the read termination setting in your application would matter. The xyhpro adapter cares about read termination (if I understand correctly) because of the mechanics of the translation from GPIB to USBTMC.Yes, EOI is the only termination that should be needed for newer (488.2 compliant) instruments. Keep in mind though that just because the updated 488.2 GPIB spec was published in 1987, there was nothing to say that instrument makers *had* to comply with it. Many legacy 488.1 instruments remained in production (in fact a few oddball 488.1 instruments may still be in limited production, I have stories from my job...). So it's possible to have a post-1987 instrument that is only 488.1 compliant (and/or not SCPI-compliant for that matter). This is all part of the fun of GPIBQuote from: dazz1 on December 22, 2023, 08:42:42 pmYep, yep. Configuring in the application software every time is the smart way.Quote from: dazz1 on December 22, 2023, 08:58:27 pmGood plan

author: dazz1
author_rank: Frequent Contributor
timestamp: December 23, 2023, 07:45:04 am
content: Hi am trying to try the DCL command.I have figured out I need to write hex value 0x14, but all I can find is confusion and error messages. An example being this:https://github.com/pyvisa/pyvisa/issues/491and here:https://pyvisa.readthedocs.io/en/latest/introduction/rvalues.htmlAlso I haven't figured out how to send an EOI terminator to the 2520. I need to be able to tell pyVISA the terminator is "EOI".I also need to send the 2520 a string that sets the terminator to EOI. The manuals are silent. I still have the 2520 terminator DIP switch set to /n. I want to test the software command to set EOI before I change the DIP switches.

author: dazz1
author_rank: Frequent Contributor
timestamp: December 23, 2023, 08:08:33 am
content: I tried this:Code:D:\GPIB USB Adapter\dazz>pythonPython 3.12.1 (tags/v3.12.1:2305ca5, Dec 7 2023, 22:03:25) [MSC v.1937 64 bit (AMD64)] on win32Type "help", "copyright", "credits" or "license" for more information.>>> import pyvisa>>> rm = pyvisa.ResourceManager()>>> print(rm.list_resources())('USB0::0x03EB::0x2065::GPIB_02_24238323232351C01171::INSTR', 'ASRL1::INSTR')>>> SigGen = rm.open_resource('USB0::0x03EB::0x2065::GPIB_02_24238323232351C01171::INSTR')>>> cmd = bytes([0x14, ])>>> SigGen.send_command(data=cmd)Traceback (most recent call last):File "<stdin>", line 1, in <module>AttributeError: 'USBInstrument' object has no attribute 'send_command'>>>So wondering if the adapter has a method to write command bytes to the instrument?

author: caiser01
author_rank: Regular Contributor
timestamp: December 23, 2023, 04:12:43 pm
content: Quote from: dazz1 on December 23, 2023, 07:45:04 amIn the issue you link to, the person is clearly using a "real" GPIB adapter or card because they refer to the pyVISA GPIBInstrument class. The xyphro adapter presents itself as a USBTMC device and therefore pyVISA can only talk to the instrument using its USBInstrument class, and therefore, the only valid VISA functions are those listed here:https://pyvisa.readthedocs.io/en/latest/api/resources.html#pyvisa.resources.USBInstrumentThat's why you got this error message:Code:AttributeError: 'USBInstrument' object has no attribute 'send_command'Because send_command() is valid for a GPIBInstrument object but not a USBInstrument object.With xyphro adapter, you don't need to (and in fact can't) send low-level commands to the instrument in the manner you're attempting.If you just run:Code:SigGen.clear()..and the adapter firmware will do all the low-level stuff for you.If you want to prove to yourself what's really happening, you can follow the logic through the various specs and xyphro's firmware:You run SigGen.clear() and pyVISA will send INITIATE_CLEAR to the xyphro adapter. Since the adapter is a USBTMC device and is USB488 compliant, it will behave as described in 4.2.1 of that specification (http://sdpha2.ucsd.edu/lab_equip_manuals/usbtmc_usb488_subclass_1_00.pdf), which is to say it will send Selected Device Clear (SDC) (hex 0x04) to the instrument. Note: The result of sending a DCL (0x14, clear all instruments on the bus) and a SDC (0x04, clear only the addressed instrument) would be the same in our case since only one instrument can be connected to the xyhpro adapter.Now, we can follow what's happening in xyphro's firmware. In TestAndMeasurement.c (https://github.com/xyphro/UsbGpib/blob/master/SW/TestAndMeasurement/TestAndMeasurement.c), there is a switch-case starting at line 566Code:switch (USB_ControlRequest.bRequest)Because we got INITIATE_CLEAR from pyVISA, that will kick us down to line 703Code:case Req_InitiateClear:The important thing that happens here is that the handleSDC flag is set true. Next we jump down to line 1099Code:if (handleSDC){gpib_ren(1); /* ensure that remote control is enabled */timeout_start(50000); /* 0.5s timeout*/gpib_sdc(gpib_addr, is_timedout);handleSDC = false;}gpib_sdc is called and now we have to jump over to gpib.c (https://github.com/xyphro/UsbGpib/blob/master/SW/TestAndMeasurement/gpib.c) to see that function starting at line 269. Inside gpib_sdc, one more function is called and that's gpib_cmd_SDC, which is very straightforward:Code:static bool gpib_cmd_SDC(gpibtimeout_t ptimeoutfunc) // selective device clear{return gpib_tx(0x04, true, ptimeoutfunc);}The command byte 0x04 is sent to the instrument to perform SDC, which as we noted above is equivalent to DCL for our single connected instrument.So to finally summarize,executing SigGen.clear() in your python script will send SDC (0x14) to your instrument.Quote from: dazz1 on December 23, 2023, 07:45:04 amNo, you don't. The firmware on the adapter again takes care of setting EOI for you and you can follow your way through the code to prove that to yourself as above.

author: dazz1
author_rank: Frequent Contributor
timestamp: December 24, 2023, 03:49:34 am
content: My first paddle into the sea of Python is a script that tests the time to execute and reliability of query commands.It does this simply by executing the same query command (ID?) 10x in quick succession, and measuring the execution time to complete each query. The purpose of posting this is to make it available to others. It should probably run with any and all GPIB instruments.With very little modification, this script could read a command line argument and execute that. One script to run many different query commands. I have chosen not to do that.My plan is to copy/paste/modify this script for each query command, run the tests, and record a summary of the results in the script.I have already found that the WaveTek 2520 is not a reliable responder. The pyVISA exception handling is not handling the occasional errors I see.Code:# Wavetek 2520 RF Signal Generator simple read test# The purpose of this script is to gauge gpib command reliability, and to measure the# execution time.# This repeats the same gpib query command 10 times and measures the execution time# for each query.import pyvisaimport timefrom timeit import default_timer as timer# Define a function that measures the execution time of the argument.# The argument is a gpib command.# User Editable Variablespause = 0.02# Edit this. This is the pause from the end of one query to the next.# It is the time taken for the instrument to be ready for the next query.gpib_query = "ID? " # Edit this. This is the gpib query command under test.# ID string for adapter 0: 'USB0::0x03EB::0x2065::GPIB_23_24238323232351C01171::INSTR'def exec_query(cmd):try:start = timer()ans = SigGen.query(cmd)end = timer()print("Query : ", cmd," Returned : ", str( ans ) )ExTm = round((end - start) * 1000,2) # millisecondsexcept pyvisa.VisaIOError:print("########### WARNING : Time Out exception has occurred")SigGen.clear()return " Cmd Execution time: ", ExTm,"ms"print("###### Simple GPIB test for WaveTek 2520 SigGen")print("# Executes read ID 10x")print()print("# Show the list of Resources")rm = pyvisa.ResourceManager()print(rm.list_resources())print("# Opening the SigGen")# Resource = GPIB-usb adapter 0. Different for each adapter.SigGen = rm.open_resource('USB0::0x03EB::0x2065::GPIB_02_24238323232351C01171::INSTR')print()# Reset the instrument, wait for reset to completeSigGen.clear() # Doesn't appear to have any effect on the Signal Generator.###### Run this once to turn off auto ID. AutoID is not supported by the WaveTek 2520.#SigGen.control_in(0xa1, 0x40, 0, 0)#SigGen.write('!0001')SigGen.write_termination = '\n'SigGen.read_termination = '\n'SigGen.timeout = 1000 #sets 1s timeout for the meter after the read#print("Read the ID")try:for x in range (1,10):print("# Loop Count :", x, exec_query(gpib_query))# Edit the gpibtime.sleep(pause)except KeyboardInterrupt:SigGen.clear()SigGen.close()rm.close()# RESULTS# typical execution time of print(SigGen.query('ID? ')) is <12ms# delay 20ms before next ID? read.I usually get an output that looks like this:Code:GPIB_test>python WvTk2520_gpib_rd_ID.py\###### Simple GPIB test for WaveTek 2520 SigGen# Executes read ID 10x# Show the list of Resources('USB0::0x03EB::0x2065::GPIB_02_24238323232351C01171::INSTR', 'ASRL1::INSTR')# Opening the SigGenQuery : ID? Returned : WVTK/2520A,V81.1,F5.1# Loop Count : 1 (' Cmd Execution time: ', 11.91, 'ms')Query : ID? Returned : WVTK/2520A,V81.1,F5.1# Loop Count : 2 (' Cmd Execution time: ', 11.75, 'ms')Query : ID? Returned : WVTK/2520A,V81.1,F5.1# Loop Count : 3 (' Cmd Execution time: ', 11.74, 'ms')Query : ID? Returned : WVTK/2520A,V81.1,F5.1# Loop Count : 4 (' Cmd Execution time: ', 11.78, 'ms')Query : ID? Returned : WVTK/2520A,V81.1,F5.1# Loop Count : 5 (' Cmd Execution time: ', 11.89, 'ms')Query : ID? Returned : WVTK/2520A,V81.1,F5.1# Loop Count : 6 (' Cmd Execution time: ', 11.92, 'ms')Query : ID? Returned : WVTK/2520A,V81.1,F5.1# Loop Count : 7 (' Cmd Execution time: ', 11.73, 'ms')Query : ID? Returned : WVTK/2520A,V81.1,F5.1# Loop Count : 8 (' Cmd Execution time: ', 11.95, 'ms')Query : ID? Returned : WVTK/2520A,V81.1,F5.1# Loop Count : 9 (' Cmd Execution time: ', 11.74, 'ms')when it doesn't work, I get an output that looks like this:Code:D:\darren\My Documents\Electronics\Wavetek SigGen\GPIB_test>python WvTk2520_gpib_rd_ID.py\###### Simple GPIB test for WaveTek 2520 SigGen# Executes read ID 10x# Show the list of Resources('USB0::0x03EB::0x2065::GPIB_02_24238323232351C01171::INSTR', 'ASRL1::INSTR')# Opening the SigGenTraceback (most recent call last):File "D:\darren\My Documents\Electronics\Wavetek SigGen\GPIB_test\WvTk2520_gpib_rd_ID.py\", line 51, in <module>SigGen.clear()File "G:\Programs\Python310\Lib\site-packages\pyvisa\resources\resource.py", line 381, in clearself.visalib.clear(self.session)File "G:\Programs\Python310\Lib\site-packages\pyvisa\ctwrapper\functions.py", line 616, in clearreturn library.viClear(session)^^^^^^^^^^^^^^^^^^^^^^^^File "G:\Programs\Python310\Lib\site-packages\pyvisa\ctwrapper\highlevel.py", line 226, in _return_handlerreturn self.handle_return_value(session, ret_value) # type: ignore^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "G:\Programs\Python310\Lib\site-packages\pyvisa\highlevel.py", line 251, in handle_return_valueraise errors.VisaIOError(rv)pyvisa.errors.VisaIOError: VI_ERROR_SYSTEM_ERROR (-1073807360): Unknown system error (miscellaneous error).

author: dazz1
author_rank: Frequent Contributor
timestamp: December 24, 2023, 04:03:13 am
content: Quote from: caiser01OK now I know.The gem has avoided a very deep dive into a rabbit hole.FYI: TheCode:clear()command has no observable effect on the 2520. I could write a function that simply sets the 13 user variable settings to known defaults.

author: dazz1
author_rank: Frequent Contributor
timestamp: December 24, 2023, 08:16:35 am
content: So below is the result of a test where the only query command executed is the current RF output LVL.The previous tests were for Frequency and for ID.The output shows the query was "LVL" but the response is Frequency, ID and lastly Level.The "350-Stored Settings Error" appears to signal that the 2520 knows something is wrong.I think it is safe to say the 2520 is probably full of bugs.Code:###### Simple GPIB test for WaveTek 2520 SigGen# Executes read ID 10x# Show the list of Resources('USB0::0x03EB::0x2065::GPIB_02_24238323232351C01171::INSTR', 'ASRL1::INSTR')# Opening the SigGenClear the instrumentQuery : LVL? Returned : FREQUENCY 222.222 MHz# Loop Count : 1 (' Cmd Execution time: ', 12.29, 'ms')Query : LVL? Returned : FREQUENCY 222.222 MHz# Loop Count : 2 (' Cmd Execution time: ', 12.16, 'ms')Query : LVL? Returned : FREQUENCY 222.222 MHz# Loop Count : 3 (' Cmd Execution time: ', 12.39, 'ms')Query : LVL? Returned : 350-STORED SETTINGS ERROR# Loop Count : 4 (' Cmd Execution time: ', 12.3, 'ms')Query : LVL? Returned : 350-STORED SETTINGS ERROR# Loop Count : 5 (' Cmd Execution time: ', 12.35, 'ms')Query : LVL? Returned : 350-STORED SETTINGS ERROR# Loop Count : 6 (' Cmd Execution time: ', 12.38, 'ms')Query : LVL? Returned : WVTK/2520A,V81.1,F5.1# Loop Count : 7 (' Cmd Execution time: ', 12.27, 'ms')Query : LVL? Returned : WVTK/2520A,V81.1,F5.1# Loop Count : 8 (' Cmd Execution time: ', 12.28, 'ms')Query : LVL? Returned : WVTK/2520A,V81.1,F5.1# Loop Count : 9 (' Cmd Execution time: ', 12.35, 'ms')Query : LVL? Returned : WVTK/2520A,V81.1,F5.1# Loop Count : 10 (' Cmd Execution time: ', 12.38, 'ms')Query : LVL? Returned : WVTK/2520A,V81.1,F5.1# Loop Count : 11 (' Cmd Execution time: ', 12.3, 'ms')Query : LVL? Returned : WVTK/2520A,V81.1,F5.1# Loop Count : 12 (' Cmd Execution time: ', 12.23, 'ms')Query : LVL? Returned : WVTK/2520A,V81.1,F5.1# Loop Count : 13 (' Cmd Execution time: ', 12.2, 'ms')Query : LVL? Returned : WVTK/2520A,V81.1,F5.1# Loop Count : 14 (' Cmd Execution time: ', 12.38, 'ms')Query : LVL? Returned : WVTK/2520A,V81.1,F5.1# Loop Count : 15 (' Cmd Execution time: ', 12.33, 'ms')Query : LVL? Returned : 350-STORED SETTINGS ERROR# Loop Count : 16 (' Cmd Execution time: ', 12.35, 'ms')Query : LVL? Returned : AMPLITUDE -10.0 dBm# Loop Count : 17 (' Cmd Execution time: ', 12.24, 'ms')Query : LVL? Returned : AMPLITUDE -10.0 dBm# Loop Count : 18 (' Cmd Execution time: ', 12.37, 'ms')Query : LVL? Returned : AMPLITUDE -10.0 dBm# Loop Count : 19 (' Cmd Execution time: ', 12.25, 'ms')I tested the hypothesis that the commands were issued too quickly with not enough time for the 2520 to finish. I extended times, especially after .clear for up to 60 seconds.The test script had dynamic fatal errors.So when I program gpib, I will need to keep sending commands until I get a valid response.

author: dazz1
author_rank: Frequent Contributor
timestamp: December 24, 2023, 09:24:46 am
content: I am getting error messages when a gpib command generates and exception.Code:File "D:\My Documents\Electronics\Wavetek SigGen\GPIB_test\WvTk2520_gpib_rd_LVL.py\", line 32, in exec_queryreturn " Cmd Execution time: ", ExTm,"ms"^^^^UnboundLocalError: cannot access local variable 'ExTm' where it is not associated with a valueI think the problem is that when the gpib command fails within a defined function the variable ExTm is not assigned a value.Code:...ans = SigGen.query(cmd) # query fails generating an exception.end = timer()print("Query : ", cmd," Returned : ", str( ans ) )ExTm = round((end - start) * 1000,2) # milliseconds# Extm never gets assigned a valueexcept pyvisa.VisaIOError:print("########### WARNING : Time Out exception has occurred")return " Cmd Execution time: ", ExTm,"ms" # on return, ExTm is unassigned...Not sure how to fix this yet. Looking into it.Edit: Fixed this by moving the execution time calculation to the return(...) statement.Code:print("Query : ", cmd," Returned : ", str( ans ) )#ExTm = round((end - start) * 1000,2) # millisecondsexcept pyvisa.VisaIOError:print("########### WARNING : Time Out exception has occurred")return " Cmd Execution time: ", round((end - start) * 1000,2),"ms"

author: dazz1
author_rank: Frequent Contributor
timestamp: December 25, 2023, 11:38:31 pm
content: Having said I wouldn't do something, I have done it.I have written a python script that takes a gpib query command (eg. "ID?") as a argument.That command is then executed in a loop.The output includes the response to the command and measures the time taken for the instrument to execute and response to the command. This measured time is end-to-end and includes the duration of communications to send the command and receive the response.This script is designed for commands where something is written to the instrument, and then a response is read back. This script does not attempt to cover all types if instructions.This script should run with any instrument. It allows a user to test the response of any instrument to gpib query commands.Code:# Wavetek 2520 RF Signal Generator simple read test# The purpose of this script is to gauge gpib command reliability, and to measure the# execution time.# This repeats the same gpib query command 10 times and measures the execution time# for each query.import pyvisaimport timeimport sysfrom timeit import default_timer as timer# CMD commands to run# D:# D:\My Documents\Electronics\Wavetek SigGen\GPIB_test\# Define a function that measures the execution time of the argument.# The argument is a gpib command.# User Editable Variablesread_cnt = 20# The number of queries looped throughpause = 1# Edit this. This is the pause from the end of one query to the next.# It is the added delay to allow the instrument to be ready for the next query.# The function to execute a GPIB query command. The command is executed and the results# are printed.def exec_query(cmd):try:start = timer()end = startans = SigGen.query(cmd)end = timer()print("Query : ", cmd," Returned : ", str( ans ) )except pyvisa.VisaIOError:print("########### WARNING : Time Out exception has occurred")return " Cmd Execution time: ", round((end - start) * 1000,2),"ms"# ID string for adapter 0: 'USB0::0x03EB::0x2065::GPIB_23_24238323232351C01171::INSTR'if len(sys.argv) > 0 :gpib_cmd = str(sys.argv)else:gpib_cmd = "ID?" # in the absence of a command, default to ID?print("The entered query command is : ", gpib_cmd)print("###### Simple GPIB test for WaveTek 2520 SigGen")print("# Executes read ID 10x")print()print("# Show the list of Resources")rm = pyvisa.ResourceManager()print(rm.list_resources())print("# Opening the SigGen")# Resource = GPIB-usb adapter 0. Different for each adapter.SigGen = rm.open_resource('USB0::0x03EB::0x2065::GPIB_02_24238323232351C01171::INSTR')print()# Reset the instrument, wait for reset to complete#time.sleep(pause)print("Clear the instrument")SigGen.clear()time.sleep(0.1)###### Run this once to turn off auto ID. AutoID is not supported by WvTk2520.#SigGen.control_in(0xa1, 0x40, 0, 0)#SigGen.write('!0001')SigGen.write_termination = '\n'SigGen.read_termination = '\n'SigGen.timeout = 500 #sets timeout (ms) for the instrument to respond.#print("Read the ID")try:for x in range (0,read_cnt):print("# Loop Count :", x, exec_query(gpib_cmd))# The gpib command under testtime.sleep(pause)except KeyboardInterrupt:print("################ Interrupted by keyboard !")SigGen.clear()SigGen.close()rm.close()# RESULTS# typical execution time of print(SigGen.query('ID? ')) is <13ms# delay 20ms before next ID? read.# Randomly returns : Query : FRQ? Returned : 350-STORED SETTINGS ERRORThis is a development of the first python script I have written, so for all those that know what they are doing, be gentle on me.This is a test program so it is unpolished and simple.The output shows the command, the response and the execution time (duration).A sample output is:Code:# Show the list of Resources('USB0::0x03EB::0x2065::GPIB_02_24238323232351C01171::INSTR', 'ASRL1::INSTR')# Opening the SigGenClear the instrumentQuery : lst? Returned : AMPLITUDE -10.0 dBm# Loop Count : 0 (' Cmd Execution time: ', 11.99, 'ms')Query : lst? Returned : AMPLITUDE -10.0 dBm# Loop Count : 1 (' Cmd Execution time: ', 11.94, 'ms')Query : lst? Returned : AMPLITUDE -10.0 dBm# Loop Count : 2 (' Cmd Execution time: ', 12.27, 'ms')Query : lst? Returned : AMPLITUDE -10.0 dBm# Loop Count : 3 (' Cmd Execution time: ', 12.07, 'ms')Query : lst? Returned : AMPLITUDE -10.0 dBm# Loop Count : 4 (' Cmd Execution time: ', 12.08, 'ms')Query : lst? Returned : AMPLITUDE -10.0 dBm# Loop Count : 5 (' Cmd Execution time: ', 11.98, 'ms')Query : lst? Returned : AMPLITUDE -10.0 dBm# Loop Count : 6 (' Cmd Execution time: ', 12.15, 'ms')Query : lst? Returned : AMPLITUDE -10.0 dBm# Loop Count : 7 (' Cmd Execution time: ', 12.12, 'ms')Query : lst? Returned : AMPLITUDE -10.0 dBm# Loop Count : 8 (' Cmd Execution time: ', 12.02, 'ms')Query : lst? Returned : AMPLITUDE -10.0 dBm# Loop Count : 9 (' Cmd Execution time: ', 12.82, 'ms')Query : lst? Returned : AMPLITUDE -10.0 dBm# Loop Count : 10 (' Cmd Execution time: ', 12.16, 'ms')Query : lst? Returned : AMPLITUDE -10.0 dBm# Loop Count : 11 (' Cmd Execution time: ', 12.27, 'ms')Query : lst? Returned : AMPLITUDE -10.0 dBm# Loop Count : 12 (' Cmd Execution time: ', 11.97, 'ms')Query : lst? Returned : AMPLITUDE -10.0 dBm# Loop Count : 13 (' Cmd Execution time: ', 12.16, 'ms')Query : lst? Returned : 350-STORED SETTINGS ERROR# Loop Count : 14 (' Cmd Execution time: ', 12.2, 'ms')Query : lst? Returned : 350-STORED SETTINGS ERROR# Loop Count : 15 (' Cmd Execution time: ', 11.99, 'ms')Query : lst? Returned : AMP STEP 0.10 dB# Loop Count : 16 (' Cmd Execution time: ', 12.12, 'ms')Query : lst? Returned : AMP STEP 0.10 dB# Loop Count : 17 (' Cmd Execution time: ', 11.96, 'ms')Query : lst? Returned : AMP STEP 0.10 dB# Loop Count : 18 (' Cmd Execution time: ', 12.37, 'ms')The sample shows that the WaveTek 2520 is unreliable. At face value, the sample output looks like a timing issue. Increasing the pause durations between instructions does not change the output. It also looks like a FIFO buffer needs to be cleared before the correct response is received.I tested the hypothesis that .clear() would flush any buffers. The gpib command: SigGen.clear() has no observable effect on the WaveTek2520, but it takes 125ms to complete, so it is doing something.

author: caiser01
author_rank: Regular Contributor
timestamp: December 26, 2023, 02:23:08 am
content: Nice job on the script and thanks for sharing.A few thoughts:1. I did not know of the existence of the timeit library so that's something to file away for later use. I've always used perf_counter from the time library for timing execution.2. 12ms response time is pretty good and typical of an instrument of this vintage.3. I wonder if changing just the write termination to '\r' in the script (no changes to the instrument's DIP switches, etc.) would eliminate the 350 errors. For my Fluke 6060B RF signal generator, I had to change the write termination to ';' to keep it from occasionally hiccuping.

author: dazz1
author_rank: Frequent Contributor
timestamp: December 26, 2023, 09:29:27 am
content: HiI have been looking for / testing methods to get a reliable response from gpib queries sent to my WaveTek2520 RF signal generator.The script I have come up with does this by ignoring any initial null responses, then it keeps reading until at least two adjacent nulls are returned.I have no idea if this is best practice, or any practice, but it appears to work.The instruction set and other key parameters are easily adjusted, so this script could be readily adapted to other instruments with simple query commands. That is why I have posted the script here:Code:# Wavetek 2520 RF Signal Generator simple read test# The purpose of this script is to test a method to obtain reliable# responses from the instrument. This script is designed to reliably# read the responses to query type commands only.## Reads fail because:#the script runs too fast (pauses need to be inserted)#the first read returns a null response and,#responses are initially from a FIFO buffer.## This script:#discards an initial single null response.#keeps reading until the responses are at least two nulls.# This script will read multi-line responses.# This script executes all query type gpib commands in a loop.# The commands are stored in a 2xn matrix.# The columns are a:#query command#description of the command## 0: cmdSET?# 1: descriptionList all internal settings# The instructions are in a user defined loop count.# The commands are in an editable array to allow this script to# be used with any simple query command, including multi-line responses.# Edit "pause" to adjust the inserted delay periods.import pyvisaimport timefrom timeit import default_timer as timerimport sysimport array as arrimport numpy as np# CMD commands to run# D:# D:\My Documents\Electronics\Wavetek SigGen\GPIB_test\# Define a function that measures the execution time of the argument.# The argument is a gpib command.# User Editable Variablesread_cnt = 5# The number of times to loop through a set of queriespause = .05# Edit this. This is the pause from the end of one query to the next.# It is the added delay to allow the instrument to be ready for the next query.############ Query Commands Arrays# Edit this array to define all of the query commands.# Array: "command", No. of response lines to read, descriptionarrayCmds = np.array([["ID?" ,"ID"],["FRQ?","Frequency"],["FST?","Frequency Step"],["LVL?","Amplitude"],["LST?","Amp Step"],["RF? ","RF Output on/off"],["IAM?","Internal AM "],["IFM?","Internal FM "],["XAM?","External AM "],["XFM?","External FM "],["RTE?","Internal modulation tone 400/1000Hz"],["MOD?","Modulation Mode"],["ERR?","Error message"],["OPT?","Installed Options"],["SET?","List all settings:"]])# The function to execute a GPIB query command. The command is executed and the results# are printed.def exec_query():try:for row in arrayCmds:print("# Query : ", row," = ",row)start = timer()end = start# Write, Read same as querySigGen.write(row) # send command to instrumentRdNull = False# Count the number of nulls receivedwhile True:time.sleep(pause)ans = SigGen.read()end = timer()duration = round((end - start) * 1000,2)if ans == "" :# if read = null#print("Null 1", RdNull)if RdNull == True:#print("Null 2", RdNull)breakRdNull = Trueelse:RdNull = Falseprint("# Returned : ", str( ans )," Duration : ", duration )except pyvisa.VisaIOError:print("########### WARNING : Time Out exception has occurred")return "# Cmd Execution time: ", duration,"ms"# ID string for adapter 0: 'USB0::0x03EB::0x2065::GPIB_23_24238323232351C01171::INSTR'print("###### Simple GPIB test for WaveTek 2520 SigGen")print("# Executes a list of query commands")print()print("# Show the list of Resources")rm = pyvisa.ResourceManager()print(rm.list_resources())print("# Opening the SigGen")# Resource = GPIB-usb adapter 0. Different for each adapter.SigGen = rm.open_resource('USB0::0x03EB::0x2065::GPIB_02_24238323232351C01171::INSTR')print()# Reset the instrument, wait for reset to completeprint("# Clear the instrument")SigGen.clear()time.sleep(0.1)###### Run this once to turn off auto ID. AutoID is not supported by WvTk2520.#SigGen.control_in(0xa1, 0x40, 0, 0)#SigGen.write('!0001')SigGen.write_termination = '\n'SigGen.read_termination = '\n'SigGen.timeout = 500 #sets timeout (ms) for the instrument to respond.print("# Run all query commands ...")try:for x in range (0,read_cnt):print("# Loop Count :", x, exec_query())# The gpib command under testtime.sleep(pause)except KeyboardInterrupt:print("################ Interrupted by keyboard !")SigGen.clear()SigGen.close()rm.close()# RESULTS# Reading the responses (multiple reads) until nulls are sensed is a reliable method of# reading data from a WaveTek 2520 RF signal generator. This may work with other# instruments by modifying the command array.A sample output is shown below:Code:# Loop Count : 3 ('# Cmd Execution time: ', 884.63, 'ms')# Query : ID? = ID# Returned : WVTK/2520A,V81.1,F5.1 Duration : 59.91# Query : FRQ? = Frequency# Returned : FREQUENCY 222.222 MHz Duration : 60.2# Query : FST? = Frequency Step# Returned : FREQ STEP 50.0 kHz Duration : 62.51# Query : LVL? = Amplitude# Returned : AMPLITUDE -10.0 dBm Duration : 61.86# Query : LST? = Amp Step# Returned : AMP STEP 0.10 dB Duration : 113.0# Query : RF? = RF Output on/off# Returned : RF OUTPUT OFF Duration : 60.41# Query : IAM? = Internal AM# Returned : INTERNAL AM 100.0 % Duration : 61.69# Query : IFM? = Internal FM# Returned : INTERNAL FM 80.0 kHz Duration : 62.06# Query : XAM? = External AM# Returned : EXTERNAL AM 60.0 % Duration : 62.13# Query : XFM? = External FM# Returned : EXTERNAL FM 235.0 kHz Duration : 111.9# Query : RTE? = Internal modulation tone 400/1000Hz# Returned : 499-SYSTEM OPERATIONAL Duration : 60.57# Query : MOD? = Modulation Mode# Returned : MODULATION EXT PM Duration : 60.55# Query : ERR? = Error message# Returned : 499-SYSTEM OPERATIONAL Duration : 60.66# Query : OPT? = Installed Options# Returned : OPT 75:Level Step Duration : 60.07# Returned : OPT 7A:External Phase Mod Duration : 121.1# Query : SET? = List all settings:# Returned : FREQUENCY 222.222 MHz Duration : 112.46# Returned : FREQ STEP 50.0 kHz Duration : 172.73# Returned : AMPLITUDE -10.0 dBm Duration : 233.66# Returned : INTERNAL AM 100.0 % Duration : 293.71# Returned : INTERNAL FM 80.0 kHz Duration : 353.74# Returned : EXTERNAL AM 60.0 % Duration : 414.08# Returned : EXTERNAL FM 235.0 kHz Duration : 475.76# Returned : RF OUTPUT OFF Duration : 536.76# Returned : 499-SYSTEM OPERATIONAL Duration : 596.77# Returned : MODULATION EXT PM Duration : 657.02# Returned : AMP STEP 0.10 dB Duration : 717.81# Returned : EXT PHASE 0.30 rads Duration : 778.42# Loop Count : 4 ('# Cmd Execution time: ', 882.73, 'ms')

author: dazz1
author_rank: Frequent Contributor
timestamp: December 26, 2023, 10:15:49 am
content: HiI found PyMeasure here:https://pymeasure.readthedocs.io/en/latest/index.htmlI am looking at this a fast track way to write pymeasure.instruments for my own instruments.I can use existing similar instruments and their code, as a template for mine.Anyone have experience with this?

author: dazz1
author_rank: Frequent Contributor
timestamp: December 26, 2023, 10:19:38 am
content: Quote from: caiser01 on December 26, 2023, 02:23:08 amI can set the termination from the front panel for testing. Haven't really done that yet.The manual says read/write terminations need to be the same.

author: bson
author_rank: Unknown
timestamp: December 27, 2023, 09:24:47 pm
content: Quote from: dazz1 on December 24, 2023, 08:16:35 amNI VISA is also full of bugs. It might be worth trying usbtmc directly to the instrument without the bloated VISA stuff.https://github.com/python-ivi/python-usbtmc

author: dazz1
author_rank: Frequent Contributor
timestamp: December 29, 2023, 12:23:26 am
content: Quote from: bsonI am using the R&S GPIB driver which I understand is a lot lighter than NI-VISA.

author: dazz1
author_rank: Frequent Contributor
timestamp: December 29, 2023, 12:39:41 am
content: HiI have a problem where the 2520 GPIB interface becomes unresponsive after being left alone for a few minutes. The fix is to unplug/plug-in the USB-GPIB adapter. This suggest the possibility that it might be possible for the adapter firmware to be modified to recover the 2520There is no evidence of indication of a bug in the usb-gpib adapter firmware. This looks like a problem with the 2520 firmware.The timeout appears to be entirely within the 2520.The code looks like this:Code:# Wavetek 2520 RF Signal Generator simple read test# CMD commands to run# D:# cd \darren\My Documents\Electronics\Wavetek SigGen\GPIB_test\# python WvTk2520_gpib_RTE.pyimport pyvisaimport timeprint("Show the list of Resources")rm = pyvisa.ResourceManager()print(rm.list_resources())print("# Opening the SigGen")# Resource = GPIB-usb adapter 0. Different for each adapter.SigGen = rm.open_resource('USB0::0x03EB::0x2065::GPIB_02_24238323232351C01171::INSTR')SigGen.timeout = 2000 #sets 2s timeout for the meter after the readprint("# Clear")SigGen.clear()...and this generate a time out error message as follows:Code:Simple GPIB test for WaveTek 2520 SigGenShow the list of Resources('USB0::0x03EB::0x2065::GPIB_02_24238323232351C01171::INSTR', 'ASRL1::INSTR')# Opening the SigGen# ClearTraceback (most recent call last):File "D:\darren\My Documents\Electronics\Wavetek SigGen\GPIB_test\WvTk2520_gpib_RTE.py", line 32, in <module>SigGen.clear()File "G:\Programs\Python310\Lib\site-packages\pyvisa\resources\resource.py", line 381, in clearself.visalib.clear(self.session)File "G:\Programs\Python310\Lib\site-packages\pyvisa\ctwrapper\functions.py", line 616, in clearreturn library.viClear(session)^^^^^^^^^^^^^^^^^^^^^^^^File "G:\Programs\Python310\Lib\site-packages\pyvisa\ctwrapper\highlevel.py", line 226, in _return_handlerreturn self.handle_return_value(session, ret_value) # type: ignore^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "G:\Programs\Python310\Lib\site-packages\pyvisa\highlevel.py", line 251, in handle_return_valueraise errors.VisaIOError(rv)pyvisa.errors.VisaIOError: VI_ERROR_TMO (-1073807339): Timeout expired before operation completed.It is important to note that this code will run OK if it is run frequently. The lock out happens if things are left alone for a few minutes.It seems that cycling the power to the USB adapter does something that "clear" does not. Just wondering if others have exprienced and solved this problem?

author: dazz1
author_rank: Frequent Contributor
timestamp: December 29, 2023, 09:39:18 am
content: Done some searching around the Internet. I ran this command to get info on my system setup.Code:>pyvisa-infoMachine Details:Platform ID: Windows-10-10.0.19045-SP0Processor: Intel64 Family 6 Model 94 Stepping 3, GenuineIntelPython:Implementation: CPythonExecutable: G:\Programs\Python310\python.exeVersion: 3.12.1Compiler: MSC v.1937 64 bit (AMD64)Architecture: AMD64Build: Dec 7 2023 22:03:25 (#tags/v3.12.1:2305ca5)Unicode: UCS4PyVISA Version: 1.14.1Backends:ivi:Version: 1.14.1 (bundled with PyVISA)#1: C:\WINDOWS\system32\visa32.dll:found by: autoarchitecture:('x86', 64)Vendor: Rohde & Schwarz GmbHImpl. Version: 7340546Spec. Version: 7340544#2: C:\WINDOWS\system32\visa64.dll:found by: autoarchitecture:('x86', 64)Vendor: Rohde & Schwarz GmbHImpl. Version: 7340546Spec. Version: 7340544None of this has helped my diagnose the problem, but it does show that what I have appears to be working.

author: caiser01
author_rank: Regular Contributor
timestamp: December 29, 2023, 03:43:13 pm
content: Quote from: dazz1 on December 29, 2023, 12:39:41 amTry adding this at the very end of the script.Code:SigGen.clear()sleep(1)SigGen.control_ren(pyvisa.constants.VI_GPIB_REN_ADDRESS_GTL)SigGen.close()rm.close()The control_ren() function does just what it says, controls the REN (remote enable) signal on the GPIB according to a constant you pass it. Passing VI_GPIB_REN_ADDRESS_GTL puts the instrument back into local mode (equivalent to pressing the Local key on the front panel). The REN signal naturally goes away when you unplug the USB adapter. Having this function at the end of the script does the same thing programmatically.

author: coromonadalix
author_rank: Super Contributor
timestamp: December 29, 2023, 04:13:08 pm
content: but it the other case, is there a "keep alive" communication, or maybe do some status polling ?? who would help prevent the disconnection from the 2520 ??

author: caiser01
author_rank: Regular Contributor
timestamp: December 29, 2023, 10:09:21 pm
content: Quote from: coromonadalix on December 29, 2023, 04:13:08 pmNever heard of a GPIB instrument that needed a communication heartbeat. That's not to say one couldn't exist.I'm more inclined to say the Wavetek 2520 may just have a poor GPIB implementation. I have seen that multiple times.If your program completes running cleanly and you want to run it again after some arbitrary length of time, the instrument should communicate again without issue. It sounds as though this instrument may get into a weird state if held in remote without interaction, which should not happen.Apart from the script additions I suggested earlier, another thing to try is:1. Run the script to completion2. Press the Local key on the front panel3. Leave it for a few minutes4. Try running the script againThat will tell you if the issue indeed lies with the instrument being too long in remote mode without communication.

author: rcjoy
author_rank: Regular Contributor
timestamp: December 30, 2023, 07:42:27 am
content: You could try increasing the timeout time. Try 10 or 30 seconds. Just a guess.

author: dazz1
author_rank: Frequent Contributor
timestamp: January 06, 2025, 07:54:03 am
content: HiI am trying to write code for an Electro-Metrics EMC30 EMC test receiver.https://www.eevblog.com/forum/testgear/electro-metrics-em-30-emc-receiver/I am writing pyvisa code to write a command that sets the receiver frequency. The command is 3 bytes of binary data. I will write the numbers here in decimal for clarity, but the data sent is binary bytes. The frequency control values are in the range 0-255.I am a python noob but I have been programming for 45 years.The command format is: 255 xx yywhere:xx = frequency course control byteyy = frequency fine control byte.So an actual command sent might look like: 255 102 47The second two bytes are stored as decimal variables: FreqCse and FreqFine.My question is how do I write these 3 bytes to the gpib interface devices with pyVISA ??I have tried a few different commands and variants.The one that almost works is:emc30.write(bin(255))emc30.write(bin(FreqCse))emc30.write(bin(FreqFine))It doesn't matter what values I put in the two variable, the frequency always goes to zero zero.I have tried: emc30.write_binary_values(255), but that doesn't work. I get an error message that says: TypeError: ... missing 1 required positional argument: "values"That looks like operator error.What is the correct way of writing 3x bytes to my device with PyVISA?

author: Kean
author_rank: Unknown
timestamp: January 06, 2025, 09:49:25 am
content: Quote from: dazz1 on January 06, 2025, 07:54:03 amI don't use PyVISA, but I believe you would want to encode the data in a bytearray (or bytes object).Try this:emc30.write(bytearray([255, 102, 47]))oremc30.write(bytes([255, FreqCse, FreqFine]))

author: dazz1
author_rank: Frequent Contributor
timestamp: January 06, 2025, 10:21:01 am
content: Quote from: Kean on January 06, 2025, 09:49:25 amIn a moment of desperation, resorted to reading the instructions found here:https://pyvisa.readthedocs.io/en/latest/introduction/rvalues.htmlI tried using a list of decimal values (as you have done), typed as 'd', but that didn't work. I think both a list of bytearray should work, but don't.I have raised this as an issue here:https://github.com/pyvisa/pyvisa/issues/883It shouldn't be this difficult to figure out.

author: Kean
author_rank: Unknown
timestamp: January 06, 2025, 10:35:51 am
content: It looks like the write function only accepts a string.Similar to the suggestion on your issue, you can try write_raw but with a byte arrayCode:emc30.write_raw(bytes([255, FreqCse, FreqFine]))But based on the description of that function, you could hit an issue with certain byte values, like the XON/XOFF or even NUL ASCII codes.https://pyvisa.readthedocs.io/en/latest/api/resources.html#pyvisa.resources.SerialInstrument.write_rawEdit: I'm guessing you are using the PyVisa SerialInstrument for a USB serial to an Arduino for the GPIB interface. In that case it appears that flow_control defaults to none...https://pyvisa.readthedocs.io/en/latest/api/resources.html#pyvisa.resources.SerialInstrument