atmega-gpib: yet another DIY GPIB-to-USB project - Page 1
Forum section: electronics / projects

author: cellularmitosis
author_rank: Unknown
timestamp: September 02, 2017, 05:42:54 am
content: Gentlemen!Though I've been working on a DIY GPIB project for a few months now, it was only recently that I started making some serious progress.The two things which got me over the hump were:I found a good resource on how GPIB works:http://www.pearl-hifi.com/06_Lit_Archive/15_Mfrs_Publications/20_HP_Agilent/HP_7470A/HP-IB_Tutorial_Description.pdfI started using a 16-channel logic analyzerIn this thread I'll post progress updates on this project, and also make some posts describing how GPIB works, with actual logic analyzer traces.

author: cellularmitosis
author_rank: Unknown
timestamp: September 02, 2017, 05:50:41 am
content: The initial board design lives on github:https://github.com/pepaslabs/atmega-gpibHowever, I made mistake on that board (I swapped the RX / TX pins, which is correctable in software, but prevents you from updating the firmware via the arduino bootloader, which means you have to de-socket the atmel chip every time you change the firmware...). Also, I used the FTDI chip for USB connectivity, and it is a bit of a pain to solder (very tight pin pitch).In other words, don't use these gerbers and order a copy of the board -- I'll soon follow with an updated board design which corrects the RX/TX mistake and uses the MCP2221A for USB, which is DIP format.

author: cellularmitosis
author_rank: Unknown
timestamp: September 02, 2017, 06:00:33 am
content: Let's go through a worked example of sending some data to a Keithley 196 DMM.To send a string to display on the K196, you use the "D" command, followed by the string to display. Commands are executed using the "X" command.So, to display "M", you'd send "DMX" to the K196. To display "EEVBLOG", you'd send "DEEVBLOGX".In order to send "DMX" to the K196, we first need to "address it to listen". This just means sending it "command byte" with its address in the listen mode.Before we do that, we might also need to "reset the bus" -- tell all current talkers to stop talking and all current listeners to stop listening.

author: cellularmitosis
author_rank: Unknown
timestamp: September 02, 2017, 06:17:02 am
content: Unlisten, Untalk, and addressing a device to talk or listenTo address a device to listen, you send it a command byte which is simply its GPIB address, plus 32 (i.e. the hex value 0x20, i.e. bit number 6). To address a device to talk, the command byte is its address plus 64 (i.e. the hex value 0x40, i.e. bit number 7).Valid GPIB address are 0-30. (It seems that by convention, the controller uses address 21).GPIB address 31 is used for the "untalk" and "unlisten" commands.My Keithley 196 is currently configured to use address 17 (which is hex 0x11)To address it to listen, I'd send the command byte 0x31 (17 + 32, or 0x11 + 0x20).To address it to talk, I'd send the command byte 0x51 (17 + 64, or 0x11 + 0x40).To command all devices to stop listening ("unlisten"), the command byte would be 0x3F (31 + 32, or 0x1F + 0x20).To command all devices to stop talking ("untalk"), the command byte would be 0x5F (31 + 64, or 0x1F + 0x40).

