- GPIB: MATE/CIIL vs default protocol
- Missing GPIB EOI at End of Message
- When to Read Measurement Data
- Weird Modal Syntax Error Behavior with 3-character Commands
In the past year, I’ve bought a bunch of measurement devices from a retired hobbyist who has been downscaling his (extensive) RF lab. During my last visit, he offered to add some extras for free, including a Racal-Dana 1992 Universal Counter.
A 1992 can be used as a frequency counter, to measure the delay between two signals, to calculate the clock frequency ratio between 2 signals, and various other special functions, for frequencies all the way up to 1.3GHz. And with up to 10 digits of precision, you get to measure the frequency of your 10MHz crystal oscillator down to the milliHz (but only if your reference clock is accurate enough…) When you start digging into the wonderful world of Time Nuts, the 1992 seems to be well respected. There’s a known issue with the flaky front panel switches, but there are plenty of Youtube video describing how to fix it.
I didn’t know it at the time, but its Buy-It-Now price on eBay is often higher than $500! Thanks, John!
My device came with option 55, a GPIB interface, and option 04E, a high stability oven controlled crystal oscillator (OCXO). John calibrated the instrument with his GPS disciplined oscillator (GPSDO) as reference.
I’ve been looking at making a GPSDO myself, and thought it’d be interesting to use the 1992 to record the phase difference between the raw, high jitter, GPS pulse-per-second (pps) signal that comes out of my cheap M8N GPS receiver module, and the equivalent signal that’s generated by the GPSDO. The first step to make that happen is establish communication between my PC and the 1992 using GPIB. It should be relatively easy to do, but some well-placed booby-traps turned it into something that took a whole day before everything was working as expected.
This short blog post describes the road blocks and how to get past them.
GPIB: MATE/CIIL vs default protocol
The issue that took most of my time was getting the 1992 to talk the right protocol. Section 5 of the User Manual is straightforward enough: you send a string with one or more 2 or 3 characters and optional numerical parameters, and the device will sometimes reply with a string that’s always 21 bytes long.
The problem was that this didn’t work at all. When I sent the internal self-test
I could see some LEDs temporarily flickering on the front panel and see the REM (remote) LED switch
permanently on, but every further GPIB transaction resulted in an error, and the device didn’t
actually switch to
CK mode either…
I eventually stumbled into this conversation on the EEVblog forum, which mentions the existence of an SK4 jumper on the military version of the GPIB board that must be set in the right position. It also links to an amended version of the manual, with the following diagram at page 200/7-22:
Opening up the 1992 can be done by removing just 2 screws, after which you can slide out the bottom cover first, followed by the top:
Here’s a closer look:
This is how the jumper should be positioned if you want the GPIB interface to work as described in the manual. In my case, the jumper was placed over the 2 pins right above it.
In that other position, the GPIB interface will conform to MATE/CIIL specification. Check out my updated blog post about test and measurement protocols to learn more about it.
There are multiple versions of the GPIB interface board. From what I’ve been able to figure out, only version 401820 has the SK4 jumper. It’s part of option 02M which adds support for MATE/CIIL.
Missing GPIB EOI at End of Message
With jumper SK4 in the right position, the 1992 immediately behaved as expected when sending configuration
CK puts it into self-check mode,
PA switches to period measurement on channel A, and
Reading data back was still an issue.
pyvisa for my GPIB adventures.
Here’s the code that you’d expect to work:
import pyvisa pyvisa.log_to_screen() rm=pyvisa.ResourceManager() inst = rm.open_resource("GPIB::14") inst.write("RGS") inst.read()
RGS command is supposed to return the firmware version of the device, but the code
Traceback (most recent call last): 2022-12-14 14:48:52,877 - pyvisa - DEBUG - GPIB0::14::INSTR - reading 20480 bytes (last status <StatusCode.success_max_count_read: 1073676294>) 2022-12-14 14:48:56,053 - pyvisa - DEBUG - GPIB0::14::INSTR - exception while reading: VI_ERROR_TMO (-1073807339): Timeout expired before operation completed. Buffer content: bytearray(b'') File "<stdin>", line 1, in <module> File "/home/tom/.local/lib/python3.8/site-packages/pyvisa/resources/messagebased.py", line 486, in read message = self._read_raw().decode(enco) File "/home/tom/.local/lib/python3.8/site-packages/pyvisa/resources/messagebased.py", line 442, in _read_raw chunk, status = self.visalib.read(self.session, size) File "/home/tom/.local/lib/python3.8/site-packages/pyvisa_py/highlevel.py", line 519, in read return data, self.handle_return_value(session, status_code) File "/home/tom/.local/lib/python3.8/site-packages/pyvisa/highlevel.py", line 251, in handle_return_value raise errors.VisaIOError(rv) pyvisa.errors.VisaIOError: VI_ERROR_TMO (-1073807339): Timeout expired before operation completed.
The solution came, once again, after finding this EEVblog forum post:
I remember back when I was trying to get my 1992 working on GPIB, there was an issue with the EOI line. Apparently, the 1992 doesn’t use it. Make sure that your program isn’t expecting it.
This comment on a National Instruments forum gives more details about EOI:
The best default termination character is none. GPIB (IEEE 488.1) defines a special hardware line, EOI, which is asserted with the last byte to signify the end of a transfer. You should rely on this method to terminate a GPIB transfer, as opposed to a termination byte that is stuffed into the bytestream. Some older devices (primarily those that were initially RS-232) use only an EOS character, and that can be CR, LF, or CR-LF, which is why the option exists to terminate a read transfer on EOS with NI-488.2.
Most devices (such as those following the IEEE 488.2 protocol) use both (they send an LF at the end with EOI asserted). Even in that case, however, you should only really be concerned with the EOI since that is the native termination of the GPIB.
So here’s what’s happening:
- All messages from the Racal 1992 to the controller, your PC, are exactly 21 bytes.
- The messages end with 2 termination characters.
- The GPIB EOI line is never asserted to indicate the end of a message!
import pyvisa rm=pyvisa.ResourceManager() inst = rm.open_resource("GPIB::14") inst.write("RGS") inst.read_bytes(21) <<<<<<<<<<
When to Read Measurement Data
A final, minor, issue was knowing when the 1992 returns data.
Most instruments have a request-reply protocol, where the instrument only has data ready to be read after the controller asks for it.
Not so for the 1992: it will indeed prepare data to be read after it has been sent
a command that starts with an
Rxx, but it also places data in a read-data FIFO whenever
it completes a new measurement. Note also that there is no
Rxx command to read back
measurement data, you just have to assume that there’s going to be data available when
you issue a GPIB read. If not, then
pyvisa will time out.
When you send an
R command, the read-data FIFO gets cleared, you can be sure that
the first data after an
R will be the data that you requested.
If you can’t predict whether or not there’ll be data available in the read-data FIFO,
e.g. because you’re measuring events that don’t happen at predictable points of time,
then you can program the 1992 with the
Q7 command to assert the
GPIB SRQ (Service ReQuest) line when there’s data available, and use the
Unfortunately, SRQ handling is not supported on a Linux machine with
pyvisa and the
pyvisa-py driver, so I wasn’t able to test that.
A decent alternative is to manually poll the GPIB status byte which has the following status bits:
Note that the numbers starts with 1 instead of 0!
pyvisa, you can check this status byte with the
Bit 4 (starting from 0) will be set when there’s data waiting to be read.
Here’s an example of an
stb based polling loop:
import pyvisa rm = pyvisa.ResourceManager() inst = rm.open_resource("GPIB::14") while True: while (inst.stb & 0x10) == 0: print(".", end='', flush=True) pass print(inst.read_bytes(21))
And here’s the result:
.............b'CK+0010.0000000E+06\r\n' .............b'CK+0010.0000000E+06\r\n' .............b'CK+0010.0000000E+06\r\n' .............b'CK+0010.0000000E+06\r\n' .............b'CK+0010.0000000E+06\r\n' .............b'CK+0010.0000000E+06\r\n' .............b'CK+0010.0000000E+06\r\n'
The other alternative is to program is very large timeout:
Weird Modal Syntax Error Behavior with 3-character Commands
On my system, all the example code above worked fine… until it didn’t. I don’t know what happened, but
from one moment to next, all commands with 3 characters resulted in a syntax error, as indicated
import pyvisa rm = pyvisa.ResourceManager() inst = rm.open_resource("GPIB::14") inst.write("RGS") print("STB: 0x%02x" % inst.stb)
The 3 LSBs of STB contain the error code, and a value of 5 means “Syntax error in GPIB command”.
My 1992 was not able to recover from it. (It still hasn’t!) Sending the instrument preset
IP command, power cycling the unit, rebooting the PC, unplugging the GPIB dongle, none of that
I found 3 ways to work around it:
Add a space in front of each command
Instead of this:
Change the GPIB write terminator from
I have no idea why this makes a difference, but it does.
This is magical
This has the benefit over adding a space that you only need to do this once, but it has the potential disadvantage that it may not work on an instrument that doesn’t have my issue.
You can select the correct terminator by checking for syntax errors. Like this:
inst.write_termination='\r\n' inst.write("RUT") if (inst.stb & 0x7) == 5: inst.write_termination='\n\r' inst.write("RUT") if (inst.stb & 0x7) == 5: raise Exception("Can't find working write termination!") else: # Read data from dummy RUT command unit_type = inst.read_bytes(21)
EOIfor write operations
ibtest, which is part of the Linux GPIB tools, I’m also able to make it work by instructing it to not send an
EOIat the end of a transmission (
ofollowed by 0).
pyvisadoesn’t give you the option to not send
I’ve been working a Racal-Dana 1992 driver for
Since I’m the one who’s writing it, I can use the first option without the need to
fiddle with termination options.
It’s unsettling when something that used work perfectly fine suddenly doesn’t, with no known way to restore things. If anyone has an idea, I’d love to hear about it! You can file an issue on GitHub or send a direct message to my Twitter or Mastodon account.