HP-3478A calibration RAM I/O script

~~~ Last release: 1.0 (2023-08-22) ~~~
Download 3478a_cal_ram.py

The HP-3478A 5-1/2 digit multimeter
The HP-3478A 5-1/2 digit multimeter in all its '80s glory. Watch out for that calibration RAM though...

The HP-3478A multimeter is a classic that can be had for a song these days so it finds it way into the hands of many hobbyists. This older device has a known pitfall: its calibration data is stored into an SRAM that is backed up by an internal non rechargeable battery. Without calibration data the instrument is useless, Which means if the battery is depleted or toast, so is the multimeter. Bummer.

Obviously the prolific instrument nerd community is going to find solutions for that. Procedures to replace the battery without losing the calibration data are common and usually involve adding an extra battery while carefully removing the old one. This is still a bit stressful because one mistake and you're instrument is trash (technically you could send it to HP for recalibration, but we all know how much that costs). Recently more advanced solutions have surfaced, notably the replacement of the SRAM with a non-volatile FRAM (see this EEVblog post too). This requires a little daughter PCB with a few logic ICs to ensure compatibility. Quite clever!

Whatever route you chose for your 3478A, once it's time to replace the battery you'll probably want to make a backup of the calibration data before attempting anything. And again, the community found undocumented ways to get that data over HPIB! Yep, I'm not going to invent much on this one, pretty much all the work has already been done by others. But that's not going to stop me writing a nice (?) little (?) calibration read/write python script to get the job done!

As a quick reminder, the calibration RAM is a 256x4 bit jobbie (1kB). 4 bits is a bit annoying to deal with so HP sends 8 bits for every 4 bit in the RAM, adding 0x40. So if the RAM contains 0x7 at one address, the HPIB-received data will be 0x47. Simple enough, and this allows all characters to fall into the nice character zone of ASCII. Brilliant.

The script is fairly straightforward but is maybe a bit longer than expected due to some embellishments like command line options, debug, etc... In short it works like this:

  • Init HPIB and connect to the device using its bus ID.
  • Read the data using the undocumented "Wa" command, where 'a' is the address in the RAM. This is repeated for every byte, one by one.
  • Verify the checksum of each field
  • Write to file.

The resulting file is in ASCII and thus easily to read, transfer, etc... Since the calibration RAM has 256 elements, the output file will be 256 bytes long (again, for each byte only the 4 LSB contain actual data). In debug mode (option '-g') the script outputs the calibration data in pretty formats on the terminal so you can see how the data looks like:

Raw HEX data:
0x00 : 4F404040404440414F4C404F4D404040
0x10 : 40404045414E4242404E474040404040
0x20 : 41414E444C454D4A494949494942414D
0x30 : 4141424B4E494949494949414D424541
0x40 : 4B434040404040404040404040404040
0x50 : 404043474841414F4D4F4C4049494949
0x60 : 4441414C4D4C414A4F49494949494540
0x70 : 45434C4D4A4C40404040404040454440
0x80 : 404F464040404040404045434E4E4D4B
0x90 : 40404040404040454145444F40404040
0xa0 : 4040404045434F414E47404040404040
0xb0 : 404445414E4E47494949484942424D44
0xc0 : 40424B4C494949494849424D424C4E49
0xd0 : 4F404040404040404040404040404040
0xe0 : 4042404142404F434F4D494040404040
0xf0 : 40404040404040404040404040404040

Raw ASCII data:
0x00 : O@@@@D@AOL@OM@@@
0x10 : @@@EANBB@NG@@@@@
0x20 : AANDLEMJIIIIIBAM
0x30 : AABKNIIIIIIAMBEA
0x40 : KC@@@@@@@@@@@@@@
0x50 : @@CGHAAOMOL@IIII
0x60 : DAALMLAJOIIIIIE@
0x70 : ECLMJL@@@@@@@ED@
0x80 : @OF@@@@@@@ECNNMK
0x90 : @@@@@@@EAEDO@@@@
0xa0 : @@@@ECOANG@@@@@@
0xb0 : @DEANNGIIIHIBBMD
0xc0 : @BKLIIIIHIBMBLNI
0xd0 : O@@@@@@@@@@@@@@@
0xe0 : @B@AB@OCOMI@@@@@
0xf0 : @@@@@@@@@@@@@@@@

Addr   Offset    Gain  CRC
0x01 : 000040   1FC0F   D0
0x0e : 000005   1E220   E7
0x1b : 000001   1E4C5   DA
0x28 : 999992   1D112   BE
0x35 : 999999   1D251   B3
0x42 : 000000   00000   00
0x4f : 000378   11FDF   C0
0x5c : 999941   1CDC1   AF
0x69 : 999995   053CD   AC
0x76 : 000000   05400   F6
0x83 : 000000   053EE   DB
0x90 : 000000   05154   F0
0x9d : 000000   053F1   E7
0xaa : 000000   0451E   E7
0xb7 : 999892   2D402   BC
0xc4 : 999989   2D2CE   9F
0xd1 : 000000   00000   00
0xde : 000201   20F3F   D9
0xeb : 000000   00000   00

These details are not too important though; you fill find even more details about the meaning of the data in the EEVblog thread mentioned above.

Data can also be written to the RAM using the "Xad" command, where again 'a' is the address and 'd' is the data byte. For writing the program goes through these steps:

  • Read the calibration file
  • Verify the checksums
  • Write to the instrument
  • Read the calibration data from the instrument
  • Compare with what was written and verify there are no errors.

During my tests of the script I found that the "Q" command also does something calibration-related, as it would write something like "UNLOCK CAL" on the screen. This brings one last thing to know: the front panel calibration switch must be in the unlocked position to be able to write to the RAM. If it is in the locked position then write operations are simply silently ignored. So I find it strange that this "Q" command, whatever it is, would request the user to unlock the calibration switch, while the normal write to the RAM with the X command would not. Oh well. In any case, keep the calibration locked before you have a valid backup of your calibration data! And copy that calibration file somewhere else on your system or cloud just to be sure.

In fact, anyone with an HP4378A should probably make a backup of its calibration data immediately, as a preventive measure, regardless of whether you change the battery or go for the FRAM route. Better safe than sorry!

Enjoy...