author: cellularmitosis
author_rank: Unknown
timestamp: September 02, 2017, 06:44:48 am
content: The handshake: sending and receiving bytesSo, we want to send the following sequence of bytes out on the bus:0x3F: UNLISTEN (optional)0x5F: UNTALK (optional)0x31: Address device 17 to listen0x55: Address device 21 to talk (optional)0x44: "D"0x4D: "M"0x58: "X"But how do we actually send them? GPIB uses three control lines to perform a "handshake", which gates the sending of each byte.(GPIB isn't a clocked bus -- it is more like a parallel version of I2C, where the slowest participant on the bus determines the speed)The three handshake lines are:DAV: Data AvailableNRFD: Not Ready For DataNDAC: Not Data AcceptedMost of the bus lines in GPIB may be either "driven" (tristate), or be operated in open-collector mode, except for these three handshake lines, whichmustbe operated in open-collector mode.The logic is active-low. This, combined with the open-collector scheme, allows a many-to-one communication scheme: many devices may pull a line low, and the last one to release the line will cause the line to flow high (via pull-up resistor), indicating to the controller than all devices have responded.The handshake sequence is a bit confusing because of the inverted (active-low) logic. In the next post I'll describe it using more colloquial terms.

author: cellularmitosis
author_rank: Unknown
timestamp: September 02, 2017, 06:55:55 am
content: The handshake in plain englishFirst, let's start with a colloquial version of what's going on in the handshake sequence.This is two iterations of the handshake loop (steps 1-6), with step 0 as a prerequisite.(see attachment 1)Now let's turn those colloquial phrases into their equivalent GPIB terminology:(see attachment 2)Notice that the talker is flipping one status, while the listener is flipping two statuses. This is because the listener is actually controlling two bus lines, whereas the talker is only controlling one.Now, let's split these steps up into the three bus lines:(see attachment 3)Now let's add a bit of color to highlight the transitions between states (while also showing the state of every bus line at every step)(see attachment 4)Next, let's transform the statuses into TRUE / FALSE values(see attachment 5)Finally, using active-low logic, we can translate those into electrical logic levels (HIGH / LOW)(see attachment 6)

author: cellularmitosis
author_rank: Unknown
timestamp: September 02, 2017, 07:10:19 am
content: RENAlso, you'll need to assert the REN line ("remote enable") for the duration of interacting with the listener.

author: cellularmitosis
author_rank: Unknown
timestamp: September 02, 2017, 07:12:48 am
content: ATNThe ATN line ("attention") is what distinguishes data from commands.If we send the byte 0x3F (Ascii "?") without ATN asserted, then we are just sending an ASCII question mark as data.But if we assert the ATN line while sending 0x3F, that tells the listener to interpret it as a command byte. 0x3F is the "unlisten" command.

author: cellularmitosis
author_rank: Unknown
timestamp: September 02, 2017, 07:16:09 am
content: Putting this all together, we can see what sending this byte sequence looks like to the logic analyzer:For whatever reason, Pulseview's GPIB decoder isn't showing the final decoded byte ("X"), but if you look at the logic lines, the byte is there.

author: cellularmitosis
author_rank: Unknown
timestamp: September 02, 2017, 07:33:05 am
content: Looking more in-depth at the handshake, here's how those 6 steps map to the logic analyzer diagram.

author: cellularmitosis
author_rank: Unknown
timestamp: September 02, 2017, 07:49:10 am
content: prototype firmwareHere's the firmware for the current working prototype:https://github.com/pepaslabs/atmega-gpib/blob/f063d4b4877ea3a536a97403e2d78c42cddd9fce/firmware/firmware.inoThis is currently a "boarduino" wired up to an MCP2221A.To tell the arduino to talk to device 17, send "++addr 17\n" over the serial port.Strings which don't start with "++" will be sent directly to the device, e.g. "DMX\n".(the Arduino will also treat '|' as a newline character, which is useful if you need to send multiple commands at once, e.g. "++addr 17|DMX|").To read one value (read until "EOI" is asserted), send "++read".To read continuously in a loop, send "++stream".As it turns out, simply addressing the Keithley 196 to talk will cause it to stream values forever, so capturing data from this device is as simple as sending "++addr 17\n++stream\n" to the Arduino.

author: bsalai
author_rank: Regular Contributor
timestamp: September 02, 2017, 08:11:07 am
content: You have made great progress. Once you have it all working, do you think it could port to the ESP32? No wires would be pretty slick.Sent from my iPhone using Tapatalk

author: cellularmitosis
author_rank: Unknown
timestamp: September 02, 2017, 08:44:29 am
content: Quote from: bsalai on September 02, 2017, 08:11:07 amThat's a fantastic idea!

author: cellularmitosis
author_rank: Unknown
timestamp: September 02, 2017, 08:52:48 am
content: We can also have a bit of fun with the "D" command

author: bsalai
author_rank: Regular Contributor
timestamp: September 02, 2017, 10:18:38 am
content: Quote from: cellularmitosis on September 02, 2017, 08:44:29 amI can't be much help with programming, but I'd be glad to provide some support, maybe getting some ESP32s or making a donation.Sent from my iPhone using Tapatalk

author: vindoline
author_rank: Unknown
timestamp: September 02, 2017, 12:49:53 pm
content: CM, fantastic progress! You've done a super job of explaining the protocol. Even I think I get it now.I'm looking forward to rev 2 of the board.

author: don.r
author_rank: Frequent Contributor
timestamp: September 09, 2017, 03:47:30 am
content: I triple vote for the ESP32! That would be one heck of an adapter! Not sure how good the Arduino toolchain is yet with the ESP32 though.

author: texaspyro
author_rank: Super Contributor
timestamp: September 09, 2017, 05:01:36 am
content: Here's some GPIB code that I wrote for a Mega Donkey LCD touchscreen micro controller board (MEGA128/MEGA2561).https://github.com/ron-grant/Mega-DonkeyIt has a Prologix emulator in it. And, despite some of the comments, it does support DEVICE mode (at least for the device I was emulating at the time). There is a bunch of fluff in the file (like an emulator for another GPIB controller and some test routines).With a little work you can extract the useful stuff. Should be easy to port to an Arduino, etc. Released under the MIT license.

author: cellularmitosis
author_rank: Unknown
timestamp: September 09, 2017, 05:15:25 am
content: Quote from: texaspyro on September 09, 2017, 05:01:36 amSUUUUUH-WEEEEET!!!Thanks man!

author: vindoline
author_rank: Unknown
timestamp: September 20, 2017, 01:46:29 pm
content: Cellularmitosis, have you verified the v2 board yet? If so, I'll have some made. I just can't take having to swap the chip every time I try and troubleshoot anythingThanks!

author: cellularmitosis
author_rank: Unknown
timestamp: September 20, 2017, 11:48:12 pm
content: vindoline: I just got the board assembled, I'll make sure to verify it works this evening!

author: cellularmitosis
author_rank: Unknown
timestamp: September 22, 2017, 05:48:27 am
content: vindoline, I was able to confirm that the board works, and that serial comms over the MCP2221 work.Unfortunately, I neglected to add a reset button to this board design. I tried a work-around, where I simply soldered a jumper wire to ground, and then briefly touched the wire to pin 1 of the atmel chip. This does cause a reset, but I can't seem to get the Arduino software to upload new firmware via USB upon reset.I'm not sure what I'm doing wrong. Here's a video showing the loop which the Arduino IDE seems to get into: each time I reset the chip, it tries to start transmitting the firmware, but then stops for some reason (just after the first TX activity, it appears). If I reset the atmel again, it tries to upload again, and then gets stuck again.Perhaps uploading via USB simply doesn't work for atmel chips which don't have an external oscillator?

author: Kleinstein
author_rank: Super Contributor
timestamp: September 22, 2017, 08:40:24 am
content: The AVR internal oscillator is not very accurate. It is just borderline for UART operation. So the UART connection to the MCP2221 might be not that reliable and could cause trouble. It is especially a problem if there is an additional rounding error in setting the baud rate.For reliable UART one usually needs a resonator or crystal or individual adjusted clock / baud rate.

author: vindoline
author_rank: Unknown
timestamp: September 22, 2017, 11:41:47 am
content: CM, that's too badI'm assuming that the chip has the correct boot loader on it for using the internal oscillator. Other than that, I have no idea.

author: Kleinstein
author_rank: Super Contributor
timestamp: September 22, 2017, 01:01:06 pm
content: There could also be a problem with the supply voltage / to little decoupling. During writing the flash the µC likely needs a higher current. So a weak regulator could be a problem too. At least I can not see TH decoupling caps. It is OK if there als SMD one on the back - usually no problem to add same afterwords.The clock is borderline accurate for UART, but with a 5 V supply and not to extreme temperature it usually works, but one should consider the clock a possible error source.

author: cellularmitosis
author_rank: Unknown
timestamp: September 22, 2017, 02:35:20 pm
content: Thanks guys, I'll try to reproduce the problem on a breadboard, then throw a logic analyzer at it.

author: vindoline
author_rank: Unknown
timestamp: October 19, 2017, 01:57:26 am
content: Cellularmitosis, has there been any progress on the GPIB project as of late? I'm hoping to be able to put a bit of effort into it and I have a question about your ver 2 pcb. What is the purpose of the "error" led and the configuration jumper? I can't find any reference to these in the code. I may layout a new pcb for this and I'd like it to be compatible with your programming efforts. Thanks.

author: bitseeker
author_rank: Super Contributor
timestamp: October 19, 2017, 02:21:00 am
content: Quote from: texaspyro on September 09, 2017, 05:01:36 amThat's cool, texaspyro. Does that mean that one could use this as a base for making an adapter to add GPIB (e.g., reading values) to pre-GPIB era hardware?

author: texaspyro
author_rank: Super Contributor
timestamp: October 19, 2017, 02:39:26 am
content: Quote from: bitseeker on October 19, 2017, 02:21:00 amIt should be able to do so. I added DEVICE support to do one thing that needed to be done one dark and stormy night in the before times. It did what I needed it to do, but have never really banged on it much.

author: bitseeker
author_rank: Super Contributor
timestamp: October 19, 2017, 04:05:30 am
content: Nifty. I'll have to explore that some more when I refurbish my HP 5216A counter. It has a card edge "printer" port on the back.

author: View[+]Finder
author_rank: Unknown
timestamp: November 15, 2017, 10:20:38 pm
content: Quote from: cellularmitosis on September 02, 2017, 08:52:48 amThanks for your research! It got me headed in the right direction for my 196 GPIB efforts. I'm using Keysight's latest Connection Expert, Python 2.7.14 and PyVISA 1.8, so YMMV. Here a couple of little programs:#Run autoCalimport sysimport timeimport visavisa = visa.ResourceManager()print(visa.list_resources())DMM196 = visa.open_resource('GPIB0::8::INSTR',send_end=True, read_termination= '\r\n', write_termination='\r\n')DMM196.write("DX")DMM196.write("DAUTO CALX")DMM196.write("A1X")time.sleep(10) # 1 sec incrementsDMM196.write("DX")print 'done'#Read some measurements to a fileimport sysimport timeimport visavisa = visa.ResourceManager()print(visa.list_resources())DMM196 = visa.open_resource('GPIB0::8::INSTR',send_end=True, read_termination= '\r\n', write_termination='\r\n')DMM196.write("DX")DMM196.write("F0R3S3P60X")DMM196.write("DF0R3S3P60X")print ''data = open('dataDMM196.csv','w')print (data)for x in range(0, 200):print (DMM196.read()[4:17])data.write (DMM196.read()[4:16] +'\n')time.sleep(1) # 1 sec incrementsdata.close()The VISA library (Keysight version at least) makes the communication easier over GPIB, so I don't know how it would translate into Arduino, etc.