HP 3478A: How to read/write cal SRAM - Page 1
Forum section: electronics / repair

author: MarkL
author_rank: Unknown
timestamp: April 03, 2017, 02:33:56 pm
content: I found a way to read and write the cal SRAM on the 3478A via the GPIB interface. It's an old question on how to (easily) backup the calibration on these devices, and I'm not aware that anyone has figured it out yet.I was inspired to look for hidden GPIB commands by this post:https://www.eevblog.com/forum/repair/hp-3421a-cal-ram/msg1176864/#msg1176864(Sorry for my partial cross-post, but I decided this information really needs to be in a 3478A thread where people can find it.)For those familiar with the 3478A, recall that the cal SRAM is 256 x 4 (NEC UDP5101L or equivalent).For reading, there's a hidden GPIB command called "W". The format is as follows:W<addr>Where <addr> is a single byte address to be read from the calibration RAM. <addr> is in binary, thus allowing access to all 256 locations.The value returned is the nibble at <addr>, but the value is offset by 0x40 so the result is printable. For each "W<addr>" command issued, the 3478A will transmit one byte in range of 0x40 to 0x4f ("@" to "O").I double checked the values returned by "W" with values previously captured via a logic analyzer attached directly to the SRAM. They match. A dump of the concatenated bytes returned looks like this:0000000: 40 40 40 40 40 49 45 41 4d 43 42 4c 4d 42 40 40 @@@@@IEAMCBLMB@@0000010: 40 40 40 41 41 4d 4e 45 41 4d 4c 40 40 40 40 40 @@@AAMNEAML@@@@@0000020: 40 41 4d 40 4d 4c 4d 48 49 49 49 49 49 41 41 4e @AM@MLMHIIIIIAAN0000030: 4d 43 4e 4a 44 49 49 49 49 49 49 41 4e 4e 45 4f MCNJDIIIIIIANNEO0000040: 49 48 40 40 40 40 40 40 40 40 40 40 40 40 40 49 IH@@@@@@@@@@@@@I0000050: 49 46 48 45 46 41 4f 41 41 4e 4b 44 40 40 40 40 IFHEFAOAANKD@@@@0000060: 45 47 40 45 41 4d 43 4d 4d 40 40 40 40 40 47 40 EG@EAMCMM@@@@@G@0000070: 45 4c 40 4f 4d 48 40 40 40 40 40 41 40 45 4d 4f EL@OMH@@@@@A@EMO0000080: 4d 4d 40 40 40 40 40 40 40 40 45 4d 43 4f 4d 4b MM@@@@@@@@EMCOMK0000090: 40 40 40 40 40 40 40 45 4d 4c 41 4e 40 40 40 40 @@@@@@@EMLAN@@@@00000a0: 40 40 40 40 44 45 45 40 4f 41 40 40 40 40 40 40 @@@@DEE@OA@@@@@@00000b0: 40 41 4c 43 4e 4e 41 49 49 49 47 46 42 42 4d 44 @ALCNNAIIIGFBBMD00000c0: 41 42 4b 4f 49 49 49 49 47 49 42 4d 4e 45 42 4a ABKOIIIIGIBMNEBJ00000d0: 47 40 40 40 40 40 40 40 40 40 40 40 40 40 49 49 G@@@@@@@@@@@@@II00000e0: 46 48 45 46 42 4f 41 43 41 4b 4e 40 40 40 40 40 FHEFBOACAKN@@@@@00000f0: 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 @@@@@@@@@@@@@@@@The nibble at address 0x00 goes back and forth between 0x40 and 0x4f if the cal switch is enabled. This is because the firmware writes to this location and then reads it back. The cal switch enables/disables the write line to the SRAM in hardware, so if the firmware was successful in writing a different value to 0x00 it knows the cal is enabled.For writing SRAM nibbles, the hidden GPIB command is:X<addr><val>Where <addr> is a one byte binary address and <val> is a one byte value to be written. Only the lower 4 bits of the value are written to the SRAM. This allows a raw binary value to be specified, or the printable value that was returned by the W command.It's probably not a great design that it only takes one erroneous character, X, sent on the GPIB interface to ruin your calibration constants. Always keep the cal switch off.In the process of trying to figure out the write command, I managed to trash my SRAM pretty badly. I was able to fully restore my SRAM to its previous state, so I can vouch that all this works.It would be nice if someone could write a python or some other multi-platform method that implements the above in a friendly way. There's a lot 3478A's out there. It would make battery replacement a lot less stressful if you could back up the SRAM first and then restore it when done. No more isolated soldering irons, etc. Or even better, it would be good to make a backup *before* the battery goes dead.

author: nfmax
author_rank: Super Contributor
timestamp: April 03, 2017, 09:07:57 pm
content: Just to confirm you mean the addresses are in binary, so a one byte value from 0 to 255, not a string of text like "01010101". Or have I read it wrong?

author: MarkL
author_rank: Unknown
timestamp: April 03, 2017, 09:34:17 pm
content: Quote from: nfmax on April 03, 2017, 09:07:57 pmRight, a one byte binary value, 0 to 255. Not a string representing bits or a decimal or anything ASCII. It also means the GPIB implementation you're using needs to be 8-bit clean for this to work. Granted, it's not consistent with the documented commands, but I guess they didn't care since it's undocumented and simpler to implement with a single byte.Example: Read from address 0x72 is two bytes long: 0x57 0x72

author: lowimpedance
author_rank: Super Contributor
timestamp: April 04, 2017, 12:49:55 am
content: Thanks for the effort you put into this including the restoration of the trashed cal data proving it works..And as you say there are plenty of these meters still in service.

author: MarkL
author_rank: Unknown
timestamp: April 04, 2017, 01:13:34 am
content: Quote from: lowimpedance on April 04, 2017, 12:49:55 amOf course! After I discovered I trashed my calibration, I was *really* committed to finding how the write works.

author: pigrew
author_rank: Frequent Contributor
timestamp: April 06, 2017, 04:49:37 am
content: Excellent.I just (very quickly) wrote a Windows program to read/write the calibration block. It needs a very recent version of the NI or Keysight VISA libraries. I've tested it with a NI USB GPIB adapter.The source code and a zip file containing a build are at:https://github.com/pigrew/HP3478CtrlMarkL, I very much appreciate that you figured out the commands to use.-Nathan

author: dfrederickson
author_rank: Contributor
timestamp: April 06, 2017, 04:38:10 pm
content: Excellent, MarkL.It seems that the 3478 arranges the cal data differently than the 3468 and 3421. Those instruments use 16 nibbles to store the constants for each function-range and what appears to be a 4-nibble ECC checksum.The 3478 stores the cal constants for, by my count, 16 function-ranges. If your data is rearranged as follows then a pattern appears that would support that many function-ranges.@@@@@IEAMCBLMB@@@@@AAMNEAML@@@@@@AM@MLMHIIIIIAANMCNJDIIIIIIANNEOIH@@@@@@@@@@@@@IIFHEFAOAANKD@@@@EG@EAMCMM@@@@@G@EL@OMH@@@@@A@EMOMM@@@@@@@@EMCOMK@@@@@@@EMLAN@@@@@@@@DEE@OA@@@@@@@ALCNNAIIIGFBBMDABKOIIIIGIBMNEBJG@@@@@@@@@@@@@IIFHEFBOACAKN@@@@@@@@@@@@@@@@@@@@@The next task is to figure out how the constants are encoded. I'd like to restore my DMM to at least the factory default parameters. Figuring out the method of calculating the checksum may be the trickier task.BTW, just because the CAL RAM is valid doesn't mean the instrument is calibrated as accuracy drifts with time. If the CAL RAM is corrupt, the instrument will revert to the default parameters.Dave

author: MarkL
author_rank: Unknown
timestamp: April 06, 2017, 05:54:02 pm
content: Quote from: pigrew on April 06, 2017, 04:49:37 amThanks for picking up the ball to write something that makes this method accessible for 3478A owners.I used Perl and bash scripts on linux to do my testing, and they were not written with user-friendliness in mind.

author: dfrederickson
author_rank: Contributor
timestamp: April 06, 2017, 06:57:44 pm
content: Quote from: MarkL on April 06, 2017, 06:22:32 pmHmm, let's see. The input response is linear and the equation for a line is y=mx+b. Constants are stored for Zero and Gain, so, from the HP Journal article for the 3468:Besides ESD, there is also a small chance that an alpha particle or a cosmic ray may alter a single bit of the memory. To protect against this rare occurrence, the two constants for each function and range have parity bits associated with them so that the 3468A's microprocessor can locate singlebit errors and detect double-bit errors. The processor can correct a single-bit error in a calibration constant and the instrument will remain calibrated. If the processor detects more than a single-bit error, the CAL annunciator is displayed and the error bits are set to warn the user that the readings are uncalibrated. When this type of error is detected, the processor uses default values ofzerofor Y andonefor G.I have a pretty good idea of how many nibbles are used for Zero, Gain, and checksum for the 3468 and 3421.http://hpmuseum.org/forum/thread-8061-post-71213.html#pid71213For the 3468 and 3421, calibration values are entered as six digits. The difference between the entered value and the measured value is stored as Zero and the ratio between the entered value and the measured value is stored as the Gain. It's not necessary to store all the significant digits. For example, if the 3 most significant digits for the Zero are always zero, then it's only necessary to save the least significant 3 digits and the sign. Same is true for the Gain correction factor except the most significant digits will be either 1.00 ... or 0.99 ... so the MSB needs to be saved, too.Dave

author: Armadillo
author_rank: Super Contributor
timestamp: April 06, 2017, 07:02:30 pm
content: There are so many uncertainties with claims as yet to be demonstrated, and for all you know, the undocumented command "W" may be returning an error bytes from Global Variables Iberr or ibsta and yes the logic analyser will be reading the same bytes returned. That, I am afraid cannot be taken as an affirmation of correctness.In the other post, dfrederickson wrote;Quote "Now I need to calibrate one parameter at a time and see which data changes, then figure out how the constants and parity/checksum are encoded. Unfortunately the 3478 responds to the B2 command with the B1 command status. Dave"unless you know the location of each parameter and the exact representation taking into account any of the endians, example enter 41.2 represented at location X as 0x34, 0x31, 0x2E, 0x32, "yy" checksum, otherwise is doubtful the application and usability of it.

author: Armadillo
author_rank: Super Contributor
timestamp: April 06, 2017, 07:12:41 pm
content: Quote from: dfrederickson on April 06, 2017, 06:57:44 pmNow those are interesting investigation. thanks

author: dfrederickson
author_rank: Contributor
timestamp: April 06, 2017, 07:18:24 pm
content: Quote from: Armadillo on April 06, 2017, 07:02:30 pmIdoknow the location of each parameter, at least for the 3468 and 3421. Knowing that there are 5 ranges for DCV, 2 for DCI, 1 each for VAC and ACI, and 7 for resistance I can pretty much figure out which function-range is in each row, above. Now I just need to figure out the encoding.Dave

author: Armadillo
author_rank: Super Contributor
timestamp: April 06, 2017, 07:25:45 pm
content: Quote from: dfrederickson on April 06, 2017, 07:18:24 pm+1;

author: MarkL
author_rank: Unknown
timestamp: April 06, 2017, 07:50:26 pm
content: Quote from: Armadillo on April 06, 2017, 07:02:30 pmThe logic analyzer was attached to the data, address, and control lines of the SRAM (U512) and captured each nibble stored at each address. How to set up the logic analyzer capture was discussed in a different thread a couple of years ago:https://www.eevblog.com/forum/testgear/3478a-cal-ram-readout-idea/msg695908/#msg695908The SRAM would not be storing iberr or ibsta anyway since the SRAM is read-only during normal operation. It's only used for calibration data. The internal SRAM of the 8039 processor (128 bytes) is what's used for volatile storage while the unit is running.I have no doubt that "W" returns the nibble at each specified address in the SRAM (and that would be the calibration external SRAM U512, to be specific).Try it for yourself if you don't believe me. Or try reading the service manual theory section 7-F-60, or look at how the SRAM is controlled in the schematic. Verification is always encouraged.

author: MarkL
author_rank: Unknown
timestamp: April 06, 2017, 09:48:02 pm
content: Quote from: dfrederickson on April 06, 2017, 06:57:44 pmOk, read your thread at hpmuseum.One way to tackle this would be to figure out the ECC algorithm so you can poke values into the cal locations to see how they affect readings. (Maybe that's what you had in mind; sorry if I'm stating the obvious...)I'm not familiar with the 3468A or 3421A, but on the 3478A it would be possible to use a logic analyzer to watch the fetch and execution of instructions as it computed the ECC.It should be possible to do a calibration and trigger on a write to any of the associated addresses in the cal SRAM. I'll take a guess that the firmware will write the new cal nibbles, compute the ECC by perhaps re-reading those nibbles, and then write the new ECC, in that order. If true, it's an easy way to bracket the code you want.Well, and then there's always the brute force method. If you're right that there's only 16 bits of ECC, how long will it take to write and test all the possible ECC values (or half, on average)? No finesse points for that approach.

author: dfrederickson
author_rank: Contributor
timestamp: April 06, 2017, 11:06:15 pm
content: Quote from: MarkL on April 06, 2017, 09:48:02 pmHi MarkL,I don't know, but the Infinite Monkeys Method worked before.The 3468 is basically an HP-IL version of the 3478, minus a few extra ranges and rear terminals. The 3421 is a data acquisition instrument that employs a 5.5digit DMM, similar to the 3468 and 3478, but with no front panel controls. The 3468 and 3421 are highlighted in the Feb 83 issue of the HP Journal and the 3478 got an honorable mention.True, it would be easy to write a program that sequentially tried all the different checksums until a status error was not reported. I'll think I'll wait until someone like Sailor simply figures out the algorithm. In the mean time I can load parameters from another 3468 and clear the error. For now that should be accurate enough for what I'm doing.Regards, Dave

author: biot
author_rank: Regular Contributor
timestamp: April 09, 2017, 04:07:22 pm
content: Quote from: MarkL on April 03, 2017, 02:33:56 pmI'm attaching a little Python script that pulls the SRAM values out and drops them to stdout. Use like this:python cal-3478adevicename> mycalThis depends on a properly working linux-gpib setup, anddevicenamemust be a properly configured device in /etc/gpib.conf. No multi-platform GPIB out there, as far as I know.Thanks so much for working this out -- would hate for my 3478A to die on me. At least now I have a backup! The battery seems to be doing OK, so perhaps I don't need to replace it yet?

author: MarkL
author_rank: Unknown
timestamp: April 10, 2017, 03:02:37 pm
content: Quote from: biot on April 09, 2017, 04:07:22 pmThe python script works for me and the data matches my clunky scripts - thanks!I haven't replaced my battery yet and it's now 34 years old. As long as you have a backup, my feeling is not to worry about it. If one day you turn on your meter and the battery is dead, you can reload the calibration constants and still use the meter while waiting for a new battery.Of course it's then time to write the SRAM writer script, or even better write it ahead of time. If you want to PM me a test version I'll try it - I'm not afraid if it takes a couple of spins to get it right and it ruins my constants. Once right you can post it.

author: bingo600
author_rank: Super Contributor
timestamp: April 12, 2017, 07:46:14 am
content: @MarkL et allNow we "just" need to reveal the HP3457's secretsPHK did the 3458A , and you did the 3478AWho's doing the 3457A/Bingo

author: MarkL
author_rank: Unknown
timestamp: April 12, 2017, 09:21:25 pm
content: Quote from: bingo600 on April 12, 2017, 07:46:14 amSounds like a fun challenge, but unfortunately I don't have a 3457A.I did look at the ROM image that's available on KO4BB with "strings" and "xxd". It looks like there's a ROM monitor that can be accessed somehow. That might provide a path to read/write the NVRAM (U511).There's also some occurrences of the words PEEK and POKE in the same area as other GPIB commands. That looks promising but they might need to be enabled first.I doubt it will happen, but if anyone wants to lend me a 3457A for a few weeks I'll give it a shot. I already have a 3456A, so I don't have a good excuse to buy one myself (not to mention making space for another gigantic DMM).

author: biot
author_rank: Regular Contributor
timestamp: April 13, 2017, 09:21:37 pm
content: Quote from: MarkL on April 12, 2017, 09:21:25 pmLooks like a Forth interpreter in there! Unfortunately I don't have a 3457A either.However this might be an interesting avenue to figure out the checksum algorithm -- disassemble the 3478A's ROM.

author: ramon
author_rank: Regular Contributor
timestamp: May 18, 2017, 02:40:57 pm
content: Thank you so much to MarkL for this information and to biot for his python script.I recently bought a cheap 3478a and the first thing I have done is a backup of the calibration RAM using GPIB.This is the output in case someone is still working on how to find the checksum algorithm and wants to compare (I already tried to compare my calibration data with data from MarkL and Pigrew meters)0000000: 4f 40 40 40 46 41 41 42 41 4f 4f 40 4d 46 40 40 O@@@FAABAOO@MF@@0000010: 40 40 45 49 42 41 40 43 45 4e 46 40 40 40 40 40 @@EIBA@CENF@@@@@0000020: 46 42 41 40 4e 4e 4d 4a 49 49 49 49 49 44 42 41 FBA@NNMJIIIIIDBA0000030: 4c 4c 40 4b 43 49 49 49 49 49 49 42 40 45 4f 44 LL@KCIIIIIIB@EOD0000040: 4a 4f 40 40 40 40 40 40 40 40 40 40 40 4f 4f 49 JO@@@@@@@@@@@OOI0000050: 49 49 45 49 45 42 4d 45 41 4e 4a 4e 49 49 49 49 IIEIEBMEANJNIIII0000060: 46 48 41 4c 42 4e 42 4a 4e 49 49 49 49 49 46 41 FHALBNBJNIIIIIFA0000070: 4c 43 4e 45 4a 49 40 40 40 40 40 40 41 4c 42 42 LCNEJI@@@@@@ALBB0000080: 45 4e 49 40 40 40 40 40 40 41 4c 40 4f 4d 4d 46 ENI@@@@@@AL@OMMF0000090: 49 49 49 49 49 49 41 4c 41 40 4f 4a 4c 49 49 49 IIIIIIALA@OJLIII00000a0: 49 49 49 41 4c 40 43 43 4b 46 49 49 49 49 49 49 IIIAL@CCKFIIIIII00000b0: 40 45 43 45 45 4b 47 40 40 40 44 43 49 43 42 4c @ECEEKG@@@DCICBL00000c0: 43 40 4d 4b 40 40 40 40 44 44 43 42 4d 45 4e 4d C@MK@@@@DDCBMENM00000d0: 42 40 40 40 40 40 40 40 40 40 40 40 4f 4f 49 49 B@@@@@@@@@@@OOII00000e0: 49 45 49 45 43 4e 42 4e 44 4a 4c 40 40 40 40 40 IEIECNBNDJL@@@@@00000f0: 40 40 40 40 40 40 4f 4f 40 40 40 40 40 40 40 40 @@@@@@OO@@@@@@@@Also python script to convert the code received from GPIB into actual RAM data (each byte substracted by 64 or 40 hex):Code:#!/usr/bin/pythonfrom functools import partialimport syswith open(sys.argv, 'r') if len(sys.argv) > 1 else sys.stdin as file:for byte in iter(partial(file.read, 1), b''):sys.stdout.write(chr(ord(byte)-64))Can be used like this:$ xxd -r gpibdata | script.py | xxd -g 1Note: I have read again the service manual, and now I understand why the did said 'CAUTION: do not send program codes "W" and/or "X" ... these codes can, under certain conditions, uncalibrate the instrument'

author: MarkL
author_rank: Unknown
timestamp: May 19, 2017, 04:24:31 pm
content: Quote from: ramon on May 18, 2017, 02:40:57 pmAh, good catch! I didn't notice that in the manual, but it certainly provided a clue. In my experimentation I never found any form of the "W" command that would write to memory. Since they mentioned "W" and "X", it wouldn't have killed them to document those commands and, for that matter, similar cal backup commands for a lot of other equipment. Tektronix is also quite guilty of hiding such useful commands.I did the subtraction of 0x40 like this:tr '\100-\117' '\000-\017' < caldata | xxd -g1What I like about Linux... always 100 different ways to do the same thing.

author: ramon
author_rank: Regular Contributor
timestamp: May 22, 2017, 01:35:55 pm
content: Thanks, with 'tr' is much better!And yes, I also think that they should have provided complete information about those gpib codes. Moreover considering that they didn't put any effort to hide the calibration switch in the front panel.The calibration procedure needs so many kinds of expensive calibration devices (in AC,DC,ohms, etc...) that it doesn't make any sense to have such easy-to-turn calibration switch in the front panel. How many devices should have been uncalibrated by mistake?. Do they did that on purpose to increase earnings from maintenance services?Anyway I am very happy with my meter. The schematics are available, and there is a lot of internal information about them.I downloaded the ROM and tried to simulate the code with one free simulator available at acebus website (8048 version 208). Unfortunately the program only allows to load up to 64KB source code (asm listing) and I cannot fit the whole dissasembled 8K code into the simulator (I removed extra spaces and comments, and I was only able to reduce it to 88K in size).The 8048 is quite weird: without CMP or SUB instruction, and also with those pages, mb0/mb1 selector, and bit 12 of program counter. I think I will not be able to find how it works. Is there any thread or progress about that? when I use strings on the ROM I cannot get any useful data. I will need to read the schematics more in detail.

author: MarkL
author_rank: Unknown
timestamp: May 23, 2017, 02:30:25 am
content: Quote from: ramon on May 22, 2017, 01:35:55 pmWhat are you trying to do?I think it's going to be difficult to simulate operation of the firmware. It's very dependent on responses from the hardware. So, you also have to simulate the hardware, which also means simulating the 8039 in the floating section.If you're trying to discover the CRC/ECC algorithm, I think you're going to need a logic analyzer attached to a running meter as I described previously.If you're looking for other hidden commands, the ones that aren't accounted for are: A G I J L O P Q U V Y. The 3478A is a fairly simple machine, so I wouldn't expect anything else hidden of significance.Some other discussion of 3478A firmware disassembly is here:https://www.eevblog.com/forum/testgear/3478a-cal-ram-readout-ideaAnd there's also this thread on the 3468A, which is very similar in design:https://www.eevblog.com/forum/testgear/hp-3468a-in-continual-resetinit/Yeah, the 8048 is very limited. The SUB instruction can be done with the following:CPL AADD A, REGCPL A(Courtesy of the MCS-48 Microcomputer User's Manual.)

author: ramon
author_rank: Regular Contributor
timestamp: May 23, 2017, 04:04:02 pm
content: Thanks for those links, they have very useful information.I am not looking for other gpib commands. I would like to identify the small set of functions that interface with the floating section. How it initiates requests (ohms, VDC, ...) and gets back the data. Also know all the fields of the calibration RAM, including the CRC/ECC algorithm too.But as I don't have a logic analyzer it will be difficult.I can try maybe to find out how the alphanumeric display works. I have seen that it is using Ports P20 to P23 (P23/PWO=1 Update display, P23/PWO=0 No update). That maybe will be the only way I have to find the correct strings into the ROM.

author: dfrederickson
author_rank: Contributor
timestamp: May 23, 2017, 05:34:00 pm
content: Quote from: ramon on May 22, 2017, 01:35:55 pmOur 3478's have a calibration sticker over the front-panel switch, plus, undocumented commands need to be sent, so I'd say not very many.QuoteMost folks get their instruments calibrated by a third party, so probably not.Quote from: MarkL on May 23, 2017, 02:30:25 amI don't know the algorithm, but I do know the default values for the 3468:0000000000000000000000000000FFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000000So for a default gain of 1 (maybe saved as gain-1) and an offset of zero, the ECC checksum is 0xFFFF.I suspect the 3478 checksum is similar.

author: nfmax
author_rank: Super Contributor
timestamp: June 12, 2017, 02:23:34 pm
content: Here is a short Python 3 program to download the calibration RAM and print it to stdout, using the tentatively identified formatting. It uses the PyVISA library and so should run on any platform that has a VISA implementation. I tested it on Windows 7, using the Keysight IO libraries with a 82357B USB/GPIB controller.The VISA address of my DVM is hard-coded in the source, but it's easy enough to change.It seems to work OK, but I am a novice Python programmer, and there are no guarantees!

author: WaveyDipole
author_rank: Frequent Contributor
timestamp: June 13, 2017, 05:46:51 pm
content: Thanks for this information. Backing up thew CAL data was one of the first questions I asked when I got my meter. It was calibrated but the battery still looked original and a replacement seemed sensible sooner rather than later. Unfortunately this answer didn't come soon enough so after a bit of research I did the replacement without a backup, which was quite nerve racking. I was a major relief when I completed the task and got the 'SELF TEST OK' message on power up!I have since written a program to control the 3478A. It still needs a bit of work on it but I am thinking of including the CAL backup/restore functionality into it. The only problem I have, is that I am using an Arduino based GPIB adapter. As far as I know, there is no NI driver for it, so I'm using direct COM port communication. I will upload the source somewhere when its ready though. It is written inn QT and although I'm currently working on Windows, I will also test it on Linux. In the meantime I will keep an eye on this thread for further developments.

author: dfrederickson
author_rank: Contributor
timestamp: June 13, 2017, 08:02:42 pm
content: Quote from: WaveyDipole on June 13, 2017, 05:46:51 pmLooks like an NI driver can be found here:http://sine.ni.com/apps/utf8/niid_web_display.model_page?p_model_id=368

author: WaveyDipole
author_rank: Frequent Contributor
timestamp: June 13, 2017, 09:03:55 pm
content: Thanks. At least it seems one does exist. Unfortunately my version of Labview/NI/IVI does not appear to be supported. It seems to be Labview 2012 SP1f3 version 12.0.1 and came supplied with the Rigol Oscilloscope. Would there not also have to be a driver for the GPIB adapter?

author: dfrederickson
author_rank: Contributor
timestamp: June 13, 2017, 09:57:45 pm
content: Sorry. Yes, the adapter will need a driver to interface to LabVIEW. It might be easier to just buy an adapter off eBay, like I did.

author: WaveyDipole
author_rank: Frequent Contributor
timestamp: June 28, 2017, 03:23:49 pm
content: I have uploaded my HP3478A control program code to GitHub. This is the first time I have ever done that!https://github.com/WaveyCode/HPRDMMAt present it does not contain the code for reading the calibration data as I'm having lots of trouble acquiring it from the meter. I suspect this is down to the Arduino adapter, but I'm not sure. I've been experimenting with a python script and got something that resembles the output I should be getting but its not 256bytes long and contains the phrase 'CR or LF inserted' which is an error message embedded in the adapter code. Sorry, but I don't have an NI capable GPIB adapter to test with.

author: iainwhite
author_rank: Unknown
timestamp: June 29, 2017, 04:08:55 pm
content: I have been playing with Pigrew's windows C# program (fromhttps://github.com/pigrew/HP3478Ctrl)I forked my own version athttps://github.com/iainkwhite/HP3478Ctrland after tinkering a bit, managed to read my cal data.Here is what I got (formatted to lines of 16 bytes)Code:@@@@BAIBMLOMKL@@@@BBBLDNBMI@@@@@BBMMMAMCIIIIIEBM@MLJEIIIIIIBMCMAJI@@@@@@@@@@@OO@@@FFCADAACNFIIIHGIALLEAJMIIIIHH@ECC@L@IIIIIHALL@AK@IIIIII@EDEMJNIIIIIH@EDCDKJIIIIIIALL@LJDIIIIII@EDBEKI@@@BFBCLCA@NB@@@@BFCLEAEMM@@@@@@@@@@@OO@@@FFCBDBBCNC@@@@@@@@@@@OO@@@@@@@@Edit: add screenshot

author: pigrew
author_rank: Frequent Contributor
timestamp: June 30, 2017, 04:24:21 am
content: Quote from: iainwhite on June 29, 2017, 04:08:55 pmThanks for the changes, I've merged most of the changes back into my branch, and posted a new binary:https://github.com/pigrew/HP3478Ctrl/releases/tag/v0.20170630-Nathan

author: WaveyDipole
author_rank: Frequent Contributor
timestamp: June 30, 2017, 07:10:20 pm
content: Quote from: dfrederickson on June 13, 2017, 09:57:45 pmI had considered that option, but everything I have seen on there so far costs more than the meter did!Of course, if I had something compatible then I could try pigrew's program!

author: scuba31
author_rank: Newbie
timestamp: August 13, 2017, 06:23:47 am
content: All,Thanks to everyone who contributed to (finally) solving this problem!I had never considered the "hidden GPIB command" possibility.I was approaching this from the perspective that electronics would need to be designed and built to interface with the 5101 IC inside the multimeter.I was just starting to lay out a prototype in Kicad when I decided to see if this had been solved in the 8 months since I last checked - and to my surprise, it has.I have 3 of these HP3478A multimeters that I replaced the batteries using a torch solder iron.Using the Visual Basic program provided on this forum, here are the calibration constants that my 3 multimeters report out.Meter #1@@@@CEFBB@BBNI@@@@CDBBL@ANG@@@@@CBAACLNIIIIIIGBCLEAKD@@@@@@BBBM@NL@@@@@@@@@@@OO@@@GHFBLMCELG@@@@HEALONCLE@@@@@H@EELDMM@@@@@A@E@@MNL@@@@@A@ENCANG@@@@@A@DEEENK@@@@@A@ELALN@@@@@@@@D@N@NM@@@AABCC@CCNO@@@@AACBE@AOB@@@@@@@@@@@OO@@@GHFCMLMBKO@@@@@@@@@@@OO@@@@@@@@Meter #2J@@@BIIB@@ALML@@@@BIB@BABNM@@@@@CB@@LNN@IIIIIEB@LMLJFIIIIIIBOC@EK@@@@@@@@@@@@OOIIICEAADABELNIIIH@H@E@B@LMIIIIGI@EBDBKNIIIIIH@E@OAKEIIIIII@EOENJBIIIIIH@EOCAKBIIIIIH@EOEEJLIIIIIH@ELLOIN@@@@HBC@@CON@@@@@@HC@B@ONC@@@@@@@@@@@OOIIICEABD@EBLN@@@@@@@@@@@OO@@@@@@@@Meter #3O@@@AHIAEEC@MO@@@@AGAEBMDMN@@@@@BAEBEONAIIIIIEADN@OJKIIIIIIADON@JG@@@@@@@@@@@OOIIIA@BBL@NEL@IIII@A@EECCLJIIIIIA@EDNEKEIIIIII@EDNLJFIIIIIH@ECCAKNIIIIII@ECD@KMIIIIII@ECNCK@IIIIIH@EMDCKAIIIIBBBDACALLIIIIIBBDBELKG@@@@@@@@@@@OOIIIA@BBE@CMLJ@@@@@@@@@@@OO@@@@@@@@

author: Squiddaddy
author_rank: Regular Contributor
timestamp: September 07, 2017, 12:35:55 am
content: Thanks pigrew!! I just downloaded your program and successfully read the SRAM from my 3478 meter.Has anyone tried to write their values back using your program yet?I am getting ready to try to replace the battery in my meter, and in case I lose my config, I'd like to know if it works.I guess I'm gun shy to try it yet.I don't like being the guinea pig. LOLHere are my SRAM values, in case someone is trying to analyze data between all of our posts.@@@@A@HBCM@MMG@@@@ACBBNENMFIIIIIIBCNDAKAIIIIIABBAB@LJIIIIIGBCAABLB@@@@@@@@@@@OO@@@DIGB@MLELKIIIICB@EC@MLAIIIIID@DDDOKC@@@@@@@ED@COC@@@@@@@EBONMK@@@@@@@EB@@OH@@@@@@@ECCLNH@@@@@@ALADMN@IIIIFGCDEEEKHIIIIIDCCDBCKO@@@@@@@@@@@OO@@@CAICBLE@ML@@@@@@@@@@@OO@@@@@@@@Thanks again to everyone involved in coming up with this solution to our problem!!!!

author: pigrew
author_rank: Frequent Contributor
timestamp: September 07, 2017, 12:51:25 am
content: Quote from: Squiddaddy on September 07, 2017, 12:35:55 amWell,I tested it out a while ago, but I think I had to fix a few issues I the code after that. I'm sure the command works, but there is a chance there are still bugs in my code.-Nathan

author: jca1955
author_rank: Newbie
timestamp: December 22, 2017, 06:22:26 pm
content: This has been a great discussion! For those interested, I have Matlab scripts to read and write a 3478A's calibration SRAM. More information can be found on these routines at my blog, here:http://k6jca.blogspot.com/2017/12/save-and-restore-hp-3478a-calibration.htmlIf you don't have Matlab, the procedures are (hopefully) straight-forward enough for you to adapt to your language of choice.- JeffP.S. If using these scripts, you will also need the Mathwork's "Instrument Control" toolbox.

author: jklasdf
author_rank: Regular Contributor
timestamp: January 05, 2018, 01:47:45 am
content: I also read back my calibration SRAM using biot's script:Code:$ ./cal-3478a.py hp3478a > cal.txt$ xxd cal.txt00000000: 4040 4040 4041 4141 4141 4f4f 4d4c 4040 @@@@@AAAAAOOML@@00000010: 4040 4040 4141 4144 444f 4440 4040 4040 @@@@AAADDOD@@@@@00000020: 4141 414e 4240 4e4c 4949 4949 4943 4142 AAANB@NLIIIIICAB00000030: 434c 454b 4849 4949 4949 4941 424f 444f CLEKHIIIIIIABODO00000040: 4a44 4040 4040 4040 4040 4040 4040 4049 JD@@@@@@@@@@@@@I00000050: 4949 4843 4941 4444 404e 4b49 4949 4949 IIHCIADD@NKIIIII00000060: 4049 4045 4144 424c 4649 4949 4949 4240 @I@EADBLFIIIIIB@00000070: 4542 4f42 4b48 4949 4949 4949 4045 4e41 EBOBKHIIIIII@ENA00000080: 454b 4049 4949 4949 4940 4445 4244 4b4a EK@IIIIII@DEBDKJ00000090: 4040 4040 4041 4045 4344 4f4e 4340 4040 @@@@@A@ECDONC@@@000000a0: 4040 4040 4544 4c4e 4d4c 4040 4040 4041 @@@@EDLNML@@@@@A000000b0: 4045 4545 424e 4d49 4949 4842 4242 424c @EEEBNMIIIHBBBBL000000c0: 4c4e 4a4e 4949 4949 4842 4242 4e4c 414b LNJNIIIIHBBBNLAK000000d0: 4240 4040 4040 4040 4040 4040 4040 4949 B@@@@@@@@@@@@@II000000e0: 4948 4349 4245 4045 4f4b 4540 4040 4040 IHCIBE@EOKE@@@@@000000f0: 4040 4040 4040 4040 4040 4042 4040 4040 @@@@@@@@@@@B@@@@For reference, here is the relevant section of my /etc/gpib.conf for the multimeter (you will also need another section for the GPIB adapter). I have my hp 3478a set for decimal code 01 (only dip switch for A1 set, ASCII code character '!' for listen and 'A' for talk):Code:device {minor = 0name = "hp3478a"pad = 1sad = 1}

author: kelchm
author_rank: Regular Contributor
timestamp: January 23, 2018, 03:40:37 am
content: Has anyone had luck using an Arduino based GPIB adapter to accomplish this?

author: Squiddaddy
author_rank: Regular Contributor
timestamp: February 07, 2018, 03:41:24 pm
content: I used an Agilent USB clone form Ebay, and it worked great. No clue about any Arduino ones though.I also used Pigrew's program since I use Windows.I still haven't changed my battery yet since it still has life, but I wanted a backup just in case it died, or if I screwed up changing the battery.Thanks again to everyone who worked on this issue to at least give us a chance.

author: Miti
author_rank: Super Contributor
timestamp: March 01, 2018, 02:19:48 am
content: Quote from: pigrew on June 30, 2017, 04:24:21 amThanks All for an amazing work!I have two HP3478A, I replaced the battery on one and the other one follows this weekend. I was able to save the calibration using the Python HP3478A.py, thanks nfmax! When I run pigrew's program I get this exception. I guess I'm missing some Labview components. I have Labview 2016 on my computer, not sure if that Ivi.Visa is something that I have to install separately. Thanks in advance!

author: Miti
author_rank: Super Contributor
timestamp: March 02, 2018, 11:44:22 am
content: I recompiled it with Visual Studio Community Edition and it works now. I've attached what works for me.

author: pigrew
author_rank: Frequent Contributor
timestamp: March 02, 2018, 01:36:55 pm
content: Sounds good. Ivi.Visa is the library I use to connect to the equipment. It's a fairly new library (within the last two years), and I linked with version 5.8 which may mean that you'd need to update your GPIB drivers (Keysight or NI) to get my binary to work. The GPIB drivers should also install IVI.Visa library.

author: Squiddaddy
author_rank: Regular Contributor
timestamp: March 08, 2018, 05:35:39 pm
content: Miti,Did you replace your battery while powered on, or did you back up the ram, change battery, and then restore ram?I backed up my ram, but haven't changed out the battery yet. Guess I'm chicken. LOL

author: fenugrec
author_rank: Frequent Contributor
timestamp: March 08, 2018, 10:10:03 pm
content: Nice !can't wait to try this on my unit. In the meantime I've written a small utility that verifies checksums and dumps each cal "entry" . Not super useful yet but it's mainly a starting point for when we figure out what each cal entry does.Code is here for anyone interested :https://github.com/fenugrec/hp3478a_utils

author: Miti
author_rank: Super Contributor
timestamp: March 09, 2018, 03:28:14 am
content: Quote from: Squiddaddy on March 08, 2018, 05:35:39 pmI replaced the batteries on two meters with the power on, after I saved the RAM using both, Python and Windows applications. I plugged the soldering station into a UPS disconnected from AC. Make sure that you also disconnect any other load from the UPS otherwise you may have grounding through that load. For example if a PC is connected to the UPS but the monitor is plugged into the wall, you're grounded.I didn't need to restore after, all went well. I used Kapton tape to isolate everything around the battery terminals on the PCB, only the "operation" site was exposed like you see in surgeries.The funny thing is that less than an hour after the "surgery" we had a power outage for about a minute.Man that was close!Before I had the guts to do it, I tried the backup/restore on another meter from work that is not used anymore, the type with transformers, mine are newer, with opto couplers and the C application works.I modified the file and I've got an "Uncalibrated", then I restored it and I've got "Self test OK". One little detail though, when you copy/paste the data from the application window into a text file, place the cursor one row below the last row of data. Do the same when you restore the data, basically copy the last new line or carriage return, otherwise it doesn't work.I've got the batteries from Sayal (in Toronto) STOCK No. BCC-4194, 3.6V.I'm not sure if they needed replacement though, both old Panasonic batteries measured over 3.3V and the date code seem to be 2003 . Anyway, it's done,they should be good for another 10 -15 years at least.The next project, replacing my Tek. 2445B battery backed calibration RAM with F-RAM.

author: lmester
author_rank: Regular Contributor
timestamp: March 11, 2018, 11:12:04 am
content: Quote from: MarkL on April 03, 2017, 02:33:56 pmMarkL,Great job! I'll no longer have to worry about a dead battery killing my 3478A calibration!I've just recently found this thread. I don't check EEVBLOG very often. Im very late geting to this partyThe user "fenugrec" brought this topic back up to the top of the list. That's how I noticed it. Even better, "fenugrec" has a link to a C program that he wrote that can decode/verify the checksums for the 3478A calibration data. I've added his checksum algorithm into my meter control software. I'm using BBC BASIC for my windows program. This was not just a code copy & paste. I had to convert his C code into BBC BASIC code. So far, my tests are good. Checksums are correct.Below are the 256 nibbles of cal data from my meter and, next, some debug data from a test of my version of "fengurec" 's checsum algorithm.I can put up a link to my HP3478A program if anyone is interested. My software will only work with Prologix adapters or clones that support the Proligix commands.Code:@@@@CA@BLLLNLG@@@@CABLLCOLO@@@@@DBLLOELMIIIIIDAEBAOKF@@@@@@AEBMNML@@@@@@@@@@@OOIIIE@BADODEL@IIII@D@E@MNKGIIIIIA@EDNNJLIIIIII@ECDDKIIIIIII@EABLKEIIIIII@EBBOKAIIIIII@EBMAKDIIIIII@EBDOJO@@@BF@CNOE@MB@@@@BECN@@MMJ@@@@@@@@@@@OOIIIE@BCLCOBKJ@@@@@@@@@@@OO@@@@@@@@Calibration data checksum test:@@@CA@BLLLNLG : CkSum = (199 + 56) Checksum OK.@@@@CABLLCOLO : CkSum = (207 + 48) Checksum OK.@@@@@DBLLOELM : CkSum = (205 + 50) Checksum OK.IIIIIDAEBAOKF : CkSum = (182 + 73) Checksum OK.@@@@@@AEBMNML : CkSum = (220 + 35) Checksum OK.@@@@@@@@@@@OO : CkSum = (255 + 0) Checksum OK.IIIE@BADODEL@ : CkSum = (192 + 63) Checksum OK.IIII@D@E@MNKG : CkSum = (183 + 72) Checksum OK.IIIIIA@EDNNJL : CkSum = (172 + 83) Checksum OK.IIIIII@ECDDKI : CkSum = (185 + 70) Checksum OK.IIIIII@EABLKE : CkSum = (181 + 74) Checksum OK.IIIIII@EBBOKA : CkSum = (177 + 78) Checksum OK.IIIIII@EBMAKD : CkSum = (180 + 75) Checksum OK.IIIIII@EBDOJO : CkSum = (175 + 80) Checksum OK.@@@BF@CNOE@MB : CkSum = (210 + 45) Checksum OK.@@@@BECN@@MMJ : CkSum = (218 + 37) Checksum OK.@@@@@@@@@@@OO : CkSum = (255 + 0) Checksum OK.IIIE@BCLCOBKJ : CkSum = (186 + 69) Checksum OK.@@@@@@@@@@@OO : CkSum = (255 + 0) Checksum OK.

author: fenugrec
author_rank: Frequent Contributor
timestamp: March 13, 2018, 04:32:36 pm
content: Quote from: lmester on March 11, 2018, 11:12:04 amI know, the traffic on these forums is insane - come back after a few days, there's enough "recent posts" to fill a few pages !Glad you managed to port the checksum code succesfully.I've been working a bit on analyzing the firmware for these, I almost wanted to resurrect the 3-year old threadhttps://www.eevblog.com/forum/testgear/3478a-cal-ram-readout-idea/25/but I don't have much to add yet. However I did add my annotated copy of the disassembly on my repo,https://github.com/fenugrec/hp3478a_utils/tree/master/ROM_disasm. I've identified GPIB code, lots of BCD arithmetic, some leads into the display code (hint : the're not saved as plain ASCII strings...).Anyone else interested in working on the disasm ? I'm trying to accomplish two things,- determine the format of the cal constants- long-term : change one button function to enable relative measurements (save offset when pressed, subtract from display).

author: Miti
author_rank: Super Contributor
timestamp: March 24, 2018, 02:38:58 am
content: Quote from: fenugrec on March 08, 2018, 10:10:03 pmI was thinking, when I altered the calibration values in my meter (on purpose) to validate the write function in pigrew's program , it shows "UNCALIBRATED" for a moment but then it works. However, when you select the range that was altered, it shows the "CAL" sign. This way we can play with the calibration entries and see what ranges they affect. No risk at all now that we know how to restore it.Moreover, reading the manual, only 15 ranges need to be calibrated (DCV 30mV, 300mV, 3V, 30V, 300V, ACV 3V, DCA 300mA, 3A, Ohms 30, 300, 3K, 30K, 300K, 3M, 30M). ACA constants are calculated using DCV, DCA and ACV, unless you want to calibrate that range.Looking at all the dumps posted and saved from my meters, there are 3 entries that are always @@@@@@@@@@@OO so I assume they are not used and above the first row of @@@@@@@@@@@OO there are 5 entries... maybe DCV?Just saying...

author: fenugrec
author_rank: Frequent Contributor
timestamp: March 27, 2018, 03:04:20 am
content: Quote from: Miti on March 24, 2018, 02:38:58 amAgreed. It could also be done simply be setting one range on the dmm, and writing bogus entries to the cal RAM until the reading changes.QuoteGood observation, and my analysis of the firmware agrees - there are no references to those 3 entries (5, 0x10 and 0x12)Also, there is definitely a separation between the first 6 nibbles and the last 5. Look at the "beautified" data of one of the dumps posted here (iainwhite) :Code:**** \dev\hp3478\hp3478a_utils\hp3478util.exe**** (c) 2018 fenugrecentry 00: 0 0 0 2 1 9 2 D C F Dentry 01: 0 0 0 0 2 2 2 C 4 E 2entry 02: 0 0 0 0 0 2 2 D D D 1entry 03: 9 9 9 9 9 5 2 D 0 D Centry 04: 9 9 9 9 9 9 2 D 3 D 1entry 05: 0 0 0 0 0 0 0 0 0 0 0entry 06: 0 0 0 6 6 3 1 4 1 1 3entry 07: 9 9 9 8 7 9 1 C C 5 1entry 08: 9 9 9 9 8 8 0 5 3 3 0entry 09: 9 9 9 9 9 8 1 C C 0 1entry 0A: 9 9 9 9 9 9 0 5 4 5 Dentry 0B: 9 9 9 9 9 8 0 5 4 3 4entry 0C: 9 9 9 9 9 9 1 C C 0 Centry 0D: 9 9 9 9 9 9 0 5 4 2 5entry 0E: 0 0 0 2 6 2 3 C 3 1 0entry 0F: 0 0 0 0 2 6 3 C 5 1 5entry 10: 0 0 0 0 0 0 0 0 0 0 0entry 11: 0 0 0 6 6 3 2 4 2 2 3entry 12: 0 0 0 0 0 0 0 0 0 0 0I like to think those 999999 values are "negative BCD" numbers but I haven't made it that far in my analysis. If someone would like to help me look at the BCD arithmetic, that would be awesome. So far I've made some pretty good progress - identified GPIB, display and keypad code, as well as some of the internal comms to the floating ADC controller.

author: Miti
author_rank: Super Contributor
timestamp: March 27, 2018, 03:26:57 am
content: First 6 nibbles = Gain, next 3 = Offset, last 2 = Checksum?

author: fenugrec
author_rank: Frequent Contributor
timestamp: March 27, 2018, 03:39:00 am
content: Quote from: Miti on March 27, 2018, 03:26:57 amNot quite, my tool already strips the checksums - what is printed is all data.

author: Miti
author_rank: Super Contributor
timestamp: March 27, 2018, 11:28:13 am
content: Ahh, I missed that but my theory stays. For the first 5 entries the first 6 nibbles are all around zero if, as you said, 999... meas negative and the last 5 nibbles are all around 2Dxxx so one may be the offset and the other the gain. I expect the offset to be pretty close to zero.It becomes Interesting, I may play with the numbers over the weekend.

author: Miti
author_rank: Super Contributor
timestamp: March 28, 2018, 01:06:22 am
content: OK, so I couldn't wait until the weekend and today after work I played with my "lab rat" again and check this out!Cal entry # Range1 30 mV DC2 300 mV DC3 3 V DC4 30 V DC5 300 V DC6 Not used. It doesn't even show "UNCALIBRATED" if altered, you can put your name there.7 All AC Volts ranges8 30 Ohm 2W, 4W9 300 Ohm 2W, 4W10 3 KOhm 2W, 4W11 30 KOhm 2W, 4W12 300 KOhm 2W, 4W13 3 MOhm 2W, 4W14 30 MOhm 2W, 4W15 300 mA DC16 3A DC17 Not used18 300 mA and 3A AC19 Not usedI also experimented with the constants for the 30V range. I used a 9V battery to see changes. I've attached the results. The first 6 nibbles are the offset, the next 5 are a kind of a gain and the last 2 the checksum. The checksum is an 8 bits constant made of the last two nibbles. If you add the checksum with all the nibbles in that entry, you get 255. The "gain" doesn't really do what I expected so it needs more thinking but the offset is bang on. The 999 thing is like the zero level is at 1000000 but you only see the last 6 digits. So for a positive value of 136 you just add 136 to 1000000 and the constant is 000136. For -136, you subtract from 1000000, so the constant is 999864. I know, it doesn't make sens... at least to me. Maybe it's a bingo moment for a software guy.As you can see, the calibration constants are common for 2W and 4W Ohm ranges. That's why the manual says that you should calibrate in the mode that you are using it.Checksum example:@@@A@IADOD@MM -> hex 0 0 0 1 0 9 1 4 F 4 0 D D Checksum = 0xDD 1+9+1+4+F+4+DD = 0xFF

author: fenugrec
author_rank: Frequent Contributor
timestamp: March 28, 2018, 01:28:51 am
content: Quote from: Miti on March 28, 2018, 01:06:22 amAwesome !! And you did a pretty thorough job, thanks for that.Quotehehe I did a double take on the unused entries but simply because you started your numbering at 1, where I used 0 !QuoteInteresting - I'll see if I can find some hints in the firmware.Quotemakes sense. As I thought, this is 6 digit BCD, right, so adding 999 999 + 1 , rolls over to 0.

author: Miti
author_rank: Super Contributor
timestamp: March 28, 2018, 01:54:16 am
content: So you say the calculations are done in BCD? Looksstupidout of fashion to me...but hey...it works.

author: fenugrec
author_rank: Frequent Contributor
timestamp: March 28, 2018, 02:16:06 am
content: Quote from: Miti on March 28, 2018, 01:54:16 amHehe, say not stupid, but rather out of fashion. Think of the advantage : numbers are already in a format ready to be displayed, or sent over GPIB as text with minimal work. Looking at firmware disassembly it's very obvious it wasn't easy to fit all this in an 8kB ROM and get decent performance !Pros :- add 0x30 to each digit and you have ASCII !- adding and subtracting is not much harder than on multi-byte base2 on these CPUs because they have special flags and opcodes to help with BCD ops- no overhead required to convert between base 10 and 16 - save on code size but also speed (5.6Mhz clock , but throughput is IIRC closer to 1MHz)Cons :- mult / div probably require more code in BCD, this is beyond my experience- ADC readings are most likely plain base2, so at least one bin-to-bcd conversion is required

author: Miti
author_rank: Super Contributor
timestamp: March 28, 2018, 02:20:36 am
content: Quote from: fenugrec on March 28, 2018, 02:16:06 amSorry, I corrected it.Interesting, the offset constants seem to be BCD but the "gain" is in hex. Maybe all the calculations that involve mult/div are done in hex, then it comes the conversion to BCD and the offset is applied right at the end.

author: fenugrec
author_rank: Frequent Contributor
timestamp: March 28, 2018, 03:01:35 am
content: Quote from: Miti on March 28, 2018, 02:20:36 amQuite possible. Would you have time to run a few more tests ? As long as your 9V battery is stable (ideally to the last digit) that would be fine. Or maybe on one of the resistance scales, the readings will probably be even more stable .The test would be to modify, individually, some of the the 5 "gain" digits, by + 1 and - 1. I think that would give more insight into the math used. For example these test values for the 30V range:Code:13F1C (your initial gain)23f1c03f1c14f1c (change just the second digit)13e1c (change just the third)I'd do it myself, but I'm away from my gear for a few weeks !Check it out, I updated the dump format :Code:#offsetgain?range0000010914F4030 mV DC0100000913411300 mV DC02000001134F53 V DC0399999413F1C30 V DC0499999913FE1300 V DC0500000000000(Not used)06000324135D3ACV0799997705D3030 Ohm 2W/4W0899999804210300 Ohm 2W/4W09000000042F23 KOhm 2W/4W0A00000004F3530 KOhm 2W/4W0B9999990403F300 KOhm 2W/4W0C99999904F0E3 MOhm 2W/4W0D9999990355230 MOhm 2W/4W0E9998442315D300 mA DC0F99998423D243A DC1000000000000(Not used)1100011823EF1300 mA/3A AC1200000000000(Not used)See how the "gain" values are similar within a same mode !

author: Miti
author_rank: Super Contributor
timestamp: March 28, 2018, 11:14:26 am
content: Quote from: fenugrec on March 28, 2018, 03:01:35 amI forgot to mention that the battery went down a bit during my experiment yesterday so for stability to the last digit I'll have to use a 3V reference that I have (a 0.02% linear regulator). Give me the values that you want to try for the 3V range.

author: fenugrec
author_rank: Frequent Contributor
timestamp: March 28, 2018, 01:28:04 pm
content: Quote from: Miti on March 28, 2018, 11:14:26 amPerfect ! how aboutCode:134F5 (orig value)234F5034F5144F5 (2nd digit)135F5 (3rd digit)optional:134E5 (4th)134F6 (5th)The last two (4th and 5th digits), not really necessary I think.I'm still not sure if that 5 digit "gain" group is actually two or more separate constants - as you know, the ranges can be calibrated either using a fullscale value or 1/3 FS (1V, 10V etc..) , maybe that makes a difference on the constants.What would be sad is if this was just a raw number/command sent to the ADC section that directly affects the conversion process, and don't really equate to a linear gain correction.

author: Miti
author_rank: Super Contributor
timestamp: March 28, 2018, 10:57:02 pm
content: Here you go.Every more significant nibble is 10 X the one before it. I would expect 16 X...or?Regarding the calibration at FS or 1/3 FS, I don't think it needs separate variables. The gain can be calculate either way, you just need to detect the level and you loose some precision at 1/3 FS.

author: fenugrec
author_rank: Frequent Contributor
timestamp: March 29, 2018, 03:02:56 am
content: Quote from: Miti on March 28, 2018, 10:57:02 pmThanks!I ran those numbers in a spreadsheet a bit. I ran solvers with different possible linear equations (all equivalent, strictly speaking, but the solver didn't converge equally well )test #1 =offset + adc * (g0 + g1*gain)Didn't go too well; poor correlation when the most significant digit of the gain changed.test #1b (naive) =offset + adc * gainsame thing, the gain's first digit screwed things up.test #2 nothing specialtest #3 =offset + adc * (gain + g0)This is very similar to test #1 but I tried to give the solver some better initial guesses for the constants. In the end I get an almost believable correlation with these hand-tweaked numbers :adc = 0.0452413 (well, 452413 counts / 1E8 ; a 19-bit ADC would give max 524288 counts so this is reasonable)g0 = 6553600 (ho ho, = 100 * 2^16 )the solver actually came up with g0 around 6557000 which felt too close to be a coincidence.The numbers are a bit disappointing. Note how for some reason the 5th line is way off compared to the others !Code:readingtheor.error300054300072-17.7864747599815303014303037-22.7216222800198297093297107-13.851327240001430035030025792.9050785200088300083300084-0.684941919986159300051300071-20.0626136400388300054300072-17.8317160800216This is of course all a bunch of guesswork on my part. I can't explain how they do the unpleasant math of all that shifting and multiplying with ~19bit ADC readings + at least one internal constant + the gain correction. The answers are in the firmware but there's a lot happening in that 8kB file...

author: Miti
author_rank: Super Contributor
timestamp: March 29, 2018, 03:31:41 am
content: Do you think there's a fixed, ideal constant that is expected by design and the calibration constant correct that fixed constant?

author: fenugrec
author_rank: Frequent Contributor
timestamp: March 29, 2018, 04:30:10 pm
content: Quote from: Miti on March 29, 2018, 03:31:41 amWell that's what my model indicates, and it would certainly be reasonable : they knew the actual realized gain is going to be very very close to their design gain. If they were to save the exact gain factor determined during calibration, it would need a lot of significant digits - and that's a waste of cal RAM !In other words, if the nominal gain is supposed to be (random number) 0.54, but when calibrated it might be, say, 0.54010033. Storing that kind of number takes lots of space, unless you save just the "10033" part, knowing you have to shift then add it to the nominal 0.54 .In other news - I was looking at some data in the firmware... Some ASCII like "UC", 0x20 (space)...Code:00000000 13 05 0C 06 20 14 05 13 14 20 20 20 00 55 43 20 12 01 0D 20 06 01 09 0C 20 00 55 43 20 12 0F 0D ¶¶¶¶ ¶¶¶¶ ¶UC ¶¶¶ ¶¶¶¶ ¶UC ¶¶¶00000020 20 06 01 09 0C 20 00 FA FA FA FA FA FA FA FA FA FA FA FA 00 15 0E 03 01 0C 09 02 12 01 14 05 04 ¶¶¶¶ ¶úúúúúúúúúúúú¶¶¶¶¶¶¶¶¶¶¶¶¶00000040 00 81 04 20 0C 09 0E 0B 20 06 01 09 0C 00 81 04 20 14 05 13 14 20 06 01 09 0C 00 08 10 09 02 20 ¶¶ ¶¶¶¶ ¶¶¶¶¶¶ ¶¶¶¶ ¶¶¶¶¶¶¶¶¶00000060 01 04 12 53 20 54 4F 00 20 20 0F 16 0C 04 20 20 00 20 20 20 20 20 20 20 20 20 20 20 20 00 13 05 ¶¶¶S TO¶ ¶¶¶¶ ¶ ¶¶¶00000080 0C 06 20 14 05 13 14 20 0F 0B 00 ¶¶ ¶¶¶¶ ¶¶¶But looks a bit like garbage ? well the LCD driver doesn't accept straight ASCII so they mapped A-Z starting at 0x01. Here's the actual strings :Code:00000000 53 45 4C 46 60 54 45 53 54 60 60 60 40 55 43 60 52 41 4D 60 46 41 49 4C 60 40 55 43 60 52 4F 4D SELF`TEST```@UC`RAM`FAIL`@UC`ROM00000020 60 46 41 49 4C 60 40 3A 3A 3A 3A 3A 3A 3A 3A 3A 3A 3A 3A 40 55 4E 43 41 4C 49 42 52 41 54 45 44 `FAIL`@::::::::::::@UNCALIBRATED00000040 40 01 44 60 4C 49 4E 4B 60 46 41 49 4C 40 C1 44 60 54 45 53 54 60 46 41 49 4C 40 48 50 49 42 60 @¶D`LINK`FAIL@ÁD`TEST`FAIL@HPIB`00000060 41 44 52 53 60 54 4F 40 60 60 4F 56 4C 44 60 60 40 60 60 60 60 60 60 60 60 60 60 60 60 40 53 45 ADRS`TO@``OVLD``@````````````@SE00000080 4C 46 60 54 45 53 54 60 4F 4B 40 LF`TEST`OK@cool !

author: relmes
author_rank: Newbie
timestamp: March 31, 2018, 07:04:11 pm
content: Update 2018/04/26 - Note there was an error in the script which led to a few memory locations reporting incorrect information. Correct script (Version 0.2) attached now but you also need to patch the GPIO6.1.ino file to tweak how it processes ESCaped input. Many thanks toxxbfor feeding back on the issue.Patch for GPIO6.1.ino:Code:--- GPIB6.1.ino+++ GPIB6.1.new.ino@@ -226,8 +226,8 @@case CR:case NL:- // if (isesc) goto loadchar;- if (isesc) { Serial.println("CR or LF inserted");goto loadchar; }+ if (isesc) goto loadchar;+ //if (isesc) { Serial.println("CR or LF inserted");goto loadchar; }*comp = NULL; // replace USBeos with nullif (gotplus == 2) { // got a "++" at the beginnig: its a command!The original message follows (note the outputs shown below contain errors in some values as they are from the original script----Quote from: kelchm on January 23, 2018, 03:40:37 amI think I have, created a rather hacked together system.Centronics 36 Way printer cable + a Dremel got me a 24 way Centronics GPIB plug.Added that to an Ardunio with the code fromhttp://egirland.blogspot.co.uk/2014/03/arduino-uno-as-usb-to-gpib-controller.htmlPython script used to communicate to the Arduino attached. (Excuse the python code - it works but isn't exactly optimal. Rename extension to .py)Update the code to set the relevant HPIB Address and com port for your Arduino connection.Once running you can send commands to the device or use the special command "read-sram" and it will read the sram of the HP 3478A and print the output to screen.At present I've not got it writing the SRAM data to file or implemented anything to write it back.Example output (from my HP 3478A):0000000: 40 40 40 40 40 49 41 41 42 4e 40 45 4d 40 40 40 @@@@@IAABN@EM@@@0000010: 40 40 41 47 41 42 4f 4d 41 4d 47 40 40 40 40 40 @@AGABOMAMG@@@@@0000020: 41 41 42 4d 44 4c 4d 4e 49 49 49 40 49 45 41 43 AABMDLMNIII@IEAC0000030: 4e 44 4f 4a 48 49 49 49 49 49 49 41 43 4d 4f 44 NDOJHIIIIIIACMOD0000040: 4a 45 40 40 40 40 40 40 40 40 40 40 40 40 40 49 JE@@@@@@@@@@@@@I0000050: 49 48 40 40 44 41 4e 4d 45 4d 4b 43 40 40 40 41 IH@@DANMEMKC@@@A0000060: 40 46 41 4c 40 45 4c 4d 4a 40 40 40 40 40 49 41 @FAL@ELMJ@@@@@IA0000070: 4c 42 41 4e 4d 48 40 40 40 40 40 40 41 4c 41 4c LBANMH@@@@@@ALAL0000080: 40 4e 45 40 40 40 40 40 41 41 4c 41 4d 4c 4d 47 @NE@@@@@AALAMLMG0000090: 40 40 40 40 40 40 41 4c 4f 42 45 4d 4c 40 40 40 @@@@@@ALOBEML@@@00000A0: 40 40 40 41 4c 42 4c 43 4e 41 40 40 40 40 40 41 @@@ALBLCNA@@@@@A00000B0: 41 4d 40 41 4f 4e 40 49 49 49 49 43 44 42 40 44 AM@AON@IIIICDB@D00000C0: 42 44 4c 48 49 49 49 49 49 42 42 40 45 42 40 4c BDLHIIIIIBB@EB@L00000D0: 47 40 40 40 40 40 40 40 40 40 40 40 40 40 49 49 G@@@@@@@@@@@@@II00000E0: 47 48 45 42 42 4c 44 4e 41 4b 46 40 40 40 40 40 GHEBBLDNAKF@@@@@00000F0: 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 @@@@@@@@@@@@@@@@Output looks to in keeping with what others have so I think it is all good, but I've not tried writing data back yet.Hope this helps.

author: xbb
author_rank: Newbie
timestamp: April 25, 2018, 11:31:24 pm
content: Quote from: relmes on March 31, 2018, 07:04:11 pmThanks for your script, I tested it with an Arduino and while the output looks ok, the checksum verification with fenugrec's tool fails.There are some more characters which require escaping (LF 10, Forward Slash 47 in my case), so I tried to just escape every character and the output now validates fine.However you need also to remove or comment out the line 232 from GPIB6.1.ino which prints "CR or LF inserted" when you escape the CR/NL charsDiff:Code:--- HP3478A-SRAM.txt 2018-04-26 00:57:24.031777400 +0200+++ HP3478A-SRAM_2.txt 2018-04-26 00:58:02.302675400 +0200@@ -104,10 +104,7 @@# This code reads the sram from HP 3478a and stores output in 2 arraysfor addr in range(elements):- cmd = "W" + chr(addr)- # If we are at the ESC char then add again to allow it to pass through to Device- if addr == 27:- cmd = cmd + chr(addr)+ cmd = "W" + chr(27) + chr(addr)ser.write(cmd +'\r\n')out = ser.read(1)This is the output before:Code:0000000: 4c 40 40 40 43 45 47 42 4f 4d 4c 41 4c 4c 40 40 L@@@CEGBOMLALL@@0000010: 40 40 43 45 42 4f 40 43 45 4d 4e 40 40 40 40 40 @@CEBO@CEMN@@@@@0000020: 44 42 4f 4e 4f 42 4c 4b 49 49 49 4c 49 44 42 4f DBONOBLKIIILIDBO0000030: 4d 44 4d 49 4f 49 49 49 49 49 49 42 4e 45 4e 44 MDMIOIIIIIIBNEND0000040: 4a 42 40 40 40 40 40 40 40 40 40 40 40 4f 4f 49 JB@@@@@@@@@@@OOI0000050: 49 48 47 40 44 42 4c 45 4f 41 4b 47 49 49 49 48 IHG@DBLEOAKGIIIH0000060: 44 47 40 45 45 42 44 4c 41 49 49 49 49 48 45 41 DG@EEBDLAIIIIHEA0000070: 4c 4e 4d 45 4a 41 49 49 49 49 49 48 40 45 45 43 LNMEJAIIIIIH@EEC0000080: 45 4b 48 49 49 49 49 49 48 40 45 45 41 4e 4b 41 EKHIIIIIH@EEANKA0000090: 49 49 49 49 49 48 40 45 43 41 4c 4b 45 49 49 49 IIIIIH@ECALKEIII00000A0: 49 49 48 40 45 45 41 4e 4b 41 49 49 49 49 49 48 IIH@EEANKAIIIIIH00000B0: 40 45 45 43 40 4b 4d 40 40 40 40 43 46 43 4f 45 @EEC@KM@@@@CFCOE00000C0: 42 4c 4d 41 40 40 40 40 40 43 43 40 4d 42 42 4e BLMA@@@@@CC@MBBN00000D0: 48 40 40 40 40 40 40 40 40 40 40 40 4f 4f 49 49 H@@@@@@@@@@@OOII00000E0: 48 47 40 44 43 4d 41 45 41 4c 43 40 40 40 40 40 HG@DCMAEALC@@@@@00000F0: 40 40 40 40 40 40 4f 4f 40 40 40 40 40 40 40 40 @@@@@@OO@@@@@@@@And after:Code:0000000: 4c 40 40 40 43 45 47 42 4f 4d 45 41 4c 4c 40 40 L@@@CEGBOMEALL@@0000010: 40 40 43 45 42 4f 40 43 45 4d 4e 40 40 40 40 40 @@CEBO@CEMN@@@@@0000020: 44 42 4f 4e 4f 42 4c 4b 49 49 49 49 49 44 42 4f DBONOBLKIIIIIDBO0000030: 4d 44 4d 49 4f 49 49 49 49 49 49 42 4e 45 4e 44 MDMIOIIIIIIBNEND0000040: 4a 42 40 40 40 40 40 40 40 40 40 40 40 4f 4f 49 JB@@@@@@@@@@@OOI0000050: 49 48 47 40 44 42 4c 45 4f 41 4b 47 49 49 49 48 IHG@DBLEOAKGIIIH0000060: 44 47 40 45 45 42 44 4c 41 49 49 49 49 48 45 41 DG@EEBDLAIIIIHEA0000070: 4c 4e 4d 45 4a 41 49 49 49 49 49 48 40 45 45 43 LNMEJAIIIIIH@EEC0000080: 45 4b 48 49 49 49 49 49 48 40 45 45 41 4e 4b 41 EKHIIIIIH@EEANKA0000090: 49 49 49 49 49 48 40 45 43 41 4c 4b 45 49 49 49 IIIIIH@ECALKEIII00000A0: 49 49 48 40 45 45 41 4e 4b 41 49 49 49 49 49 48 IIH@EEANKAIIIIIH00000B0: 40 45 45 43 40 4b 4d 40 40 40 40 43 46 43 4f 45 @EEC@KM@@@@CFCOE00000C0: 42 4c 4d 41 40 40 40 40 40 43 43 40 4d 42 42 4e BLMA@@@@@CC@MBBN00000D0: 48 40 40 40 40 40 40 40 40 40 40 40 4f 4f 49 49 H@@@@@@@@@@@OOII00000E0: 48 47 40 44 43 4d 41 45 41 4c 43 40 40 40 40 40 HG@DCMAEALC@@@@@00000F0: 40 40 40 40 40 40 4f 4f 40 40 40 40 40 40 40 40 @@@@@@OO@@@@@@@@

author: relmes
author_rank: Newbie
timestamp: April 26, 2018, 09:12:12 am
content: Quote from: xbb on April 25, 2018, 11:31:24 pmYou are right. It needs to escape some other chars as well as GPOB6.1.ino processes a few chars specially. (Namely , ESC, LF, CR and +). You're method of just escaping all is a great idea. Thank you - if I can I'll edit my original post to highlight the issue.For completeness this is the patch for the GPIB6.1.ino file (swapping which goto loadchar line is commented - it needs to call loadchar just not print back to the serial):Code:--- GPIB6.1.ino+++ GPIB6.1.new.ino@@ -226,8 +226,8 @@case CR:case NL:- // if (isesc) goto loadchar;- if (isesc) { Serial.println("CR or LF inserted");goto loadchar; }+ if (isesc) goto loadchar;+ //if (isesc) { Serial.println("CR or LF inserted");goto loadchar; }*comp = NULL; // replace USBeos with nullif (gotplus == 2) { // got a "++" at the beginnig: its a command!

author: sundance
author_rank: Regular Contributor
timestamp: July 10, 2018, 12:10:41 pm
content: Any new insights on how the calibration SRAM data is encoded? (esp. the gain part)

author: fenugrec
author_rank: Frequent Contributor
timestamp: November 09, 2018, 02:43:04 am
content: Just found something hidden in plain sight : the HP Journal, 1983-02 issue, has an article about the 3478A, which is presented as the "HP-IB version of the 3468".They mention a few things about cal :- offset is applied to raw ADC reading, *then* gain factor is applied. Makes sense since the calibration process makes you short/zero the reading first, then test full-scale.- They also say this about the checksums:QuoteInteresting, but I wonder if at some point they removed parity-correction; either that or it's pretty well hidden in the disasm...

author: Miti
author_rank: Super Contributor
timestamp: November 14, 2018, 08:33:10 pm
content: I wonder what's the meter showing during calibration. Is it showing the raw numbers? If yes, maybe it's worth calibrating a range, 3V DC range for example, now that we know which is which, and see how the raw numbers correlate with the calibration constant.

author: fenugrec
author_rank: Frequent Contributor
timestamp: November 15, 2018, 03:43:07 am
content: Quote from: Miti on November 14, 2018, 08:33:10 pmThat won't be necessary ! Just finished figuring out the gain constants, with the help of partial MAME emulation.My cal dumper produces output like this for each range :Code:entry # offset gain? range00 000368 3EDC5 30 mV DCThe offset is BCD, we knew this. I thought the gain was an actual hex value, but not quite - it's a weird mix of signed hex digits and decimal scaling (...) I'll try to explain.1) ADC gives a raw, 8-digit packed BCD reading (4 bytes). (ex.: 1021520, 1 021 520). This is sign-extended into 5 bytes. I'm not sure the lowest digit is significant or always 0.2) Add offset : pregain = ADC + cal_offset * 10 == ADC + 3680 == 1 025 2002.5) not sure exactly why , but it seems we add 50 here. Maybe for rounding ? 1 025 2503) then we need the gain factor "gain_const". In the cal dump, it's printed as "3EDC5" and must be interpreted this way :Code:get digit_n as hex;if digit_n > 8, then factor_n = digit_n - 16gain_const = 1 + (digit_1 / 100) + (digit_2 / 1000) + ... (digit_5 / 1E6);So for the example above "3EDC5", we haveCode:gain_const = 1 + (3 / 100) + (-2 / 1000) + (-3 / 1E4) + (-4 / 1E5) + (5 / 1E6);gain_const = 1.0276654) display_raw = pregain * gain_const , so 1 053 614. Well, simulation gives 1 053 610, but rounding / trunction, so yeah.5) display = display_raw / 10 and/or adjust decimal point. I lost track of the number of trailing 0's !And, that's pretty much all there is to it.

author: coromonadalix
author_rank: Super Contributor
timestamp: November 15, 2018, 12:00:32 pm
content: wow great work, since im totally noob in programming, is there an updated GPIO6.1.inoavailable to download,I have to reinstall my win 10 i dont have any compilers / ide ... at the momentthks

author: Miti
author_rank: Super Contributor
timestamp: November 16, 2018, 02:49:57 am
content: Quote from: fenugrec on November 15, 2018, 03:43:07 amBravoAmazing work Fenugrec!Now we need an application where you say "I want to read 10 digits more on 3V DC" and it reads the constant, calculates, modifies and writes it back.Pigrew,Can you code something?

author: coromonadalix
author_rank: Super Contributor
timestamp: November 18, 2018, 04:30:27 pm
content: Quote from: Miti on November 16, 2018, 02:49:57 amWhat do you mean by : "I want to read 10 digits more on 3V DC" you want a 10 digits resolution

author: Miti
author_rank: Super Contributor
timestamp: November 18, 2018, 10:10:06 pm
content: Quote from: coromonadalix on November 18, 2018, 04:30:27 pmWhat I mean is that, compared with a calibrated instrument, my instrument reads less by 10 digits. Calibrate reads 3.00000V, mine reads 2.99990V, so I need to alter the calibration constants to bring it in line with the calibrated one. Preferably you do a full calibration but it is not always easy for a hobbyist. Another application would be to bring an instrument to a reasonable calibration state, after loosing the calibration constants due to a dead battery.

author: coromonadalix
author_rank: Super Contributor
timestamp: November 19, 2018, 02:16:29 am
content: ahhhhhhhh ok thks for the clarification

author: Pete2
author_rank: Contributor
timestamp: November 20, 2018, 07:09:28 am
content: Great thread. I just got my (first?) 3478A and am planning to replace the battery. Seems like it's never been replaced (yellow Panasonic with an expiry date 00). The unit itself seems to be manufactured in 1991. Plenty of volts in the battery still: about 3.4 VI would like to get the cal memory backed up but I'm missing a GPIB adapter and cable. I'd like to use linux, so what's the best adapter (ie. cheapest) that works?

author: coromonadalix
author_rank: Super Contributor
timestamp: November 20, 2018, 09:40:36 pm
content: it would be the arduino project :http://egirland.blogspot.com/2014/03/arduino-uno-as-usb-to-gpib-controller.html

author: Pete2
author_rank: Contributor
timestamp: November 22, 2018, 06:56:09 am
content: Thanks, I will probably get an Agilent 82357B adapter at some point, seems ebay has plenty of them at under 100 USD.

author: coromonadalix
author_rank: Super Contributor
timestamp: November 22, 2018, 11:04:03 am
content: @ pete2 be careful there's a ton of fake Agilent 82357B usb gpib adapters around .......

author: Pete2
author_rank: Contributor
timestamp: November 23, 2018, 05:30:56 am
content: coromonadalix, thanks for the tip. Any way to know which ones are fake? Also, do fake ones work at all? Almost all of them are listed as "new in box". If some of them are fakes, how to tell apart...

author: MarkL
author_rank: Unknown
timestamp: November 23, 2018, 04:52:49 pm
content: Quote from: Pete2 on November 23, 2018, 05:30:56 amIt's usually hard to tell from photos and descriptions, but you can be pretty much guaranteed it's counterfeit if coming from China or Taiwan.There's a lengthy thread on it here, and someone noticed that there's a lack of metal shielding on the fakes:https://www.eevblog.com/forum/testgear/flood-of-new-agilent-82357b-gpib-usb-adaptors-on-ebay-the-real-deal/msg983752/#msg983752The fakes also have poorly spelled Certificates of Authenticity (COA), non-existent serial numbers which can be checked on the Keysight web site, mismatched serial numbers on the box/certificate/unit, and really terrible soldering/rework on the inside if you open it up. All is detailed in that thread, including someone who did an unboxing of a real one to show what to expect.Some people have had success using the fakes. But many are unstable, and some just don't work at all. I don't recall reading that anyone didn't get a refund after reporting a counterfeit.

author: steve1515
author_rank: Regular Contributor
timestamp: August 03, 2019, 01:32:27 am
content: In case anyone is interested, I decided to create my own program to read and write the calibration data from the HP 3478A. It also displays the gains and offsets for each range from existing calibration files.Program Download:https://github.com/steve1515/hp3478a-calibration/releasesInstructions & Source Code:https://github.com/steve1515/hp3478a-calibrationHope someone finds this useful.

author: ErnieW
author_rank: Newbie
timestamp: August 27, 2019, 09:52:15 pm
content: Hi, I am new to the blog and have just acquired a 3478A to complement my range of test equipment (which is mostly for rf measurements). I opened it to check the battery which is still 3,4V. But it is always good to backup the cal values - just in case.Unfortunately the above program requires a Prologix GPIB Interface, which I do not have.I have a hp 82357B GPIB - USB interface. As I am not a programmer and steve1515 has released his source code, maybe someone in the group can modifiy his code to work with my interface.Probably this would also be useful to other members.Regards Ernst

author: Miti
author_rank: Super Contributor
timestamp: August 30, 2019, 02:42:02 pm
content: Check reply #44. That program should work with your adapter. Thanks to member pigrew.

author: ErnieW
author_rank: Newbie
timestamp: September 01, 2019, 12:35:42 pm
content: Thanks, this worked for me. But would be nice to see an interpretation of the cal values.

author: pigrew
author_rank: Frequent Contributor
timestamp: September 01, 2019, 01:32:37 pm
content: Quote from: ErnieW on September 01, 2019, 12:35:42 pmI'm glad it worked. I doubt I will get around to updating the software any time soon (I don't have a business of changing 3478A batteries...). However, I would accept github pull requests.

author: alocam
author_rank: Regular Contributor
timestamp: October 05, 2019, 10:10:34 pm
content: Hello,I have two HP3478A meters that I purchased recently, and it looks like your program would be nice to get the cal data our for backup purposes. However, I only have access to an HP5810a GPIB ethernet gateway.Do you know whether it would be feasible to reconfigure the program to make it work with such GPIB interface instead of the USB one?Regards!

author: fenugrec
author_rank: Frequent Contributor
timestamp: October 06, 2019, 01:13:06 am
content: Quote from: alocam on October 05, 2019, 10:10:34 pmMost likely, reading cal constants is very simple (https://github.com/fenugrec/hp3478a_utils/blob/master/hp3478util.c#L258) and should be easily programmed or done manually with any GPIB interface. You'll have to work out the details of how to program yours though, how to use its API etc.

author: lmester
author_rank: Regular Contributor
timestamp: January 19, 2020, 05:39:59 am
content: Thanks to code provided by steve1515 I've now added the ability to edit the gain and offset for each calibration entry into my HP3478A control program. This lets you "tweak" your cal without going through the full calibration procedure.https://mesterhome.com/gpibsw/hp3478a/index.htmlI have some questions that steve1515 or others on this thread may be able to answer.What is the valid range for the gain value? It seems that Steve's algorithm (or my implementation of it) fails when the gain is outside the range of 1 to 1.055555. Have any of you seen a gain value outside of that range? If so, I'll need to do more work on the cal edit feature in my program.

author: fenugrec
author_rank: Frequent Contributor
timestamp: January 19, 2020, 02:28:01 pm
content: Quote from: lmester on January 19, 2020, 05:39:59 amIt should be possible to have gains up to 1.077777, and below 1 probably from 0.911112 if my math was right ? (doubtful, I can't remember the results in MAME)He wrote his algorithm slightly differently to mine, and I just noticed a bug in mine - with that fixed, they should now be fairly equivalent. I haven't look at the disasm in a while though; and looking at some cal dumps now I'm not sure what we're doing is correct (i.e. subtracting those negative digits >= 9 from the whole gain constant). But I have a spreadsheet and some tests that would tend to confirm that, so whatever. Some example gain constants :Code:gain_constgain13F1C1.012906fff1c0.988906888880.911112

author: steve1515
author_rank: Regular Contributor
timestamp: January 21, 2020, 09:20:43 pm
content: Hmm... I took a look at what my code would return for these example results and I get something different when the raw value is equal to 8. It looks like it's possible that I have a bug where I should be subtracting 16 when the nibble is >= to 8 instead of just > 8. (I'm missing the equal sign.) If I make that correction, I get the same results as fenugrec.This is what I'm currently getting:Code:Raw Gain13F1C 1.012906fff1c 0.98890688888 1.088888This is what fenugrec's code returns:Code:Raw Gain13F1C 1.012906fff1c 0.98890688888 0.911112Note the difference in the last entry. I suppose I should hold off on making any correction since fenugrec believes we might both be doing something incorrect in the decoding. I'll go with whatever fenugrec says since he understand the firmware much more then I do.fenugrec, what do you think? Should I make the correction or should we look into this some more?

author: fenugrec
author_rank: Frequent Contributor
timestamp: January 22, 2020, 02:18:15 pm
content: Hi Steve,Quote from: steve1515 on January 21, 2020, 09:20:43 pmIMO it wouldn't hurt to run a few more tests. One could simply hook up the meter to a reasonably stable source (or resistor), and try a bunch of different gain constants and note the results. We did this a while ago but only crudely with 3-4 constants IIRC.Now I'd be curious to test one range with offset=0 and gain=00000 then changing some gain digits for key values, i.e. 0,7,8,9,A,F. I'd try changing maybe the first and 3rd digit, so around a dozen tests in total (i.e. 00000, 70000, 70700, etc) plus maybe the two extremes, 77777 and 88888. Still fairly simple, and definitely easier than analyzing 8048 assembler.

author: lmester
author_rank: Regular Contributor
timestamp: January 22, 2020, 02:28:29 pm
content: Steve,With the test data I get the same results as you. It looks like I did implement your gain unpack code correctly.Code:Raw Gain13F1C 1.012906fff1c 0.98890688888 1.088888Since I'm allowing the user to edit a gain or offset value I first must unpack the data. After the user submits the revised value I then re-pack it with a new checksum.It looks like the problem is in my code to re-pack the gain value. I'm getting different results on two of the three test gains.Code:DecodeValueEncodeValue13F1C1.01290613F1c1.012906FFF1C0.9889060110F1.001099888881.088888FFFFE0.988888It looks like what I need is a correct algorithm for re-packing the gain into the meter calibration format. Mine is not working correctly for all gain values.Would you or fenugrec be able to help me get the gain data properly re-packed? Also, let me know if I need to make changes in the unpack algorithm.Below is the flawed function that I'm currently using.Code:function RevGain$(g)'reverse gain. calculate gain encoded value in hex.'Uncompressed gain in g. Returns encoded gain in RevGain$gt=g-1 '?? 1 is a constant & not used in the calc. is this correct ??RevGain$="" 'Build new string into a null string.for i = 6 to 2 step -1'Add any needed trailing 0's to get i digits in numbergd=val(right$(mid$(str$(gt)+"00000",1,i+2),1))if gd>5 thencd=gd+6gt=gt+(10-gd)*10^-ielsecd=gdgt=gt-gd*10^-iend ifgt=int((gt+(5*10^-11))*10^10)/10^10 'round off to fix compiler math errorRevGain$=dechex$(cd)+RevGain$ 'Build compressed gain hex string.next iend function

author: fenugrec
author_rank: Frequent Contributor
timestamp: January 22, 2020, 03:25:18 pm
content: Quote from: lmester on January 22, 2020, 02:28:29 pmSure, but as I mentioned we may be slightly wrong (or at least uncertain) about the decoding; it would be really good to do some kind of test as I described, before spending too much time on a possibly-wrong encoding implementation.

author: Miti
author_rank: Super Contributor
timestamp: January 22, 2020, 09:50:55 pm
content: I could help in the weekend. I have a reasonably accurate and stable 3V reference made with MAX6126A. If you can tell me exactly what offsets and gains you want to check, I’ll give you the readings.

author: lmester
author_rank: Regular Contributor
timestamp: January 23, 2020, 12:36:13 pm
content: Quote from: fenugrec on January 22, 2020, 03:25:18 pmThat sounds good. Apply a fixed input to the meter and then enter various gain values. Is this correct? The most stable reference for me would be a resistor. I assume it won't matter which function or range is used. You only want the meter response to changes in the gain value.

author: fenugrec
author_rank: Frequent Contributor
timestamp: January 23, 2020, 02:05:55 pm
content: Quote from: lmester on January 23, 2020, 12:36:13 pmCorrect. And to make the math easier, set the Offset for that range to 0 too. Your resistor can be fine as long as you can ensure a tight connection for the duration of the tests; in 5-digit mode the last digit(s) should be pretty stable and repeatable. If not, @Miti can probably help (again !)Gain constants: I think these should cover all edge cases:Code:0000000700008000090000a0000f0090700777778888899999

author: Miti
author_rank: Super Contributor
timestamp: January 23, 2020, 10:53:37 pm
content: And how do I send these raw gains? I would have to read the calibration constants, modify the gain for the 3V range, calculate the checksum, upload the new constants?

author: lmester
author_rank: Regular Contributor
timestamp: January 24, 2020, 12:15:48 am
content: Quote from: Miti on January 23, 2020, 10:53:37 pmThat's what I'm testing now. I modified my cal edit program to accept a raw gain value. I enter 0 for the offset and 5 hex digits for the gain. The program calculates the checksum and sends the new cal entry to the meter. I then log the new reading from the meter.If you're interested I can put the modified program up on my web site.I may need to hold off on this and just let the meter run overnight. It's been on for several hours. The reading started at .68324 K Ohms it's slooowly decreased to .68311. I'm assuming that the meter and the resistor that I'm measuring have not yet reached a stable temperature.Just looked over at the meter reading. It's been stable during the time I was typing this. I'll try to get some more data.

author: Miti
author_rank: Super Contributor
timestamp: January 24, 2020, 12:49:38 am
content: Quote from: lmester on January 24, 2020, 12:15:48 amSure I'm interested. Even if you do this experiment, I still intend to do it in the weekend.

author: lmester
author_rank: Regular Contributor
timestamp: January 24, 2020, 01:26:22 am
content: Quote from: Miti on January 24, 2020, 12:49:38 amDownload the file HP3478AGainCheck.exe fromhttps://mesterhome.com/gpibsw/hp3478a/Software/Replace your existing Hp3478a.exeGo to edit configuration. Select the desired range. Enter 0 for the offset. Enter exactly 5 hex digits for the raw gain. Click update cal. Exit edit calibration data and click start measurement from the main window. The meter reading should change to reflect the new gain and offset settings.Warning! Range and error checking are disabled. Make sure to enter exactly 5 hex digits for the gain.Below is the data from three tests. The second test was the most stable. The starting and ending meter reading was the same. I'm measuring resistance. It'll be interesting to see if you get better stability when measuring voltage.Code:initial reading .683093K range default calibration: offset -1 gain 1.0036 (04C00)Start: and End: are the calibrated resistance readings from the beginning and end of each testStart: .68309RawG Meter reading00000 6806400700 6811200800 6800900900 6801600a00 6802200f00 6805690700 6334677777 7335688888 6201399999 62769End: .68307Start: .6830700000 6806200700 6811000800 6800800900 6801400a00 6802100f00 6805590700 6334577777 7335688888 6201299999 62769End: . 68307Start: .6830600000 6806100700 6810900800 6800600900 6801300a00 6802000f00 6805390700 6334377777 7335388888 6201099999 62766End: . 68304

author: fenugrec
author_rank: Frequent Contributor
timestamp: January 24, 2020, 01:57:08 am
content: Quote from: lmester on January 24, 2020, 01:26:22 amVery nice, thanks for those rigorous tests. Plugging the numbers :Code:gain constreading 'x'decode(x)Un-apply gain(= reading / decode(x))TEST SERIES 100000680641.00000068064.000700681121.00070068064.400800680090.99920068063.500900680160.99930068063.600a00680220.99940068062.800f00680560.99990068062.890700633460.93070068062.777777733561.07777768062.388888620130.91111268063.099999627690.92222368062.7TEST SERIES 200000680621.00000068062.000700681101.00070068062.400800680080.99920068062.400900680140.99930068061.600a00680210.99940068061.800f00680550.99990068061.890700633450.93070068061.777777733561.07777768062.388888620120.91111268061.999999627690.92222368062.7As you can see, the results fit nearly perfectly - as good as I could expect, down to the last digit, which definitely proves the quality of your experimental methodology.The code I used in that spreadsheet is unfortunately an awful BASIC macro,Code:gain = 1for cur=1 to 5temp = clng("&h" & mid(gainstring, cur, 1)) ### this converts a single digit from the "raw gain constant" text string to a numerical value.if (temp >= 8) thentemp = temp - 16endifrem digit 1 (cur = 1) is 1/100)gain = gain + (temp / (10^(cur + 1)))next curbut that code, to the best of my knowledge, is equivalent to my original C code and Steve's, assuming he checks for "digit >= 8" too.Now, for the reverse function, encode(gain), I'd have to think about this before I could say anything smart.Again, thanks for that data. Always nice to validate theory.

author: Miti
author_rank: Super Contributor
timestamp: January 25, 2020, 12:38:33 am
content: Here are my readings. First I tried on the 3V range, it goes out of range with raw gain 77777. Then I tried on 30V range.Some misalignment in the data but you get the idea.Code:Initial reading3.00048V3V DC Range30V DC RangeGain reportedCorrect gainInitial offset-2Initial gain1.027762000002.919432.91981.000001.000002.919432.9198007002.921482.92191.00071.00072.9194363952.919856101008002.91712.91751.00080.99922.9194355482.919835869009002.917392.91780.99930.99932.9194336042.91984389100a002.917682.91810.99940.99942.9194316592.91985191100f002.919142.91950.99990.99992.9194319432.919791979907002.717122.71750.93070.93072.9194369832.91984527877777Over3.14691.0777771.0777770.000002.919806231888882.659932.66031.0888880.9111122.9194325182.919838615999992.692372.69270.9222230.9222232.9194348872.919792718

author: lmester
author_rank: Regular Contributor
timestamp: January 25, 2020, 05:20:38 am
content: Miti,The gain unpack is also working with your data. Your calculated gain values are very close to the 2.91943 (gain = 1) value.Code:GainC is the compressed gain value used for the testMeterDisp is the meter reading for the current GainCGainNum is the uncompressed gain valueCalc-Gain is MeterDisp/GainNum. Should be 2.91943GainCMeterDispGainNumCalc-Gain000002.919431.0000002.91943007002.921481.0007002.919436008002.91710.9992002.919435009002.917390.9993002.91943300a002.917680.9994002.91943100f002.919140.9999002.919431907002.717120.9307002.91943677777OverRng1.077777?888882.659930.9111122.919432999992.692370.9222232.919434Thanks to steve1515 and fenugrec I'm getting a better understanding of what's going on here.That's the problem with using code that I don't fully understand. Debugging can be really hard!My gain unpack code is currently using "digit>8" not "digit>=8". I assume that I should switch this to "digit>=8"? With my meter cal data there are no compressed cal digits equal to 8. The change makes no difference using my data.Also, I'd still like to know what range check to use for the gain. What limits should I set for user entered gain values?

author: fenugrec
author_rank: Frequent Contributor
timestamp: January 25, 2020, 08:08:51 pm
content: Quote from: lmester on January 25, 2020, 05:20:38 amyes, otherwise the raw constant "88888" wouldn't decode/unpack properly. As you saw, it corresponds to a gain of 0.911112 which is validated by many tests now.Maybe it would help to think about how the gain is applied by the stock firmware: it doesn't convert the constant to a fixed-point decimal number like what we're doing. That would be incredibly wasteful on that mcs-48 architecture with no hardware multiply. Here's roughly what it does, starting with a raw reading 'R' , with for example a gain constant K=90700. I'll call each digit Kn such that K1 = 9, K3 = 7, ...Code:C = R; //C will be the "almost calibrated" reading, just before the offset is applied.K1 = 9;// At the "1" digit, we're working at the 1/100 decimal position, so R is "decimal-shifted" 2 digits right.// Since K1 >= 8, we need to subtract (16-9)=7 times the shifted raw reading.C = C - ((16-9) * R/100);K2 = 0;//do nothingK3 = 7:// digit 3 : means "add 7 times", but now R is shifted 4 positionsC = C + (7 * R/10000);//and the rest of the digits are 0, so do nothing.//The equivalent operation is C = (1 * R) - (7 * 0.01 * R) + (7 * 0.00001 * R)//can also be written as C = R * (1 - 0.07 + 0.00007) or//of course, C = R * 0.9307The reverse process is sortof like a long division I guess ? I think it goes something like this. Assume all offsets are 0 for simplicity. The meter has a raw ADC reading 'R', and it knows the expected calibrated value 'C'.calculate error 'e = c - r' . Can be negative of courseshift raw value right, i.e. divide by 10. First iteration needs to start at a 1/100 division. let's call it 'sr = r * (1/100)'how many times does 'sr' fit in 'e' ?if it fits 0 to 7 times, then that encodes directly to digit 1.if it fits -1 to -8 times, then "encode" that digit as (16 - <value>), so 0x0F for -1 to 0x08 for -8.if it fits 8 or 9 times, problem : those digits indicated negative values, so we need to cheat:carry 10 to the digit to the left (by incrementing by 1 - careful if the digit was already 7, you'll need to do the same manoeuvre recursively), and set the current digit to (value - 10) i.e. -2 or -1.In other words, use the fact that 8 * sr = (10 * sr) + (-2 * sr)if it fits -9 times, same idea : borrow 10 from digit on the left, adjust, and continue.calculate new 'e' value for next loop, i.e. remainder. Right shift sr again and continueI think that should work, conceptually at least. Interesting consequence of the +7/-8 limit on digits : some gain values can be encoded in more than one way, for example 0001C and 00006 both correspond to a gain of 1.000006 .QuoteThat would be the two extremes we've tested,Code:77777 1.07777788888 0.911112

author: lmester
author_rank: Regular Contributor
timestamp: January 26, 2020, 02:55:02 am
content: Quote from: fenugrec on January 25, 2020, 08:08:51 pmThank you for the info.I'm sorry, it seems that I still don't understand the procedure. I've ben trying to calculate the packed gain for .911112 packed =0x88888. I'm not getting correct results.I'm assuming that e is the gain value? e=.911112Could you please go through the procedure using .911112? This would give me a better understanding of the process.

author: steve1515
author_rank: Regular Contributor
timestamp: January 26, 2020, 10:03:38 pm
content: I've updated my release to correct for the decode error. If anyone wants to check it out and verify it would be appreciated.https://github.com/steve1515/hp3478a-calibration/releaseshttps://github.com/steve1515/hp3478a-calibrationI've also been thinking about how to convert from floating point back to a raw gain, and I'm not sure there is a good way. I see what fenugrec is saying... The meter just keeps the raw nibbles and uses them as is. No floating point calculations are done in the meter. Maybe it would be better to have the interface allow the user to adjust the raw gain values as 5 sliders or 5 numeric up-down boxes where the floating point value is displayed for reference as the value is changed.

author: fenugrec
author_rank: Frequent Contributor
timestamp: January 27, 2020, 12:12:15 am
content: Quote from: steve1515 on January 26, 2020, 10:03:38 pmLet me try again. Say the gain constant K is "0001C". The digits are :Code:k1 = 0k2 = 0k3 = 0k4 = 1k5 = 'C' = -4As we know, 0-7 mean 0-7, but 8 to F are negatives, so 0x0C corresponds to -4.What is the meter calculating ? please read through this. scroll !Code:R = raw ADC reading,delta = correction to applyC = corrected value :C = R + deltadelta = R * ( (K1 * 0.01) + (K2 * 0.001) + (K3 * 0.0001) .... + (K5 * 0.000 001))######all good ? in this case K1 to K3 are 0, so we can rewrite asdelta = R * ((1 * 0.00001) + (-4 * 0.000 001))and then of course,delta = R * (0.000006)######easy enough, I hope. This last value, 0.000006, I'll call it "k_factor" to distinguish it from the gain. So,delta = R * k_factorRemember from the beginning,C = R + deltaC = R + R*k_factorC = R * (1 + k_factor)but we like to think about gain. What's gain ?C = R * gainso,gain = 1 + k_factortherefore "gain" in our example is 1.000006.############what's the opposite process ? Let's say for gain=1.049000 ? We want to determine the digits K1 to K5, such thatk_factor = (K1 * 0.01) + (K2 * 0.001) + (K3 * 0.0001) + (K4 * 0.00001) + (K5 * 0.000 001)1) finding k_factor : super easy. Of course this can give a negative number, since "gain" can be <1.k_factor = gain - 1 = 0.0490002) how do you "solve" the equation to find K1 to K5 ?2A) determine the desired k_factor = gain - 1 = 0.0490002B) for digit K1, which corresponds to the position "0.04", can we solve (0.04 = K1 * 0.01) ? Of course. K1 = 4.2C) for digit K2, corresponding to the position "0.009". Can we solve (0.009) = (K2 * 0.001) ?yes, but we have a problem : we would like K2 = 9, but we can only have K values between -8 and +7.What can we do ?2D) well, 9 = (10 - 1). Serious math. what does that mean ?k_factor = (K1 * 0.01) + (K2 * 0.001) + ...k_factor = (4 * 0.01) + ((10 * 0.001) + (-1 * 0.001)) + ...k_factor = (4 * 0.01) + (0.01 + (-1 * 0.001)) + ...k_factor = (5 * 0.01) + (-1 * 0.001) + ...see what happened ? I incremented K1, and set K2 = -1. All's good, we've made the digits fall in the valid range -8.... +7the digits are nowK1 = 5K2 = -12A3) : next digits are 0, thankfully. But it would be the same process.##### note: if a carry/borrow operation causes a digit to fall outside the valid range, then another carry/borrow would have to be repeated with the next digit to the left.2A5) we end up with a gain constant "5F000".

author: fenugrec
author_rank: Frequent Contributor
timestamp: March 14, 2020, 03:05:04 pm
content: I forgot to push to GH last time I worked on this. I added an "encode_gain" function and selftest (verifies that encode(gain) == expected_gain).The encode function isn't accessible from the CLI though; ran out of time to add that. Should be easy enough : sscanf(%d, &gain), bounds check, encode(gain).https://github.com/fenugrec/hp3478a_utils/commit/04584cd4eb7f9f741913e01591b73cf6db307348

author: Miti
author_rank: Super Contributor
timestamp: March 14, 2020, 05:45:18 pm
content: Kirill added Prologix support to his adapter and it works with Lmester's program.https://www.eevblog.com/forum/projects/project-extending-hp3478a-functionality/new/#newA big thanks to both, Kirill and Lmester!

author: lmester
author_rank: Regular Contributor
timestamp: March 21, 2020, 12:27:33 am
content: fenugrec,I think I have the gain encode function working properly. I still might have a problem.You'd mentioned that a gain value of 0001C is equivalent to 00006 and both correspond to a gain of 1.000006. I think I see these differences in my gain encoding. It looks like my implementation of your algorithm prefers "06" encoding instead of "1C" encoding.I've looked at several different instrument cal backup data files. It looks like the instrument always encodes gain as "1C" instead of "06".I've done some testing. The instrument does seem to handle the compressed gain in either format. My testing shows that both encoded gain values give the same instrument reading.I'm just not comfortable about writing different compressed gain data into the instrument for the same gain setting.Below are some tests.Inst: The value read from the cal RAM.Re-enc: The re-encoded value written back into the cal RAM.Gain: The same gain is reported for both compressed gain values.Inst. Re-enc. Gain.04C00 03600 1.003622C01 21601 1.0216011CFE3 06FE3 1.005883It'd be interesting to process some of the above gains with your code.Do you generate 04C00 or 03600 for a gain of 1.0036?Finally, I did some reality checks for gain updates entered using my software. The offset is set to 0. Various gain multipliers were applied and compared with the instrument reading.This looks very good.Readings with offset set to 0. and various gain settings.Calc gain = .68085 * Inst. gainInst. gain Inst. reading Calc. gain1.000000 .68085 0.680851.010000 .68766 0.68765851.077777 .73380 0.73380447045.911112 .62033 0.6203306052.990000 .67404 0.6740415

author: fenugrec
author_rank: Frequent Contributor
timestamp: March 21, 2020, 01:20:36 pm
content: Hi,Quote from: lmester on March 21, 2020, 12:27:33 amExcellent, glad to hear.QuoteFair point. The only theory I have is that the original algo tries to clamp each digit value to the range [-4...+5] i.e. allowing only C,D,E,F,0,1,...,5 . I checked a few cals (non exhaustive) and indeed the digits 6,7,8,9,A,B seem to be always absent. One reason to do this might be to limit rounding error propagation by keeping multiplications small (<= 5) ?You're welcome to check against the annotated disassembly listing I have in my repo, but I find that reading hand-optimized BCD code is super tedious. Or you could emulate that portion of the code under MAME, but tracking 6-digit packed-BCD operations is also headache-inducing...

author: lmester
author_rank: Regular Contributor
timestamp: March 22, 2020, 02:01:53 am
content: Quote from: fenugrec on March 21, 2020, 01:20:36 pmI have six cal files that i've been using to test my program. Two from my instruments and the rest from posts on EEVBLOG. All are missing 6,7,8,9,A,B in the gain digits. It does look like these digits are not used.QuoteI must give you a big thank you for your work disassembling the code.Many years ago I got stuck with a project to recover 6502 code from a disassembly listing. The programmer got into an argument with the company and took the source code when he left. All that I had was an EPROM with the object code. That was a really nasty job.Working with disassembled code and no comments is certainly headache-inducing!!For now I'm just going to use the existing gain compress code. The instrument does seem to handle the different encoding. Also, I expect that the gain adjust feature won't be used very often.If I have any problem reports I may then adjust the algorithm to avoid the unused digits.

author: Mp3
author_rank: Frequent Contributor
timestamp: April 11, 2020, 10:48:38 pm
content: Just wanted to thank everyone involved in this effort, I am about to build one of the atmega328 adapters to back up my own calibration data, and i will share it here.I have one unit that hasn't been calibrated since 2004 and I will soon be buying a friend's 3478A which was calibrated only six months ago. I'll be sure to share data backed up from both units.Has anyone tested writing the backed up data to a 3478A after a battery swap? I'm wondering if this utility replaces the need to provide auxiliary power to the SRAM while replacing the internal battery.

author: Miti
author_rank: Super Contributor
timestamp: April 12, 2020, 11:50:16 am
content: Yes, indeed, you don’t need to worry about hot swapping the battery anymore. And you also don’t need to design your own adapter. It’s all done and tested.Adapter:https://www.eevblog.com/forum/projects/ar488-arduino-based-gpib-adapter/Adapter with bonuses :https://www.eevblog.com/forum/projects/project-extending-hp3478a-functionality/Free software :https://www.eevblog.com/forum/testgear/free-hp3478a-multimeter-control-program/You can also use the SW to “tune” the calibration if you need and you have precision reference gear.Bonus - backlight :https://www.eevblog.com/forum/testgear/hp3478a-backlight-my-version/msg1506655/#msg1506655

author: cbueche
author_rank: Newbie
timestamp: August 12, 2020, 08:14:17 am
content: Hello all,a quick thank you to all who contributed to decoding the intricacies of the HP 3478a. For the people coming late to the party, here is a full log of my actions. It would be cool to check the data I got from my procedure - I know your values would diverge but you do have a sense of what they should look like.get gpib to work in Linux :https://linux-gpib.sourceforge.io/(somewhat outdated but worked for me on Kubuntu 18.04)create a virtual env for Python scriptdump the data using below's Python script : python ./getcal.py > hp3478_cal_dump.bincompile hp3478util fromhttps://github.com/fenugrec/hp3478a_utils(see issue 1 if you can't create an executable)hp3478util -a hp3478_cal_dump.bin -dvirtualenvCode:python3.8 -m venv venvsource venv/bin/activatepip install --upgrade pippip install pyusbpip install pyvisapip install pyvisa-pypip install gpib-ctypesgetcal.pyYou need to modify the hardcoded address (16 below).Code:#!/bin/env python3import sysimport pyvisarm = pyvisa.ResourceManager()dvm = rm.open_resource('GPIB::16::INSTR')vals_per_line = 16for addr in range(256):dvm.write_raw(bytes([ord('W'), addr]))val = dvm.read()sys.stdout.write(val)if ((addr + 1) % vals_per_line == 0):sys.stdout.write('\n')sys.stdout.write('\n')dvm.close()rm.close()dump of my data from python script@@@@@FGAM@NOLG@@@@@GAMMONL@@@@@@AAMMMNLHIIIIIDALDBBKIIIIIIIALDOCJF@@@@@@@@@@@@@IIH@CHAAABCMBIIIHHH@EALAKIIIIIHH@EMEDK@IIIIII@EMCMJGIIIIIH@EOAOJFIIIIII@EOB@KCIIIIIH@ENCAKCIIIIIHALOCLIOIIIHDEBMLAAKFIIIIHCBLDBCKI@@@@@@@@@@@@@IIGICBB@C@BMA@@@@@@@@@@@@@@@@@@@@@output of hp3478util -a hp3478_cal_dump.bin -t************ hp3478util, (c) 2018-2020 fenugrec ************entry 0x00: OK (30 mV DC)entry 0x01: OK (300 mV DC)entry 0x02: OK (3 V DC)entry 0x03: OK (30 V DC)entry 0x04: OK (300 V DC)entry 0x05 ((Not used)): bad cks (0x00) (unused entry)entry 0x06: OK (ACV)entry 0x07: OK (30 Ohm 2W/4W)entry 0x08: OK (300 Ohm 2W/4W)entry 0x09: OK (3 KOhm 2W/4W)entry 0x0A: OK (30 KOhm 2W/4W)entry 0x0B: OK (300 KOhm 2W/4W)entry 0x0C: OK (3 MOhm 2W/4W)entry 0x0D: OK (30 MOhm 2W/4W)entry 0x0E: OK (300 mA DC)entry 0x0F: OK (3A DC)entry 0x10 ((Not used)): bad cks (0x00) (unused entry)entry 0x11: OK (300 mA/3A AC)entry 0x12 ((Not used)): bad cks (0x00) (unused entry)output of hp3478util -a hp3478_cal_dump.bin -d************ hp3478util, (c) 2018-2020 fenugrec ************entry # offset (rawgain) gain range00 000067 1D0EF 1.006979 30 mV DC01 00A000 71DDF 1.070669 300 mV DC02 000000 A11DD 0.941067 3 V DC03 C89999 941CA 0.934054 30 V DC04 2B9999 9991C 0.922306 300 V DC05 3AA600 00000 1.000000 (Not used)06 00009A 98038 0.922022 ACV07 123D29 998A8 0.922132 30 Ohm 2W/4W08 51C1B9 99998 0.922222 300 Ohm 2W/4W09 A5D54B 09999 0.992223 3 KOhm 2W/4W0A 05D3AD A7999 0.946223 30 KOhm 2W/4W0B 805F1F A6A99 0.945323 300 KOhm 2W/4W0C 9905F2 0B399 0.995223 3 MOhm 2W/4W0D 99805E 31B39 1.030523 30 MOhm 2W/4W0E 998A1C F3C9F 0.992529 300 mA DC0F 98452D CA11B 0.954105 3A DC10 999832 C423B 0.964225 (Not used)11 000000 00000 1.000000 300 mA/3A AC12 99A793 22030 1.022030 (Not used)

author: pqass
author_rank: Super Contributor
timestamp: August 21, 2020, 04:54:49 pm
content: I came here looking for the formula for processing the raw gain value, however, I've discovered a problem with thehp3478util -a hp3478_cal_dump.bin -doutput as produced with cbueche's calibration data in the previous post.Specifically, the -d switch forgets to remove the end-of-line line-feed character (0x0A) before processing the line. If it were the same for the -t switch, then the program wouldn't produce "OK" crc's.If I run the linux hex-dump commandcat cbueche_lf.cal | od -A x -t x1z -w13 --skip=1on a cal file where there is a trailing line-feed every 16 bytes, then it will produce the following output which is consistent with the offset and raw gain columns shown in cbueche's post:(After the ASCII column, I've included processed offset and gain which should just be the lower nibble of each byte except the last two bytes.)Code:000001 40 40 40 40 46 47 41 4d 40 4e 4f 4c 47 >@@@@FGAM@NOLG<00: offset=000067 raw_gain=1d0ef00000e 40 40 0a 40 40 40 47 41 4d 4d 4f 4e 4c >@@.@@@GAMMONL<01: offset=00a000 raw_gain=71ddf00001b 40 40 40 40 40 40 0a 41 41 4d 4d 4d 4e >@@@@@@.AAMMMN<02: offset=000000 raw_gain=a11dd000028 4c 48 49 49 49 49 49 44 41 4c 0a 44 42 >LHIIIIIDAL.DB<03: offset=c89999 raw_gain=941ca000035 42 4b 49 49 49 49 49 49 49 41 4c 44 4f >BKIIIIIIIALDO<04: offset=2b9999 raw_gain=9991c000042 43 0a 4a 46 40 40 40 40 40 40 40 40 40 >C.JF@@@@@@@@@<05: offset=3aa600 raw_gain=0000000004f 40 40 40 40 49 0a 49 48 40 43 48 41 41 >@@@@I.IH@CHAA<06: offset=00009a raw_gain=9803800005c 41 42 43 4d 42 49 49 49 48 0a 48 48 40 >ABCMBIIIH.HH@<07: offset=123d29 raw_gain=998a8000069 45 41 4c 41 4b 49 49 49 49 49 48 48 40 >EALAKIIIIIHH@<08: offset=51c1b9 raw_gain=99998000076 0a 45 4d 45 44 4b 40 49 49 49 49 49 49 >.EMEDK@IIIIII<09: offset=a5d54b raw_gain=09999000083 40 45 4d 43 0a 4d 4a 47 49 49 49 49 49 >@EMC.MJGIIIII<10: offset=05d3ad raw_gain=a7999000090 48 40 45 4f 41 4f 4a 46 0a 49 49 49 49 >H@EOAOJF.IIII<11: offset=805f1f raw_gain=a6a9900009d 49 49 40 45 4f 42 40 4b 43 49 49 49 0a >II@EOB@KCIII.<12: offset=9905f2 raw_gain=0b3990000aa 49 49 48 40 45 4e 43 41 4b 43 49 49 49 >IIH@ENCAKCIII<13: offset=99805e raw_gain=31b390000b7 49 49 48 0a 41 4c 4f 43 4c 49 4f 49 49 >IIH.ALOCLIOII<14: offset=998a1c raw_gain=f3c9f0000c4 49 48 44 45 42 4d 4c 0a 41 41 4b 46 49 >IHDEBML.AAKFI<15: offset=98452d raw_gain=ca11b0000d1 49 49 49 48 43 42 4c 44 42 43 4b 0a 49 >IIIHCBLDBCK.I<16: offset=999832 raw_gain=c423b0000de 40 40 40 40 40 40 40 40 40 40 40 40 40 >@@@@@@@@@@@@@<17: offset=000000 raw_gain=000000000eb 49 49 0a 47 49 43 42 42 40 43 40 42 4d >II.GICBB@C@BM<18: offset=99a793 raw_gain=220300000f8 41 40 40 40 40 40 0a 40 40 40 40 40 40 >A@@@@@.@@@@@@<19: offset=100000 raw_gain=a0000000105 40 40 40 40 40 40 40 40 40 40 0a >@@@@@@@@@@.<20: offset=000000 raw_gain=0000aI believe the correct output should be (without any added line-feed characters):(Note that my gain column may be wrong although I've taken it from hp3478util.c getgain(). Please confirm otherwise. "crc=ff" means valid crc.)Code:000001 40 40 40 40 46 47 41 4d 40 4e 4f 4c 47 >@@@@FGAM@NOLG<00: offset=000067 raw_gain=1d0ef gain=1.006979 crc=ff 30 mV DC00000e 40 40 40 40 40 47 41 4d 4d 4f 4e 4c 40 >@@@@@GAMMONL@<01: offset=000007 raw_gain=1ddfe gain=1.006688 crc=ff 300 mV DC00001b 40 40 40 40 40 41 41 4d 4d 4d 4e 4c 48 >@@@@@AAMMMNLH<02: offset=000001 raw_gain=1ddde gain=1.006668 crc=ff 3 V DC000028 49 49 49 49 49 44 41 4c 44 42 42 4b 49 >IIIIIDALDBBKI<03: offset=999994 raw_gain=1c422 gain=1.006422 crc=ff 30 V DC000035 49 49 49 49 49 49 41 4c 44 4f 43 4a 46 >IIIIIIALDOCJF<04: offset=999999 raw_gain=1c4f3 gain=1.006393 crc=ff 300 V DC000042 40 40 40 40 40 40 40 40 40 40 40 40 40 >@@@@@@@@@@@@@<05: offset=000000 raw_gain=00000 gain=1.000000 crc=00 <not used>00004f 49 49 48 40 43 48 41 41 41 42 43 4d 42 >IIH@CHAAABCMB<06: offset=998038 raw_gain=11123 gain=1.011123 crc=ff AC V00005c 49 49 49 48 48 48 40 45 41 4c 41 4b 49 >IIIHHH@EALAKI<07: offset=999888 raw_gain=051c1 gain=1.005061 crc=ff 30 Ohm 2W/4W000069 49 49 49 49 48 48 40 45 4d 45 44 4b 40 >IIIIHH@EMEDK@<08: offset=999988 raw_gain=05d54 gain=1.004754 crc=ff 300 Ohm 2W/4W000076 49 49 49 49 49 49 40 45 4d 43 4d 4a 47 >IIIIII@EMCMJG<09: offset=999999 raw_gain=05d3d gain=1.004727 crc=ff 3 kOhm 2W/4W000083 49 49 49 49 49 48 40 45 4f 41 4f 4a 46 >IIIIIH@EOAOJF<10: offset=999998 raw_gain=05f1f gain=1.004909 crc=ff 30 kOhm 2W/4W000090 49 49 49 49 49 49 40 45 4f 42 40 4b 43 >IIIIII@EOB@KC<11: offset=999999 raw_gain=05f20 gain=1.004920 crc=ff 300 kOhm 2W/4W00009d 49 49 49 49 49 48 40 45 4e 43 41 4b 43 >IIIIIH@ENCAKC<12: offset=999998 raw_gain=05e31 gain=1.004831 crc=ff 3 MOhm 2W/4W0000aa 49 49 49 49 49 48 41 4c 4f 43 4c 49 4f >IIIIIHALOCLIO<13: offset=999998 raw_gain=1cf3c gain=1.005926 crc=ff 30 MOhm 2W/4W0000b7 49 49 49 48 44 45 42 4d 4c 41 41 4b 46 >IIIHDEBMLAAKF<14: offset=999845 raw_gain=2dc11 gain=1.016611 crc=ff 300 mA DC0000c4 49 49 49 49 48 43 42 4c 44 42 43 4b 49 >IIIIHCBLDBCKI<15: offset=999983 raw_gain=2c423 gain=1.016423 crc=ff 3A DC0000d1 40 40 40 40 40 40 40 40 40 40 40 40 40 >@@@@@@@@@@@@@<16: offset=000000 raw_gain=00000 gain=1.000000 crc=00 <not used>0000de 49 49 47 49 43 42 42 40 43 40 42 4d 41 >IIGICBB@C@BMA<17: offset=997932 raw_gain=20302 gain=1.020302 crc=ff 300 mA/3A AC0000eb 40 40 40 40 40 40 40 40 40 40 40 40 40 >@@@@@@@@@@@@@<18: offset=000000 raw_gain=00000 gain=1.000000 crc=00 <not used>0000f8 40 40 40 40 40 40 40 40 >@@@@@@@@<19: <padding>

author: cbueche
author_rank: Newbie
timestamp: August 29, 2020, 12:02:03 pm
content: Hi,after a laptop upgrade (now running Kubuntu 20.04) and recompiling all tools and GPIB setup is done, I have a new GPIB adapter as well (bought used on Ebay, BEIMING F82357), I read the calibration data again and got the same as the last time :Code:@@@@@FGAM@NOLG@@@@@GAMMONL@@@@@@AAMMMNLHIIIIIDALDBBKIIIIIIIALDOCJF@@@@@@@@@@@@@IIH@CHAAABCMBIIIHHH@EALAKIIIIIHH@EMEDK@IIIIII@EMCMJGIIIIIH@EOAOJFIIIIII@EOB@KCIIIIIH@ENCAKCIIIIIHALOCLIOIIIHDEBMLAAKFIIIIHCBLDBCKI@@@@@@@@@@@@@IIGICBB@C@BMA@@@@@@@@@@@@@@@@@@@@@Then running through hp3478util :Code:hp3478a_utils/hp3478util -a calibration_data/hp3478_cal_dump_1.bin -t************ hp3478util, (c) 2018-2020 fenugrec ************entry 0x00: OK (30 mV DC)entry 0x01: OK (300 mV DC)entry 0x02: OK (3 V DC)entry 0x03: OK (30 V DC)entry 0x04: OK (300 V DC)entry 0x05 ((Not used)): bad cks (0x00) (unused entry)entry 0x06: OK (ACV)entry 0x07: OK (30 Ohm 2W/4W)entry 0x08: OK (300 Ohm 2W/4W)entry 0x09: OK (3 KOhm 2W/4W)entry 0x0A: OK (30 KOhm 2W/4W)entry 0x0B: OK (300 KOhm 2W/4W)entry 0x0C: OK (3 MOhm 2W/4W)entry 0x0D: OK (30 MOhm 2W/4W)entry 0x0E: OK (300 mA DC)entry 0x0F: OK (3A DC)entry 0x10 ((Not used)): bad cks (0x00) (unused entry)entry 0x11: OK (300 mA/3A AC)entry 0x12 ((Not used)): bad cks (0x00) (unused entry)so far so good, now look at this dump :Code:hp3478a_utils/hp3478util -a calibration_data/hp3478_cal_dump_1.bin -d************ hp3478util, (c) 2018-2020 fenugrec ************entry # offset (rawgain) gain range00 000067 1D0EF 1.006979 30 mV DC01 000007 1DDFE 1.006688 300 mV DC02 000001 1DDDE 1.006668 3 V DC03 999994 1C422 1.006422 30 V DC04 999999 1C4F3 1.006393 300 V DC05 000000 00000 1.000000 (Not used)06 998038 11123 1.011123 ACV07 999888 051C1 1.005061 30 Ohm 2W/4W08 999988 05D54 1.004754 300 Ohm 2W/4W09 999999 05D3D 1.004727 3 KOhm 2W/4W0A 999998 05F1F 1.004909 30 KOhm 2W/4W0B 999999 05F20 1.004920 300 KOhm 2W/4W0C 999998 05E31 1.004831 3 MOhm 2W/4W0D 999998 1CF3C 1.005926 30 MOhm 2W/4W0E 999845 2DC11 1.016611 300 mA DC0F 999983 2C423 1.016423 3A DC10 000000 00000 1.000000 (Not used)11 997932 20302 1.020302 300 mA/3A AC12 000000 00000 1.000000 (Not used)I now get the gain values you have in your post. I'm not sure why my initial data extracted with "-d" was wrong. I wrote the getcal.py in steps and maybe I had some CR/LF in it while debugging, causing the errors.

author: pqass
author_rank: Super Contributor
timestamp: August 29, 2020, 04:06:02 pm
content: Quote from: cbueche on August 29, 2020, 12:02:03 pmGood to hear that it was just an input file mixup between the -t and -d outputs. The raw offset column is a binary coded decimal (see fenugrec earlier in this thread) and we shouldn't see any alpha characters in it.Thanks for confirming my gain output.For future readers, this is the Linux shell script that I use to dump raw calibration data (don't feed it new-lines):Code:#!/bin/shif [ -f "$1" ]; thencat "$1" | od -A x -t x1z -w13 --skip=1 | awk 'BEGIN{SEP="|";rectypestr="30 mV DC" SEP "300 mV DC" SEP "3 V DC" SEP "30 V DC" SEP "300 V DC" SEP "<not used>" SEP "AC V" SEP "30 Ohm 2W/4W" SEP "300 Ohm 2W/4W" SEP "3 kOhm 2W/4W" SEP "30 kOhm 2W/4W" SEP "300 kOhm 2W/4W" SEP "3 MOhm 2W/4W" SEP "30 MOhm 2W/4W" SEP "300 mA DC" SEP "3A DC" SEP "<not used>" SEP "300 mA/3A AC" SEP "<not used>" SEP "<padding>";rectype = "";split(rectypestr, rectype, SEP);}{if(NF==15) {crc=0; oset = ""; gain = ""; cgain = 1.0; multi = 0.01;for(i=1; i<NF; i++) {if(length($i)==2) {crc += strtonum("0x"(substr($i,2))""((i==13)?"0":""));if (i < 8) {/* first 6 bytes */oset = oset "" substr($i,2);} else if (i < 13) {/* next 5 bytes */gain = gain "" substr($i,2);digit = strtonum("0x"(substr($i,2)));cgain += (digit - ((digit > 7) ? 16 : 0)) * multi;multi = multi / 10;}}}coset = strtonum(oset); /* raw offset is in bcd; not hex */if (strtonum(oset)>499999) coset -= 1000000; /* if raw offset is greater than 499999 then its a negative number */printf "%s\t%.2d: raw_offset=%s raw_gain=%s offset=%+07d gain=%1.6f crc=%.2x %s\n", $0, (NR-1), oset, gain, coset, cgain, crc, rectype;} else if(NF>1) {printf "%s\t%.2d: %s\n", $0, (NR-1), rectype;}}'elseecho "$0 <cal file>"fiAnd this is the output using cbueche's calibration data as input (I now process the raw_offset to get +/- values):(Usetr -d '\n' <cbueche2_lf.cal >cbueche2.calto remove any new-line characters before feeding the script.)Code:$ ./verify.sh cbueche2.cal000001 40 40 40 40 46 47 41 4d 40 4e 4f 4c 47 >@@@@FGAM@NOLG<00: raw_offset=000067 raw_gain=1d0ef offset=+000055 gain=1.006979 crc=ff 30 mV DC00000e 40 40 40 40 40 47 41 4d 4d 4f 4e 4c 40 >@@@@@GAMMONL@<01: raw_offset=000007 raw_gain=1ddfe offset=+000007 gain=1.006688 crc=ff 300 mV DC00001b 40 40 40 40 40 41 41 4d 4d 4d 4e 4c 48 >@@@@@AAMMMNLH<02: raw_offset=000001 raw_gain=1ddde offset=+000001 gain=1.006668 crc=ff 3 V DC000028 49 49 49 49 49 44 41 4c 44 42 42 4b 49 >IIIIIDALDBBKI<03: raw_offset=999994 raw_gain=1c422 offset=-000006 gain=1.006422 crc=ff 30 V DC000035 49 49 49 49 49 49 41 4c 44 4f 43 4a 46 >IIIIIIALDOCJF<04: raw_offset=999999 raw_gain=1c4f3 offset=-000001 gain=1.006393 crc=ff 300 V DC000042 40 40 40 40 40 40 40 40 40 40 40 40 40 >@@@@@@@@@@@@@<05: raw_offset=000000 raw_gain=00000 offset=+000000 gain=1.000000 crc=00 <not used>00004f 49 49 48 40 43 48 41 41 41 42 43 4d 42 >IIH@CHAAABCMB<06: raw_offset=998038 raw_gain=11123 offset=-001962 gain=1.011123 crc=ff AC V00005c 49 49 49 48 48 48 40 45 41 4c 41 4b 49 >IIIHHH@EALAKI<07: raw_offset=999888 raw_gain=051c1 offset=-000112 gain=1.005061 crc=ff 30 Ohm 2W/4W000069 49 49 49 49 48 48 40 45 4d 45 44 4b 40 >IIIIHH@EMEDK@<08: raw_offset=999988 raw_gain=05d54 offset=-000012 gain=1.004754 crc=ff 300 Ohm 2W/4W000076 49 49 49 49 49 49 40 45 4d 43 4d 4a 47 >IIIIII@EMCMJG<09: raw_offset=999999 raw_gain=05d3d offset=-000001 gain=1.004727 crc=ff 3 kOhm 2W/4W000083 49 49 49 49 49 48 40 45 4f 41 4f 4a 46 >IIIIIH@EOAOJF<10: raw_offset=999998 raw_gain=05f1f offset=-000002 gain=1.004909 crc=ff 30 kOhm 2W/4W000090 49 49 49 49 49 49 40 45 4f 42 40 4b 43 >IIIIII@EOB@KC<11: raw_offset=999999 raw_gain=05f20 offset=-000001 gain=1.004920 crc=ff 300 kOhm 2W/4W00009d 49 49 49 49 49 48 40 45 4e 43 41 4b 43 >IIIIIH@ENCAKC<12: raw_offset=999998 raw_gain=05e31 offset=-000002 gain=1.004831 crc=ff 3 MOhm 2W/4W0000aa 49 49 49 49 49 48 41 4c 4f 43 4c 49 4f >IIIIIHALOCLIO<13: raw_offset=999998 raw_gain=1cf3c offset=-000002 gain=1.005926 crc=ff 30 MOhm 2W/4W0000b7 49 49 49 48 44 45 42 4d 4c 41 41 4b 46 >IIIHDEBMLAAKF<14: raw_offset=999845 raw_gain=2dc11 offset=-000155 gain=1.016611 crc=ff 300 mA DC0000c4 49 49 49 49 48 43 42 4c 44 42 43 4b 49 >IIIIHCBLDBCKI<15: raw_offset=999983 raw_gain=2c423 offset=-000017 gain=1.016423 crc=ff 3A DC0000d1 40 40 40 40 40 40 40 40 40 40 40 40 40 >@@@@@@@@@@@@@<16: raw_offset=000000 raw_gain=00000 offset=+000000 gain=1.000000 crc=00 <not used>0000de 49 49 47 49 43 42 42 40 43 40 42 4d 41 >IIGICBB@C@BMA<17: raw_offset=997932 raw_gain=20302 offset=-002068 gain=1.020302 crc=ff 300 mA/3A AC0000eb 40 40 40 40 40 40 40 40 40 40 40 40 40 >@@@@@@@@@@@@@<18: raw_offset=000000 raw_gain=00000 offset=+000000 gain=1.000000 crc=00 <not used>0000f8 40 40 40 40 40 40 40 40 >@@@@@@@@<19: <padding>

author: fenugrec
author_rank: Frequent Contributor
timestamp: August 29, 2020, 05:23:52 pm
content: Quote from: pqass on August 21, 2020, 04:54:49 pmHi, I got the notification on github concerning this issue, but I can't access my code and crap so I have nothing to suggest until I get back in ~2 weeks. Ping me again if you don't hear from me by then.But if it's just a processing issue it should be trivial to patch in the meantime (I think we got the math part mostly perfect ? except maybe clamping the gain digits to [-4..+5] , I forget the details)

author: pqass
author_rank: Super Contributor
timestamp: August 29, 2020, 05:54:17 pm
content: Quote from: fenugrec on August 29, 2020, 05:23:52 pmFalse alarm. You're good. User fed cal data with embedded new-lines ("\n") for -d.Although, it wouldn't hurt to put warnings if data in a particular field is suspect.eg. non-BCD digits appearing in raw offset, offset and gain fields without leading "4" hex nibble, should check crc behind the scene when executing -d to validate the line, etc.

author: cbueche
author_rank: Newbie
timestamp: August 30, 2020, 01:16:07 pm
content: pqpass with your script I now get the same results, so let's assume all is good and proceed to the new battery soldering :-)Fenugrec no worries and no stress, thanks for your great utility ! I haven't worked with C since 1991 but I think there is no bug, only a user's messing-up :-)

author: cbueche
author_rank: Newbie
timestamp: August 30, 2020, 03:27:37 pm
content: ok I messed upI followed the instructions : soldered a 4V battery-pack + serial-diode parallel to C510, measured the tension there (had ~ 3.5V), removed the old calibration-battery, still had about 3.5V over C510 so life was good... soldered new battery in place (my soldering iron is fully-isolated and the multimeter wasn't connected to anything), life was still good... removed the backup 3V source and power-cycled the HP3478A... life wasn't that good anymore... got the infamous "Uncalibrated" error at self-testReally not sure at what step I messed up, maybe a short when desoldering or measuring on C510. Anyway. Time to see how to recover my calibration data...I adapted my getval.py to be a "putval.py" and passed it my calibration dump, with of course the front-panel "cal" in write-mode.Code:#!/bin/env python3# usage : python ./putcal.py calibration_data/hp3478_cal_dump_1.binimport sysimport pyvisarm = pyvisa.ResourceManager()dvm = rm.open_resource('GPIB::16::INSTR')calfile = sys.argvwith open(calfile, 'r') as file:data = file.read().replace('\n', '')ldata = len(data)print("got {} bytes from {}".format(ldata, calfile))if ldata != 256:print("input file must be 256 bytes after filering newline chars. Now {} bytes, exit".format(ldata))sys.exit(1)for addr in range(256):dval = dataprint("writing position {} with value {}".format(addr, dval))dvm.write_raw(bytes([ord('X'), addr]))dvm.write_raw(dval)dvm.close()rm.close()After setting the front-panel "cal" to read-mode again and a power-cycle check, I get "self test ok" again I was able to read back the same calibration data using getval.py and life is good again, the saved data matches what I had at the begining of the whole trip and my HP3478A is good for the next 30 years. Time for pizza + beerThanks all for the help !Charles

author: pa3gyf
author_rank: Newbie
timestamp: June 03, 2021, 08:32:15 pm
content: Hi all,Sorry for the likely necrobump here, but I managed to back up the calibration data of my HP-3478A mostly using the info from this thread! So big thanks!And here's the cal data <tried but failed to get this into mono-spaced font>:[jan@rush ~]$ hexdump pa3gyf-hp3478a-01.cal0000000 4040 4040 4842 4140 4543 4440 484e 40400000010 4040 4742 4341 4f45 4d4e 4040 4040 40400000020 4142 4443 4045 404f 4949 4949 4549 43410000030 4544 4b45 494b 4949 4949 4149 4443 4c410000040 444b 4040 4040 4040 4040 4040 4f40 404f0000050 4040 4543 4143 4d41 4542 4e4d 4949 48490000060 4349 4c41 4c43 4a4c 4948 4949 4849 41490000070 424c 4d4f 4f49 4949 4949 4949 4c41 44410000080 4a4c 494b 4949 4949 4148 4f4c 4540 494a0000090 4949 4949 4949 4c41 4e40 4a42 494c 494900000a0 4949 4148 4f4c 4540 494a 4949 4949 484900000b0 4540 4145 4b44 404b 4040 4341 4240 454500000c0 454d 4d4d 4040 4040 4341 4542 4e42 4e4100000d0 4043 4040 4040 4040 4040 4040 4f4f 404000000e0 4340 4345 4342 444c 4d43 404c 4040 404000000f0 4040 4040 4040 4f4f 4040 4040 4040 4040000010073,Jan -pa3gyf

author: pqass
author_rank: Super Contributor
timestamp: June 25, 2021, 01:41:31 am
content: Quote from: pa3gyf on June 03, 2021, 08:32:15 pmSince you're into necro, I just want to add that I've verified each record of your cal data.I've reconstituted the raw cal data from your hexdump output by:1. removing the first 8 chars (address), then2. swaping each pair in the hex quad, then3. removing all spaces, then4. converting each hex pair to ascii to get:@@@@BH@ACE@DNH@@@@BGACEONM@@@@@@BACDE@O@IIIIIEACDEEKKIIIIIIACDALKD@@@@@@@@@@@OO@@@CECAAMBEMNIIIHICALCLLJHIIIIHIALBOMIOIIIIIIALADLJKIIIIIHALO@EJIIIIIIIAL@NBJLIIIIIHALO@EJIIIIIIH@EEADKK@@@AC@BEEMEMM@@@@ACBEBNANC@@@@@@@@@@@OO@@@CECBCLDCML@@@@@@@@@@@OO@@@@@@I then fed the raw cal string into my verify.sh script (see my post #123 on the previous page):000001 40 40 40 42 48 40 41 43 45 40 44 4e 48 >@@@BH@ACE@DNH< 00: raw_offset=000280 raw_gain=13504 offset=+000280 gain=1.013504 crc=ff 30 mV DC00000e 40 40 40 40 42 47 41 43 45 4f 4e 4d 40 >@@@@BGACEONM@< 01: raw_offset=000027 raw_gain=135fe offset=+000023 gain=1.013488 crc=ff 300 mV DC00001b 40 40 40 40 40 42 41 43 44 45 40 4f 40 >@@@@@BACDE@O@< 02: raw_offset=000002 raw_gain=13450 offset=+000002 gain=1.013450 crc=ff 3 V DC000028 49 49 49 49 49 45 41 43 44 45 45 4b 4b >IIIIIEACDEEKK< 03: raw_offset=999995 raw_gain=13455 offset=-000005 gain=1.013455 crc=ff 30 V DC000035 49 49 49 49 49 49 41 43 44 41 4c 4b 44 >IIIIIIACDALKD< 04: raw_offset=999999 raw_gain=1341c offset=-000001 gain=1.013406 crc=ff 300 V DC000042 40 40 40 40 40 40 40 40 40 40 40 4f 4f >@@@@@@@@@@@OO< 05: raw_offset=000000 raw_gain=00000 offset=+000000 gain=1.000000 crc=ff <not used>00004f 40 40 40 43 45 43 41 41 4d 42 45 4d 4e >@@@CECAAMBEMN< 06: raw_offset=000353 raw_gain=11d25 offset=+000235 gain=1.010725 crc=ff AC V00005c 49 49 49 48 49 43 41 4c 43 4c 4c 4a 48 >IIIHICALCLLJH< 07: raw_offset=999893 raw_gain=1c3cc offset=-000107 gain=1.006256 crc=ff 30 Ohm 2W/4W000069 49 49 49 49 48 49 41 4c 42 4f 4d 49 4f >IIIIHIALBOMIO< 08: raw_offset=999989 raw_gain=1c2fd offset=-000011 gain=1.006187 crc=ff 300 Ohm 2W/4W000076 49 49 49 49 49 49 41 4c 41 44 4c 4a 4b >IIIIIIALADLJK< 09: raw_offset=999999 raw_gain=1c14c offset=-000001 gain=1.006136 crc=ff 3 kOhm 2W/4W000083 49 49 49 49 49 48 41 4c 4f 40 45 4a 49 >IIIIIHALO@EJI< 10: raw_offset=999998 raw_gain=1cf05 offset=-000002 gain=1.005905 crc=ff 30 kOhm 2W/4W000090 49 49 49 49 49 49 41 4c 40 4e 42 4a 4c >IIIIIIAL@NBJL< 11: raw_offset=999999 raw_gain=1c0e2 offset=-000001 gain=1.005982 crc=ff 300 kOhm 2W/4W00009d 49 49 49 49 49 48 41 4c 4f 40 45 4a 49 >IIIIIHALO@EJI< 12: raw_offset=999998 raw_gain=1cf05 offset=-000002 gain=1.005905 crc=ff 3 MOhm 2W/4W0000aa 49 49 49 49 49 48 40 45 45 41 44 4b 4b >IIIIIH@EEADKK< 13: raw_offset=999998 raw_gain=05514 offset=-000002 gain=1.005514 crc=ff 30 MOhm 2W/4W0000b7 40 40 40 41 43 40 42 45 45 4d 45 4d 4d >@@@AC@BEEMEMM< 14: raw_offset=000130 raw_gain=255d5 offset=+000088 gain=1.025475 crc=ff 300 mA DC0000c4 40 40 40 40 41 43 42 45 42 4e 41 4e 43 >@@@@ACBEBNANC< 15: raw_offset=000013 raw_gain=252e1 offset=+000011 gain=1.025181 crc=ff 3A DC0000d1 40 40 40 40 40 40 40 40 40 40 40 4f 4f >@@@@@@@@@@@OO< 16: raw_offset=000000 raw_gain=00000 offset=+000000 gain=1.000000 crc=ff <not used>0000de 40 40 40 43 45 43 42 43 4c 44 43 4d 4c >@@@CECBCLDCML< 17: raw_offset=000353 raw_gain=23c43 offset=+000235 gain=1.022643 crc=ff 300 mA/3A AC0000eb 40 40 40 40 40 40 40 40 40 40 40 4f 4f >@@@@@@@@@@@OO< 18: raw_offset=000000 raw_gain=00000 offset=+000000 gain=1.000000 crc=ff <not used>0000f8 40 40 40 40 40 40 >@@@@@@< 19: <padding>CRC=ff means the record is verified. Yay!

author: bingo600
author_rank: Super Contributor
timestamp: February 25, 2023, 03:07:57 pm
content: Quote from: biot on April 09, 2017, 04:07:22 pmI needed to grab my HP 3478A calibration constants, as i soon have to change the battery.I have adapted biot's cal-3478a to python3, used on most newer linux'es.Script is attached as a zip file, so remember to make it executable after extracting it.I still don't know why only tar and not tar.gz files are allowed?The script makes use of linux-gpib, so make sure it works first.Edit: The zip contains the fixed version (see post below)/BingoReferences:Original cal-3478a (python2) here - Thnx biothttps://www.eevblog.com/forum/repair/hp-3478a-how-to-readwrite-cal-sram/msg1182436/#msg1182436Raspberry linux-gpip install guide (I used it on a Raspi3 running Bullseye) - Thnx MiDihttps://www.eevblog.com/forum/metrology/raspberry-pi23-logging-platform-for-voltnuts/msg2008349/#msg2008349Code:root@raspi3:~# sudo dmesg | grep -i -e gpib -e agilent[ 14.478470] usb 1-1.4: Manufacturer: Agilent Technologies, Inc.[ 14.648728] gpib_common: loading out-of-tree module taints kernel.[ 14.661207] Linux-GPIB 4.3.5 Driver[ 14.746457] agilent_82357a_gpib driver loading[ 14.748089] usbcore: registered new interface driver agilent_82357a_gpib[ 14.748122] gpib: registered agilent_82357a interface[ 15.860168] usb 1-1.4: bus 1 dev num 7 attached to gpib minor 0, agilent usb interface 0[ 15.871055] agilent_82357a_attach: attached[ 147.005668] gpib0: exiting autospoll thread[ 147.006044] agilent_82357a_detach: detached[ 147.006246] usb 1-1.4: bus 1 dev num 7 attached to gpib minor 0, agilent usb interface 0[ 147.017505] agilent_82357a_attach: attachedroot@raspi3:~#

author: bingo600
author_rank: Super Contributor
timestamp: February 25, 2023, 03:57:19 pm
content: Hmm ... That's a bit weird ...I took two dual sets of backup:One set with Win10 +https://mesterhome.com/gpibsw/One set with a Raspi3 (Bullseye) + linux-gpibhttps://www.eevblog.com/forum/repair/hp-3478a-how-to-readwrite-cal-sram/msg4722449/#msg4722449I did a compare , first "pairwise" - they matched ... Both pairsThen i compared a Win backup against a linux-gpib backup .... They only matched the first part of the CalRam ...I prob. did a 3478 poweroff/on between the backups.Is that CalRam used as "normal ram too?"Have attched the 4 images ....Edit:The first 128 bytes matches across platforms .. aka on all 4 files.The last 128 bytes matches if compared with the "other backup" taken on the same platform.But NOT if comparing a Win vs Lin backupHmmm ...- From first post in this threadCode:For those familiar with the 3478A, recall that the cal SRAM is 256 x 4 (NEC UDP5101L or equivalent).So what is returned on that "GPIB Read" ... a Nibble (All 256 counts) or a Byte (HP does some magic , and presents those nibbles as bytes)FSCK !!! -My first byte in the CalRam was 4f, this means that the guy calibrating my meter back in 15' had left Cal Write enabled ...It looked like it was "Horisontal" , but it missed a little twist ..../Bingo

author: pqass
author_rank: Super Contributor
timestamp: February 25, 2023, 05:33:47 pm
content: Quote from: bingo600 on February 25, 2023, 03:57:19 pmNot likely since the [ground-referenced] MCU is an Intel 8039 which has 128 bytes of RAM built-in and no ROM (needs external ROM).The only external RAM is a 256x4 which is just enough to hold 19 records (of 13 bytes each; with 3 records unused).QuoteI'm not sure what's going on with the RasPi GPIB Read but since the problem appears after byte 127, it could be sign related?Since the upper nibble doesn't exist on the bus, the MCU may just assign a fixed hex 4 to that so the byte is a valid ASCII (between '@' and 'O').Well the good news is that the cal data from your Win10+ GPIB pull looks to be good since the CRCs are valid.CRC=ff means the record is verified.When I pulled my 3478 cal, I made sure I had valid CRCs before messing with the hardware.Code:$ ./verify.sh bingo.cal000001 40 40 40 44 48 44 42 4f 4c 4c 44 4c 42 >@@@DHDBOLLDLB<00: raw_offset=000484 raw_gain=2fcc4 offset=+000484 gain=1.018564 crc=ff 30 mV DC00000e 40 40 40 40 44 45 42 4f 4e 45 4d 4c 45 >@@@@DEBONEMLE<01: raw_offset=000045 raw_gain=2fe5d offset=+000037 gain=1.018847 crc=ff 300 mV DC00001b 40 40 40 40 40 44 42 4e 43 45 45 4d 4e >@@@@@DBNCEEMN<02: raw_offset=000004 raw_gain=2e355 offset=+000004 gain=1.018355 crc=ff 3 V DC000028 49 49 49 49 49 46 42 4e 41 40 43 4b 48 >IIIIIFBNA@CKH<03: raw_offset=999996 raw_gain=2e103 offset=-000004 gain=1.018103 crc=ff 30 V DC000035 40 40 40 40 40 40 42 4d 45 44 44 4e 43 >@@@@@@BMEDDNC<04: raw_offset=000000 raw_gain=2d544 offset=+000000 gain=1.017544 crc=ff 300 V DC000042 40 40 40 40 40 40 40 40 40 40 40 40 40 >@@@@@@@@@@@@@<05: raw_offset=000000 raw_gain=00000 offset=+000000 gain=1.000000 crc=00 <not used>00004f 49 49 49 43 41 40 41 44 44 4d 4d 4b 4d >IIICA@ADDMMKM<06: raw_offset=999310 raw_gain=144dd offset=-000690 gain=1.014367 crc=ff AC V00005c 49 49 49 48 43 41 40 45 44 45 43 4c 47 >IIIHCA@EDECLG<07: raw_offset=999831 raw_gain=05453 offset=-000169 gain=1.005453 crc=ff 30 Ohm 2W/4W000069 49 49 49 49 48 42 41 4c 4e 40 4e 4a 48 >IIIIHBALN@NJH<08: raw_offset=999982 raw_gain=1ce0e offset=-000018 gain=1.005798 crc=ff 300 Ohm 2W/4W000076 49 49 49 49 49 49 40 45 42 41 40 4c 41 >IIIIII@EBA@LA<09: raw_offset=999999 raw_gain=05210 offset=-000001 gain=1.005210 crc=ff 3 kOhm 2W/4W000083 49 49 49 49 49 49 40 45 40 43 44 4b 4d >IIIIII@E@CDKM<10: raw_offset=999999 raw_gain=05034 offset=-000001 gain=1.005034 crc=ff 30 kOhm 2W/4W000090 49 49 49 49 49 48 40 45 4f 41 4c 4a 49 >IIIIIH@EOALJI<11: raw_offset=999998 raw_gain=05f1c offset=-000002 gain=1.004906 crc=ff 300 kOhm 2W/4W00009d 49 49 49 49 49 48 40 45 4f 45 45 4a 4c >IIIIIH@EOEEJL<12: raw_offset=999998 raw_gain=05f55 offset=-000002 gain=1.004955 crc=ff 3 MOhm 2W/4W0000aa 49 49 49 49 49 48 41 4c 44 41 4c 4a 4c >IIIIIHALDALJL<13: raw_offset=999998 raw_gain=1c41c offset=-000002 gain=1.006406 crc=ff 30 MOhm 2W/4W0000b7 40 40 40 41 44 47 43 4e 4d 42 40 4d 43 >@@@ADGCNMB@MC<14: raw_offset=000147 raw_gain=3ed20 offset=+000103 gain=1.027720 crc=ff 300 mA DC0000c4 40 40 40 40 41 45 43 4e 4e 4e 4c 4c 40 >@@@@AECNNNLL@<15: raw_offset=000015 raw_gain=3eeec offset=+000013 gain=1.027776 crc=ff 3A DC0000d1 40 40 40 40 40 40 40 40 40 40 40 40 40 >@@@@@@@@@@@@@<16: raw_offset=000000 raw_gain=00000 offset=+000000 gain=1.000000 crc=00 <not used>0000de 49 49 49 41 45 45 42 44 43 41 43 4c 4c >IIIAEEBDCACLL<17: raw_offset=999155 raw_gain=24313 offset=-000845 gain=1.024313 crc=ff 300 mA/3A AC0000eb 40 40 40 40 40 40 40 40 40 40 40 40 40 >@@@@@@@@@@@@@<18: raw_offset=000000 raw_gain=00000 offset=+000000 gain=1.000000 crc=00 <not used>0000f8 40 40 40 40 40 40 40 40 0a >@@@@@@@@.<19: <padding>See my verify.sh script on post #123 on the previous page.

author: fenugrec
author_rank: Frequent Contributor
timestamp: February 25, 2023, 06:55:42 pm
content: Quote from: bingo600 on February 25, 2023, 03:57:19 pmNo. IIRC only the first calram location is "weird"; toggled periodically by the mcu to determine whether it's write protected or not. The rest is cal records.QuoteThat is precisely what the firmware does :https://github.com/fenugrec/hp3478a_utils/blob/master/ROM_disasm/dc118.d48#L2805Code:anlp2,#0xf7; 14c3 - 9a f7.w; calRAM_CEmova,r6; 14c5 - fe~movr0,a; 14c6 - a8(movxa,@r0; 14c7 - 80.; read CAL!anla,#0xf; 14c8 - 53 0fS.adda,#0x40; 14ca - 03 40.@the last 3 lines: replace upper nibble with 0x40. This is why the '@' character appears so often in ascii dumps; 0 + 0x40 = '@'

author: bingo600
author_rank: Super Contributor
timestamp: February 25, 2023, 08:18:08 pm
content: I found the bugPython3 "in it's infnite visdom" is now applying locale/character encoding Ie UTF-8 to strings.This messes with string operations. And makes old Python2 string conversion tricks unusableI am NOT a python guru, so this is the way i had to change it, in order to operate on a "binary array" instead of the strings.Code:## Watch out !!!# Python3 is doing "locale/character set" conversion on strings# You will be BITTEN, if you use old Python2 strings## Force a binary array by creating w. bytearraybytesArr = bytearray(b'\x00\x00\x00')gpib.timeout(devhdl, gpib.T1s)for addr in range(256):bytesArr = ord('W')bytesArr = addrbytesArr = 10 # LF# The two below lines will NOT work due to the new locale conversion stuff.#cmd = "W" + chr(addr) + '\n'#gpib.write(devhdl, cmd)gpib.write(devhdl, bytes(bytesArr)) # Convert bytesArr back to bytes, before using itval = gpib.read(devhdl, 1)sys.stdout.buffer.write(val)Edit: I know i could just have changed the addr part of the byte array, but the Raspi even w Python will "run circles" around the HP3478A processor.Attached is a working Python3 - hp3478a cal readout program - It requires linux-gpib to be functional.And my readouts on Windows and RaspiNote:When i took the Windows CalRam backups, i had hp3478a Calibration enabledThis means the first byte contain 0x4f (cal enabled) , instead of 0x40 (cal disabled)When i took the linux / Raspi CalRam backup using the new python program , i had disabled hp3478a Calibration. Making the first byte 0x40.That is why Win and linux differs in the first byte./Bingo

author: bingo600
author_rank: Super Contributor
timestamp: February 25, 2023, 08:48:31 pm
content: Now i get this output from hp3478util.c (attached)https://github.com/fenugrec/hp3478a_utilsCode:* On lnux link with -lm : gcc -o hp3478util hp3478util.c -lm* And - #define WITH_GPIB0Code:Raspi$ ./hp3478util -d -b hp3478a-cal-raspi3-2022022501.cal************ hp3478util, (c) 2018-2020 fenugrec ************entry #offset(rawgain)gainrange000004842FCC41.01856430 mV DC010000452FE5D1.018847300 mV DC020000042E3551.0183553 V DC039999962E1031.01810330 V DC040000002D5441.017544300 V DC05000000000001.000000(Not used)06999310144DD1.014367ACV07999831054531.00545330 Ohm 2W/4W089999821CE0E1.005798300 Ohm 2W/4W09999999052101.0052103 KOhm 2W/4W0A999999050341.00503430 KOhm 2W/4W0B99999805F1C1.004906300 KOhm 2W/4W0C99999805F551.0049553 MOhm 2W/4W0D9999981C41C1.00640630 MOhm 2W/4W0E0001473ED201.027720300 mA DC0F0000153EEEC1.0277763A DC10000000000001.000000(Not used)11999155243131.024313300 mA/3A AC12000000000001.000000(Not used)Raspi$ ./hp3478util -t -b hp3478a-cal-raspi3-2022022501.cal************ hp3478util, (c) 2018-2020 fenugrec ************entry 0x00: OK (30 mV DC)entry 0x01: OK (300 mV DC)entry 0x02: OK (3 V DC)entry 0x03: OK (30 V DC)entry 0x04: OK (300 V DC)entry 0x05 ((Not used)): bad cks (0x00) (unused entry)entry 0x06: OK (ACV)entry 0x07: OK (30 Ohm 2W/4W)entry 0x08: OK (300 Ohm 2W/4W)entry 0x09: OK (3 KOhm 2W/4W)entry 0x0A: OK (30 KOhm 2W/4W)entry 0x0B: OK (300 KOhm 2W/4W)entry 0x0C: OK (3 MOhm 2W/4W)entry 0x0D: OK (30 MOhm 2W/4W)entry 0x0E: OK (300 mA DC)entry 0x0F: OK (3A DC)entry 0x10 ((Not used)): bad cks (0x00) (unused entry)entry 0x11: OK (300 mA/3A AC)entry 0x12 ((Not used)): bad cks (0x00) (unused entry)

author: djrm
author_rank: Contributor
timestamp: March 14, 2024, 05:41:37 pm
content: Hello everyone,I'm a new user of an HP3478A Multimeter, it seems to be working well though I'm keen to service it by changing caps and battery.I have built an AR488, its working with HP3478A.exe in both Windows and Linux under Wine, I also have 'HP 3478A.exe' working in Windows only.When I try to save the calibration using HP3478A.exe it always fails with a couple of checksum errors, the multimeter doesnt show and checksum errors in use. I think the transfer is getting corupted.I have copied the transfered data out of the log window and massaged it to be read with hp3478a_utils to try and understand what could be the problem, with a bit of tinkering I can get all lines to have good chacksums, see diffs below.Here is the dump before editing:Code:david@I7MINT:~/Github/hp3478a_utils$ ./hp3478util -a djrm-cal.txt -t************ hp3478util, (c) 2018-2020 fenugrec ************entry 0x00 (30 mV DC): bad cks (0xFE)entry 0x01: OK (300 mV DC)entry 0x02 (3 V DC): bad cks (0x0C)entry 0x03: OK (30 V DC)entry 0x04: OK (300 V DC)entry 0x05: OK ((Not used))entry 0x06: OK (ACV)entry 0x07: OK (30 Ohm 2W/4W)entry 0x08: OK (300 Ohm 2W/4W)entry 0x09: OK (3 KOhm 2W/4W)entry 0x0A: OK (30 KOhm 2W/4W)entry 0x0B: OK (300 KOhm 2W/4W)entry 0x0C: OK (3 MOhm 2W/4W)entry 0x0D: OK (30 MOhm 2W/4W)entry 0x0E: OK (300 mA DC)entry 0x0F: OK (3A DC)entry 0x10: OK ((Not used))entry 0x11: OK (300 mA/3A AC)entry 0x12: OK ((Not used))diff showing checksum correction, found by guesswork!Here is the test and dump after editing the two dodgy lines.Code:entry 0x00: OK (30 mV DC)entry 0x01: OK (300 mV DC)entry 0x02: OK (3 V DC)entry 0x03: OK (30 V DC)entry 0x04: OK (300 V DC)entry 0x05: OK ((Not used))entry 0x06: OK (ACV)entry 0x07: OK (30 Ohm 2W/4W)entry 0x08: OK (300 Ohm 2W/4W)entry 0x09: OK (3 KOhm 2W/4W)entry 0x0A: OK (30 KOhm 2W/4W)entry 0x0B: OK (300 KOhm 2W/4W)entry 0x0C: OK (3 MOhm 2W/4W)entry 0x0D: OK (30 MOhm 2W/4W)entry 0x0E: OK (300 mA DC)entry 0x0F: OK (3A DC)entry 0x10: OK ((Not used))entry 0x11: OK (300 mA/3A AC)entry 0x12: OK ((Not used))Code:david@I7MINT:~/Github/hp3478a_utils$ ./hp3478util -a djrm-cal2.txt -d************ hp3478util, (c) 2018-2020 fenugrec ************entry #offset(rawgain)gainrange0000029314CD51.01357530 mV DC0100002914C1C1.013606300 mV DC02000000133101.0133103 V DC0399999514F331.01393330 V DC0400000014C4E1.013638300 V DC05000000000001.000000(Not used)0699890815D351.014735ACV079996031CE3F1.00582930 Ohm 2W/4W089999581CE211.005821300 Ohm 2W/4W09999995055241.0055243 KOhm 2W/4W0A999995052201.00522030 KOhm 2W/4W0B999996051251.005125300 KOhm 2W/4W0C999996053C01.0052603 MOhm 2W/4W0D9999961CFF11.00589130 MOhm 2W/4W0E999974240521.024052300 mA DC0F999997240FF1.0239893A DC10000000000001.000000(Not used)1199890824FCE1.023858300 mA/3A AC12000000000001.000000(Not used)My question is what could be the problem?, is it something to do with the AR488 software? I have been looking for another utility to capture the calibration data but have not found anything yet.Any help resolving this will be greatly appreciated.Kind regards, David.

author: Kleinstein
author_rank: Super Contributor
timestamp: March 14, 2024, 05:54:13 pm
content: The AR488 is not fully at the GIPB standard when it comes to the drive strength and detection levels. So with some meters there is a chance to get borderline cases from the hardware side and thus possible bit errors. This is more like a hardware limitation as a softwas fault. In some cases the software side may get a little better result with added delays / reduced speed.I may need tinkering with pull-up resistors and speed settings, maybe the supply voltage.

author: djrm
author_rank: Contributor
timestamp: March 14, 2024, 06:01:19 pm
content: Quote from: Kleinstein on March 14, 2024, 05:54:13 pmHi & Thanks for answering,I have tried adding delays and reducing the baudrate to 9600 without success, it seems odd to me that the error is always the same whatever I try. i.e. checksum error on first and third cal lines. I tried sending 'W' 0x00 CRLF to see if I could get an individual byte back but never received anything at all.Kind regards, David.

author: Kleinstein
author_rank: Super Contributor
timestamp: March 14, 2024, 06:17:18 pm
content: Getting the error always at the same position is indeed a bit odd.Are other tranfers (e.g. repeated status / version reading) also getting occasional tranfer errors ?The baud rate should be the least problem. The RS232 end of the AR488 should normally work OK - though some of the USB to UART solution can be buggy too.At least for the receive side there should be some buffering and thus not direct link from baud rate to GPIB speed.The weak point are the levels at the GPIB bus - AFAIK the simpel AR488 solution uses the µC pins directly and no extra drivers. This solution is borderline with some instruments.It can be worth looking at the signal levels with a scope.

author: djrm
author_rank: Contributor
timestamp: March 14, 2024, 06:22:15 pm
content: Quote from: Kleinstein on March 14, 2024, 06:17:18 pmIn normal use I'm getting no errors, commands are returned without any visible errors.I'll check the signal lines with my 'scope - not sure what I'm looking for but I'll maybee see an odd looking signal line or something.D.

author: pqass
author_rank: Super Contributor
timestamp: March 14, 2024, 07:25:13 pm
content: Quote from: djrm on March 14, 2024, 06:01:19 pmFor a rough/baremetal read of the cal data...Connect your terminal emulator (GTKTerm, minicom, ...) to the AR488 com port (typically at 115200-8-N-1).Type: "++ver", enter, to confirm that your AR488 is responding.Type: "++addr N", enter, where N is the GPIB address of the 3478A.Type: "++read", enter, to confirm a response from the meter.Turn on log to file.To read a cal byte (in a fresh bash shell) type:"/usr/bin/echo -en "W\e\xHH\r++read\r" >>/dev/ttyUSB0"Turn off logging in the terminal program.The cal byte is the first character of every log file row; ignore remaining characters to end-of-line.If needed, to write a cal byte (after turning the "cal enable" screw on meter faceplate), type:"/usr/bin/echo -en "X\e\xHH\xVV\r++read\r" >>/dev/ttyUSB0"Meaning of echo switches ("man echo" for more detail):\e =ASCII escape char 1B hex (needed to tell AR488 that next byte is binary)\xHH=HHis the hex of the character representing the address of the cal byte\xVV=VVis the hex of the character representing the value of the cal byte\r =ASCII carriage return 0D hexttyUSB0 =com port where AR488 is connected (replace as appropriate for your setup).Creating a bash script to automate calling 256 echo lines above or scraping the first character from the log file is left as an exercise for the diligent student.

author: djrm
author_rank: Contributor
timestamp: March 14, 2024, 07:54:03 pm
content: Quote from: pqass on March 14, 2024, 07:25:13 pmThanks, I'd been missing the escape on the address byte, I'll try again.As for rewriting as a script, I'm not sure I'm up to that.Just had a quick look at some signals on the 'scope. Some appear to be three state, others bit and byte pulses.I'm not familiar with GPIB protocol, I wonder if pulseview knows about it ... it does :-)edit, more importantly I had not been issuing any ++read commands to see the returned values!, dohKind regards, David.

author: djrm
author_rank: Contributor
timestamp: March 14, 2024, 08:28:41 pm
content: Sending read cal commands by hand results in the same sequence as seen by HP3478A.exe program, I wonder if this is a true copy of what I have in the cal. I would expect the meter to show an error though.Code:@@@BICADLMELM : CkSum = (205 + 49) Checksum Fail.@@@@BIADLALMF : CkSum = (214 + 41) Checksum OK.M@@@@@ACCA@OG : CkSum = (247 + 21) Checksum Fail.Code:@+00.0007E-3@+00.0007E-3@+00.0005E-3@+00.0004E-3B+00.0004E-3I+00.0007E-3C+00.0007E-3A+00.0004E-3D+00.0004E-3L+00.0006E-3M+00.0004E-3E+00.0007E-3L+00.0009E-3M+00.0009E-3@+00.0008E-3@+00.0013E-3GPIB@+00.0010E-3@+00.0007E-3B+00.0007E-3I+00.0008E-3A+00.0006E-3D+00.0005E-3L+00.0010E-3A+00.0011E-3L+00.0012E-3M+00.0011E-3F+00.0007E-3M+00.0008E-3@+00.0009E-3@+00.0009E-3@+00.0009E-3@+00.0010E-3GPIB@+00.0011E-3A+00.0008E-3C+00.0005E-3C+00.0010E-3A+00.0009E-3@+00.0011E-3O+00.0009E-3G+00.0008E-3with ++ver every 16 bytesThe scope trace looks clean and is reaching 0 and 5V okD.

author: pqass
author_rank: Super Contributor
timestamp: March 14, 2024, 08:52:06 pm
content: Quote from: djrm on March 14, 2024, 08:28:41 pmIf the meter boots with "SELF TEST OK" then the cal data in the battery-backed RAM is A-okay."M" to "N" is \x4D or \b01001101to \x4E or \b01001110which is 2 bits off."M" to "@" is \x4D or \b01001101to \x40 or \b01000000is 3 bits off! Very odd!if you call "/usr/bin/echo -en "W\e\xHH\r++read\r" >>/dev/ttyUSB0" multiple times (at the problem addresses), does it consistantly give the same bad value? Or, does it occasionally give the correct value?

author: djrm
author_rank: Contributor
timestamp: March 14, 2024, 09:03:10 pm
content: The bad results are consistent and repeatable, I'm going to check my AR488 wiring again.I'm tempted to fit the LA onto the ram pins but I'm afraid I'd mess up and lose the cal completely.If I had full confidence in the GPIB cal reading then I'd try cal writing good checksums into the device (but I won't)I saw some discussion about newline character translation in some older GPIB firmware, but it was for another GPIB driver.

author: MarkL
author_rank: Unknown
timestamp: March 14, 2024, 10:46:49 pm
content: Quote from: djrm on March 14, 2024, 09:03:10 pmOooh... Back to basics. There's always a risk poking at something that's working, but you can minimize the risk by not putting your probes directly on the RAM chip. Probe the data and address lines, /RD, and the memory enable /OE1 on other chips, such as the processor and U506. Also stay away from U515 since it is also powered by the battery when the unit is off (it holds the RAM write line high), and obviously leave the CAL switch off.If you haven't seen it, here's some detail on how the SRAM readout was done previously:https://www.eevblog.com/forum/testgear/3478a-cal-ram-readout-idea/msg695908/#msg695908QuoteThat's a wise choice.

author: djrm
author_rank: Contributor
timestamp: March 14, 2024, 11:01:12 pm
content: Quote from: MarkL on March 14, 2024, 10:46:49 pmThanks, yes I spent all last night reading all the previous posts I could find including that one.I tried another Arduino firmware with the same pin definitions but it doesn't want to read the config data at all and isn't very happy reading data from the PC programs but does at least manage it from a terminal.I think the next step after a sleep will be to connect the LA to the GPIB lines and monitor the bus trafficI have yet to try the special extended function GPIB firmware, I believe it is now capable of reading calibration.D.

author: lmester
author_rank: Regular Contributor
timestamp: March 15, 2024, 01:23:53 pm
content: You may want to try a different AR488 firmware version and see if this fixes your problem.I recently had users of my software getting checksum errors when they tried to read the meter calibration. I found that this was caused by problems with specific AR488 firmware versions. My program works with AR488 0.49.14 but fails with AR488 0.51.18.

author: fenugrec
author_rank: Frequent Contributor
timestamp: March 15, 2024, 01:35:48 pm
content: Interesting...+1 on trying different fw versions, although this is oddly specific behaviour for it to occur on the same 2 locations every time.QuoteWell clearly, not *completely* - only those two ranges with questionable content. You could test writing and reading back values to the unused rows, that should be fairly harmless (unless writing somehow fails due to a bad RAM and you can't restore it, in which case you'd be hosed anyway).QuoteIf we're going to go that way, I'll add my own guesses :- your correction to the 3V range (first char becomes a '@' e.g. 0x00 ) : that is probable, since it's the most significant digit. Also follows a pattern where the offset is shifted by one digit each range and very similar through those DCV ranges.- On the 30mV range I'm not so sure that the checksum byte is corrupt.If you're equipped to probe directly the RAM data and address lines, that will be interesting. It would be a very strange problem if the RAM is read properly on initial selftest, but not later when queried via GPIB. Have you tried triggering a selftest after a few minutes of being powered on ?

author: djrm
author_rank: Contributor
timestamp: March 15, 2024, 02:54:57 pm
content: Quote from: lmester on March 15, 2024, 01:23:53 pmI'm very happy to report that the problem has gone away using AR488 V0.49.14Code:Version 12-29-22Gain encode/decode algorithm thanks to: Steve1515 (EEVblog) and fenugrec (EEVblog).Windows XP Service Pack 3 Platform ID 2Config file loaded.Arduino COM delay 1100msDebug ON.Command delay = 0ms.Max COM port = 64.OC:Open COM33 CheckCom.CheckCom start COM33CheckCom end CreateFileA COM33CheckCom port foundCheckCom end CloseHandle COM33OC:Open COM33 open port.OC:Open COM33 OK.CA:Start CheckAdapter on COM33CA:Check Prologix GPIB adapter. ProVer =:"GPIB"QS: Send:"++ver" Reply:""CA:Prologix not found. ++ver retry for Arduino.CA:Retry ++ver (Arduino boot delay)-r CA:Retry: Found Prologix adapter (Arduino retry).CA:Exit checkAdapter on COM33COM port set to COM33IG:Start InitGPIBIG:Find Prologix GPIB adapter.IG:ProVer srch:"GPIB"IG:Found Prologix adapter.IG:set ++mode 1.IG:set eot_enable 0.IG:set read timeout:++read_tmo_ms 3000IG:SetGPIB Address ++addr 23 success.IG:set EOI 0.IG:set EOS 0.IG:Set auto talk mode off: ++auto 0 success.IGT:QSB result 1Instrument address set to GPIB 233478A using current instrument settings.3478A connected.Instrument startInstrument stop/localInstrument stop/localCF:LogPath: Z:\home\david\Downloads\HP3478A\log\:Z:\home\david\Downloads\HP3478A\cfg\Reading calibration data.**********Verify checksums.@@@BICADLNELM : CkSum = (205 + 50) Checksum OK.@@@@BIADLALMF : CkSum = (214 + 41) Checksum OK.@@@@@@ACCA@OG : CkSum = (247 + 8) Checksum OK.IIIIIEADOCCKC : CkSum = (179 + 76) Checksum OK.@@@@@@ADLDNML : CkSum = (220 + 35) Checksum OK.@@@@@@@@@@@OO : CkSum = (255 + 0) Checksum OK.IIHI@HAEMCEKI : CkSum = (185 + 70) Checksum OK.IIIF@CALNCOJN : CkSum = (174 + 81) Checksum OK.IIIIEHALNBAK@ : CkSum = (176 + 79) Checksum OK.IIIIIE@EEBDKM : CkSum = (189 + 66) Checksum OK.IIIIIE@EBB@LD : CkSum = (196 + 59) Checksum OK.IIIIIF@EABEKO : CkSum = (191 + 64) Checksum OK.IIIIIF@ECL@KH : CkSum = (184 + 71) Checksum OK.IIIIIFALOOAJ@ : CkSum = (160 + 95) Checksum OK.IIIIGDBD@EBLC : CkSum = (195 + 60) Checksum OK.IIIIIGBD@OOJG : CkSum = (167 + 88) Checksum OK.@@@@@@@@@@@OO : CkSum = (255 + 0) Checksum OK.IIHI@HBDOLNJE : CkSum = (165 + 90) Checksum OK.@@@@@@@@@@@OO : CkSum = (255 + 0) Checksum OK.Reading calibration data complete.Calibration data checksum valid.Calibration data saved to:Z:\home\david\Downloads\HP3478A\cfg\HP3478A.calI'll study the sketch differences to try and identify the problem, but its not too important for me now.( I was using latest version 0.51.28 before )update: the AR488 code appears to have been extensively refactored between the non-working and working versions. it will not be trivial to find the cause of the problem.hp3478a_utils is now happy with the read calibration too:Code:david@I7MINT:~/Github/hp3478a_utils$ ./hp3478util************ hp3478util, (c) 2018-2020 fenugrec ************some missing args.usage:***** file input, if applicable--ascfile-a <filename>ASCII CAL dump--binfile-b <filename>binary CAL dump (one byte per nibble)***** action : specify one-ttest checksums of every record-p <outfile>create dump with processed bytes (clear 4 higher bits)-ddump raw data for every recorddavid@I7MINT:~/Github/hp3478a_utils$ ./hp3478util -a HP3478A.cal -t************ hp3478util, (c) 2018-2020 fenugrec ************entry 0x00: OK (30 mV DC)entry 0x01: OK (300 mV DC)entry 0x02: OK (3 V DC)entry 0x03: OK (30 V DC)entry 0x04: OK (300 V DC)entry 0x05: OK ((Not used))entry 0x06: OK (ACV)entry 0x07: OK (30 Ohm 2W/4W)entry 0x08: OK (300 Ohm 2W/4W)entry 0x09: OK (3 KOhm 2W/4W)entry 0x0A: OK (30 KOhm 2W/4W)entry 0x0B: OK (300 KOhm 2W/4W)entry 0x0C: OK (3 MOhm 2W/4W)entry 0x0D: OK (30 MOhm 2W/4W)entry 0x0E: OK (300 mA DC)entry 0x0F: OK (3A DC)entry 0x10: OK ((Not used))entry 0x11: OK (300 mA/3A AC)entry 0x12: OK ((Not used))david@I7MINT:~/Github/hp3478a_utils$ ./hp3478util -a HP3478A.cal -d************ hp3478util, (c) 2018-2020 fenugrec ************entry #offset(rawgain)gainrange0000029314CE51.01358530 mV DC0100002914C1C1.013606300 mV DC02000000133101.0133103 V DC0399999514F331.01393330 V DC0400000014C4E1.013638300 V DC05000000000001.000000(Not used)0699890815D351.014735ACV079996031CE3F1.00582930 Ohm 2W/4W089999581CE211.005821300 Ohm 2W/4W09999995055241.0055243 KOhm 2W/4W0A999995052201.00522030 KOhm 2W/4W0B999996051251.005125300 KOhm 2W/4W0C999996053C01.0052603 MOhm 2W/4W0D9999961CFF11.00589130 MOhm 2W/4W0E999974240521.024052300 mA DC0F999997240FF1.0239893A DC10000000000001.000000(Not used)1199890824FCE1.023858300 mA/3A AC12000000000001.000000(Not used)Photo shown my adapter.Thanks everyone for all the help, very much appreciated, David.Attached image shows difference in read cal using two versions of AR488

author: lmester
author_rank: Regular Contributor
timestamp: March 16, 2024, 05:04:50 am
content: Here is data from a user of my program that had the same checksum fail. He also had a checksum fail on the first and third cal entries. That might not be a coincedence. I need to do some more testing and report results to the AR488 author.

author: djrm
author_rank: Contributor
timestamp: March 16, 2024, 08:50:19 am
content: Quote from: lmester on March 16, 2024, 05:04:50 amThere is a bit of a pattern showing.The third line has an unusual character in the first position, I would expect to see an '@'The first line checksum is off by one. possibly caused by the wrong character in the 10th position.The same character appears in the first position of the third line and the 10th position in the first line.Possible causes are anybody's guess, maybee bad address sent or memory overwriting of received data...update, just having a look at the AR88 code structureScreenshot from 2024-03-16 09-53-55.png(666.19 kB. 1957x1665 - viewed 177 times.)Kind regards, David.

author: lmester
author_rank: Regular Contributor
timestamp: March 16, 2024, 07:50:05 pm
content: I just tested with my AR488. Checksum fails on first and third entry when using 0.51.18.Code:AR488 GPIB controller, ver. 0.49.14, 02/03/2021Reading calibration data.**********Verify checksums.@@@CA@BLLLNLG : CkSum = (199 + 56) Checksum OK.@@@@CABLLCOLO : CkSum = (207 + 48) Checksum OK.@@@@@DBLLOELM : CkSum = (205 + 50) Checksum OK.IIIIIDAEBAOKF : CkSum = (182 + 73) Checksum OK.@@@@@@AEBMNML : CkSum = (220 + 35) Checksum OK.@@@@@@@@@@@OO : CkSum = (255 + 0) Checksum OK.IIIE@BADODEL@ : CkSum = (192 + 63) Checksum OK.IIII@D@E@MNKG : CkSum = (183 + 72) Checksum OK.IIIIIA@EDNNJL : CkSum = (172 + 83) Checksum OK.IIIIII@ECDDKI : CkSum = (185 + 70) Checksum OK.IIIIII@EABLKE : CkSum = (181 + 74) Checksum OK.IIIIII@EBBOKA : CkSum = (177 + 78) Checksum OK.IIIIII@EBMAKD : CkSum = (180 + 75) Checksum OK.IIIIII@EBDOJO : CkSum = (175 + 80) Checksum OK.@@@BF@CNOE@MB : CkSum = (210 + 45) Checksum OK.@@@@BECN@@MMJ : CkSum = (218 + 37) Checksum OK.@@@@@@@@@@@OO : CkSum = (255 + 0) Checksum OK.IIIE@BCLCOBKJ : CkSum = (186 + 69) Checksum OK.@@@@@@@@@@@OO : CkSum = (255 + 0) Checksum OK.Reading calibration data complete.Calibration data checksum valid.Calibration data saved to:D:\HP3478A_6\cfg\HP3478A.cal#################################################AR488 GPIB controller, ver. 0.51.18, 26/02/2023Reading calibration data.**********Verify checksums.@@@CA@BLLGNLG : CkSum = (199 + 51) Checksum Fail.@@@@CABLLCOLO : CkSum = (207 + 48) Checksum OK.G@@@@DBLLOELM : CkSum = (205 + 57) Checksum Fail.IIIIIDAEBAOKF : CkSum = (182 + 73) Checksum OK.@@@@@@AEBMNML : CkSum = (220 + 35) Checksum OK.@@@@@@@@@@@OO : CkSum = (255 + 0) Checksum OK.IIIE@BADODEL@ : CkSum = (192 + 63) Checksum OK.IIII@D@E@MNKG : CkSum = (183 + 72) Checksum OK.IIIIIA@EDNNJL : CkSum = (172 + 83) Checksum OK.IIIIII@ECDDKI : CkSum = (185 + 70) Checksum OK.IIIIII@EABLKE : CkSum = (181 + 74) Checksum OK.IIIIII@EBBOKA : CkSum = (177 + 78) Checksum OK.IIIIII@EBMAKD : CkSum = (180 + 75) Checksum OK.IIIIII@EBDOJO : CkSum = (175 + 80) Checksum OK.@@@BF@CNOE@MB : CkSum = (210 + 45) Checksum OK.@@@@BECN@@MMJ : CkSum = (218 + 37) Checksum OK.@@@@@@@@@@@OO : CkSum = (255 + 0) Checksum OK.IIIE@BCLCOBKJ : CkSum = (186 + 69) Checksum OK.@@@@@@@@@@@OO : CkSum = (255 + 0) Checksum OK.Reading calibration data complete.Calibration data not saved. Invalid checksum!

author: djrm
author_rank: Contributor
timestamp: March 16, 2024, 08:08:05 pm
content: Quote from: lmester on March 16, 2024, 07:50:05 pmYour data has a very similar pattern to what I've seen.btw, the program HP3478ACalibration.exe failed with a misleading version error with v0.51.18 though reads calibration successfully with v0.49.14Code:PS C:\Users\David\Downloads\HP3478ACalibration_20200126> .\HP3478ACalibration.exe -f cal.txt -r 18Reading calibration data from instrument...ERROR: Failed while reading calibration data from instrument.Extended Error Information:Could not communicate with instrument.PS C:\Users\David\Downloads\HP3478ACalibration_20200126> .\HP3478ACalibration.exe -f cal.txt -r 18Reading calibration data from instrument...ERROR: Failed while reading calibration data from instrument.Extended Error Information:Invalid GPIB adapter version string.

author: WaveyDipole
author_rank: Frequent Contributor
timestamp: March 17, 2024, 11:58:02 am
content: I have been keeping an eye on this problem with interest ever since lmester reported it to me on thew AR488 thread. Someone else has now linked this one so I have just been reading up and it is indeed a curious problem. Initially it was suggested this might be related to a code change that resulted in a change to EOI timing. EOI should be signalled with the last character sent and not after it. I am uncertain why that change was made, but this should have been fixed in version 0.51.28. Logic analyzer traces seemed to indicate that the EOI signal is now being generated concurrently with the last character being sent. However, it seems that the problem is still present in 0.51.28 (according to djrm's comment in #150 and lmesters comment on the AR488 thread) so it seems there is something else going on. I also hadn't quite grasped that the problem consistently affects the first and third lines of the output and consistently affects multiple users in exactly the same two lines. That is certainly very odd.Unfortunately I haven't had a HP3478A to test with for some time, although I appreciate the comparison posted by lmester in post #153. I will investigate further but since I cannot conclusively test, I will have to rely on others being able to do so. I will obviously keep 0.49.14 available in the archive.David, your observations in #152 are also appreciated. I had noticed however, that in your #136, the wrong character is in position 13. It just so happens that in lmerster's example that the 10th and 13th character are the same but a noteworthy pattern nonetheless. The attnRequired, lonmode and tonmode functions do not come into play in controller mode, but certainly sendToInstrument and read_h will.I have been trying to refresh my memory on how the dump is generated and found a note that says a W<addr> command is sent to the instrument where <addr> runs from 0 to 255, presumably in a loop. I am assuming that a ++read has to be sent to read each byte in turn? From the dump it would see that a checksum is calculated for every 13 bytes received?

author: djrm
author_rank: Contributor
timestamp: March 17, 2024, 02:32:17 pm
content: Quote from: WaveyDipole on March 17, 2024, 11:58:02 amMy post #150 has an attachment image showing the bad and good transfers, the data in post #136 has the bad and manually 'corrected' values, I later realised that the error positions were not what I had guessed. clear now? relevant section of image inline below:I could setup a LA trace on the GPIB lines if it would be any help fixing the problem.I have now made an additional board to run HP3478ext software, that too is working well now.

author: pqass
author_rank: Super Contributor
timestamp: March 17, 2024, 03:30:27 pm
content: Quote from: WaveyDipole on March 17, 2024, 11:58:02 amA checksum byte is saved into the cal SRAM when the calibration is saved for each type (DCV,ACV,DCA,ACA,ohms)+range. The W command just reads any addressed byte from that SRAM. The cal SRAM is organzied as 19 records of 13 bytes (11+checksum word). The first record begins at address 01 hex; first byte of the SRAM is ignored. Three records are unused and there is 8 bytes padding at the end. The checksum word is used to validate the previous 11 bytes of a given record.What the control program should be doing is issuing the following command for each SRAM byte requested at the given address:W\e\xHH\r++read\rWhere:\xHH = byte representing a hex address into a 256 nibble SRAM\e = ASCII escape\r = ASCII carriage returnSame command as hex: (hhis the address byte)57 1Bhh0D 2B 2B 72 65 61 64 0DBut these are the problem commands:57 1b0a0d 2b 2b 72 65 61 64 0d57 1b1b0d 2b 2b 72 65 61 64 0dIt's interesting that the 3rd byte, what should be an unmolested address, happens to be a control code. Hmmm.... Check the escape logic Wavey.

author: m k
author_rank: Super Contributor
timestamp: March 17, 2024, 05:05:16 pm
content: My first thought was a corrupted memory where variable width is too narrow.But maybe it has something to do with values under 0x20.

author: djrm
author_rank: Contributor
timestamp: March 17, 2024, 05:11:01 pm
content: I have now run a pulseview gpib trace and can see missing address bytes in the read commands.trace is taken when running read cal with HP3478A Control with AR488 V0.51.28Maybe easier to see in this view:

author: lmester
author_rank: Regular Contributor
timestamp: March 17, 2024, 05:27:38 pm
content: My code uses the Prologix W command to send the cal RAM address (0-255). It also uses the escape sequence when the address is a Prologix reserved character <CR><LF><ESC> and +.It does look like there is a problem with the binary write or escape sequence logic.Code:print #main.Terminal,"Reading calibration data."print #comm,"D2READING CAL" '"READING CAL" message on meter displaycall sleep 10 'Fix for "John AR488" Firmwarey=0for x = 0 to 255 'Read 256 nibblescp$=chr$(x)'<ESC> sequence to send reserved binary chars to Prologix adapterselect case xcase 13 '<CR>cp$=esc$+cp$case 10 '<LF>cp$=esc$+cp$case 27 '<ESC>cp$=esc$+cp$case 43 '"+"cp$=esc$+cp$end select'Read instrument config data. Each char contains one nibble.ICal$(x)=QuerySERB$("W"+cp$,cr$,1,1)if len(ICal$(x))<>1 thenif DBug then print #main.Terminal,"RC:Fail query W :";ICal$(x);" Len:";len(ICal$(x))print #main.Terminal,"Instrument com fail."if handle$ <> "NoSave" thennotice "Instrument com fail. Calibration not read."elsenotice "Instrument com fail during calibration data backup!"end ifInstOK=0:goto  'Instrument com failend ify=y+1:if y>24 then print #main.Terminal,"*";:y=0next x'print #main.Terminal,":";ICal$(0);":";asc(ICal$(0)) 'Test for Girlando 0x00 binary send bugprint #main.Terminal,cr$;"Verify checksums."CRSum=1 'init read data checsum is validfor x = 0 to 18 'Checksum for 19 cal entriescs=0 'Checksumfor y= 0 to 10 '11 nibbles data in each entrynib=asc(ICal$((x*13)+y+1))nib=nib and 15 'mask hi nibbleprint #main.Terminal,ICal$((x*13)+y+1);cs=cs+nibcs=cs and 255 'Truncate to 8 bitsnext ydcs=csnib=asc(ICal$((x*13)+12))nib=nib and 15 'mask hi nibbleprint #main.Terminal,ICal$((x*13)+12);nib=nib * 16 'Shift left 4 bitscs=cs+nibcs=cs and 255 'Truncate to 8 bitsnibh=nibnib=asc(ICal$((x*13)+13))nib=nib and 15 'mask hi nibbleprint #main.Terminal,ICal$((x*13)+13);" : CkSum = (";print #main.Terminal,nib+nibh;" ";cs=cs+nibcs=cs and 255 'Truncate to 8 bitsif dcs>10 then 'Format textprint #main.Terminal,"+ ";dcs;") ";elseprint #main.Terminal,"+ ";dcs;") ";end ifif cs=255 thenprint #main.Terminal,"Checksum OK."elseif x=5 or x=16 or x=18 thenprint #main.Terminal,"Checksum fail unused loc-ignore."elseprint #main.Terminal,"Checksum Fail."CRSum=0 'Checksum failend ifend ifnext xprint #main.Terminal,cr$;print #main.Terminal,"Reading calibration data complete."if CRSum=1 thenprint #main.Terminal,"Calibration data checksum valid."' if handle$<> "NoSave" then 'print #main.Terminal,"Calibration data saved to:";CalFileU$open CalFileU$ for output as #5for x = 0 to 255print #5,ICal$(x);next xclose #5' end ifelseif handle$<> "NoSave" thenprint #main.Terminal,"Calibration data not saved. Invalid checksum!"notice "Calibration data not saved. invalid checksum!"elseprint #main.Terminal,"Invalid checksum during calibration data read!"notice "Invalid checksum during calibration data backup!"end ifend if'====================================================function QuerySERB$(icmd$,irsp$,blen,timeout)'This function sends a command, then waits for a response or timeout'Allows blen # of binary chars to be retrieved.'icmd$ = command to send'irsp$ = expected response'blen = binary data flag >0 = number of expected bytes'timeout = # seconds to abort (ms resolution)if icmd$<>"" then if lof(#comm) > 0 then rs$ = input$(#comm, lof(#comm)) 'Flush bufferif icmd$<>"" then print #comm,icmd$ 'Send command if presentif VTD>0 then call sleep VTD 'Time delay for Arduino adapter' if DBug then print #main.Terminal,"QuerySERB: READ EOI"if blen>0 thenprint #comm,"++read eoi" 'Request response wait for EOI' if DBug then print #main.Terminal,"QuerySERB:++read eoi"elseprint #comm,"++read eoi"' in QueryserB Girlando adapter chokes on this:' just use read eoi for now' print #comm,"++read ";asc(right$(irsp$,1)) 'Request response no EOI wait for last char in irsp$' if DBug then print #main.Terminal,"QuerySERB:++read "; asc(right$(irsp$,1));":"end if' if DBug then print #main.Terminal,"QuerySERB: READ EOIx"ok = 0 'Start with error flag setdl=0 'Binary data lengther$ = "" 'Instrument responseRTimeS=time$("ms") 'Init the timerwhile ETime(RTimeS) < (timeout*1000) and ok = 0if lof(#comm) > 0 thenrs$ = input$(#comm, lof(#comm))er$ = er$ + rs$dl=len(er$)if blen<>0 then'Use length if length > 0if dl>=blen then ok=1 'Got all # bytes?else'Use ASCII terminator if length = 0if instr(er$,irsp$) > 0 then ok = 1 'Found terminating string?end ifRTimeS=time$("ms") 'Init the timerend ifcall sleep 1 'Don't be a CPU hogwend' if counter >0 then print #main.Terminal, "RespQS$: ";counterQuerySERB$=er$ 'Return stringif ok = 0 then QuerySERB$="" 'Return null for error' if DBug then print #main.Terminal,"QuerySERB Send:";qt$;icmd$;qt$;"QSB Reply:";qt$;er$;qt$;"QSB Delay:";VTD;"ms"' if DBug then' for n=1 to len(er$):print #main.Terminal, asc(mid$(er$,n,1));"%";:next' end ifif lof(#comm) > 0 then er$ = input$(#comm, lof(#comm)) 'Clear any remaining from bufferend function

author: WaveyDipole
author_rank: Frequent Contributor
timestamp: March 17, 2024, 06:05:20 pm
content: Thanks Luke. Yes, that also occurred to me when I realised that the first character position in row 3 is the 27th character. So we have the 10th, 13th and 27th characters that are suspect. When looking at how the calibration values reading routine works I then saw this in your HP3478 code:Code:select case xcase 13 '<CR>cp$=esc$+cp$case 10 '<LF>cp$=esc$+cp$case 27 '<ESC>cp$=esc$+cp$case 43 '"+"cp$=esc$+cp$end selectCoincidence? The character codes of the characters that are correctly being escaped in your code seem to coincide with the character positions that are incorrect in the cal data output, except maybe character position 43?The output shown in #157 is very interesting. Thank you David. You have highlighted the lines with the W command (hex 0x57). One can then see the <addr> byte followed by CRLF (0x0d, 0x0a), except in the 10th and 13th request where we only see CRLF. I am curious whether then same is true in the block for address 43 (0x2b).Now I need to have a look at my code and figure out what the problem is, but I agree, its likely related to the escaping of certain characters.

author: WaveyDipole
author_rank: Frequent Contributor
timestamp: March 17, 2024, 07:09:53 pm
content: Does the cal data reading process set ++eoi 1? Could someone run a test reading the cal data with ++eoi 1 set please and post whether they get a successful read or the same result?

author: djrm
author_rank: Contributor
timestamp: March 17, 2024, 08:31:14 pm
content: Quote from: WaveyDipole on March 17, 2024, 07:09:53 pmGreetings,TI see in the console that the hp3478.exe program sends a "++eoi 0" command at startup, If I manually send "++eoi 1" afterthe program has started from another shell then a subsequent read of the cal setting succeeds.hth David

author: fenugrec
author_rank: Frequent Contributor
timestamp: March 17, 2024, 09:08:25 pm
content: Am I reading correctly that you guys are sending (as seen on GPIB) W \r <addr> \n ?In my code (uses NI libs, tested once or twice on a DOS machine), I was doing " W <addr> \n", in other words no \r at all :Code:cmd='W';cmd='\n';for (idx=0; idx < CALSIZE; idx++) {cmd = (uint8_t) idx;ibwrt(Dev, cmd, 3);if (ibsta & ERR) {printf("wrt problem @ 0x%X\n", idx);goto badexit;}ibrd(Dev, &buf, 1);It sure looks like there may be some escaping problems in AR488 but removing the \r entirely may help on unpatched firmware ? (cannot test myself)https://github.com/fenugrec/hp3478a_utils/blob/master/hp3478util.c#L429

author: pqass
author_rank: Super Contributor
timestamp: March 17, 2024, 09:09:14 pm
content: So I ran an experiment...I enabled the cal screw on the faceplate and issued this command:echo -en "X\e\x0a\x41\r++read\r" >>/dev/ttyUSB0My good cal was changed from (5th record beginning from hex address 35):Code:$ ./verify.sh pqass.cal...000035 49 49 49 49 49 49 42 45 43 4e 4d 4a 44 >IIIIIIBECNMJD<04: raw_offset=999999 raw_gain=253ed offset=-000001 gain=1.025277 crc=ff 300 V DC...to failed record (crc!=ff):Code:$ ./verify.sh /tmp/pqass.redo.cal...000035 49 49 49 49 49 49 42 45 43 4e 4d 4a 4d >IIIIIIBECNMJM<04: raw_offset=999999 raw_gain=253ed offset=-000001 gain=1.025277 crc=108 300 V DC...The difference just happens to be the last (checksum) byte of the record.What I think happened is the "if (cfg.eoi)...else" branch (see code below) suppressed the 0A (hex) address byte I was targeting and instead used the next byte 41 (hex) as an address instead with the following byte \r or 0D (hex) as the byte to save at that address.CORRECTION: the \r would have been suppressed too. Hmmm... I don't know why exactly a D (hex) was saved but it definitely skipped the first 0A address byte because it changed the byte at 41 (hex)!CORRECTION to the CORRECTION: the second \r is from when the buffer is split; the 1st half being the X<addr><value> but the <value> is truncated. ie. the meter is using the end of line marker as the value to save.The SRAM is really only 4 bits wide so upon readback the meter just puts a 4 (hex) in the upper nibble, hence it returned "M" which is 4D (hex).From GPIBbus.cpp version 0.51.18:Code:void GPIBbus::sendData(char *data, uint8_t dsize) {...// Write the data stringfor (int i = 0; i < dsize; i++) {// If EOI asserting is onif (cfg.eoi) {// Send all characterserr = writeByte(data, NO_EOI);} else {// Otherwise ignore non-escaped CR, LF and ESCif ((data != CR) && (data != LF) && (data != ESC)) err = writeByte(data, NO_EOI);}#ifdef DEBUG_GPIBbus_SENDDB_RAW_PRINT(data);#endifif (err) break;}...So how does this differ from AR488.ino 0.49.14:Code:void gpibSendData(char *data, uint8_t dsize) {...for (int i = 0; i < dsize; i++) {// If EOI asserting is onif (AR488.eoi) {// Send all characterserr = gpibWriteByte(data);} else {// Otherwise ignore non-escaped CR, LF and ESCif ((data != CR) || (data != LF) || (data != ESC)) err = gpibWriteByte(data);}#ifdef DEBUG3dbSerial->print(data);#endifif (err) break;}...For 0.51.18, Wavey "fixed" theCode:if ((data != CR) || (data != LF) || ...code given that this will always return true.

author: WaveyDipole
author_rank: Frequent Contributor
timestamp: March 17, 2024, 10:07:18 pm
content: pqass, you kind of beat me to it, but yes, that is the explanation!Quote from: djrm on March 17, 2024, 08:31:14 pmThank you for test that and the result is as I suspected. It confirms what the problem is.In order to explain, it is necessary to consider the command sequence that is being sent to the meter in order to retrieve the cal data. To recap the command is:W<addr>, where <addr> is a single byte containing the memory address of the nibble to be read. Mark that. This is binary data, not text. The data is then followed by CRLF as a "line terminator" because ++eos is set to its default setting.Now here is the (now repeated) code from 0.49.14 which sends the data:Code:// Write the data stringfor (int i = 0; i < dsize; i++) {// If EOI asserting is onif (AR488.eoi) {// Send all characterserr = gpibWriteByte(data);} else {// Otherwise ignore non-escaped CR, LF and ESCif ((data != CR) || (data != LF) || (data != ESC)) err = gpibWriteByte(data);}if (err) break;}I have removed the debug bit for clarity. We have a loop processing the buffer called data which contains the characters to be sent. In this case, the buffer contains 2 bytes: 0x57 and the <addr> byte, the terminators having been removed at the parsing stage. Note that if ++eoi is set to 1 (EOI asserting is on), then all characters in the buffer are written to GPIB. This is followed by terminators being added on according to to ++eos setting with EOI being signaled on the last character sent.However, if ++eoi is 0, then the 'else' clause comes into play. In this case, CR, LF and ESC characters are ignored. Why? Because if we are using CR, LF or CRLF as terminators without EOI, then we assume this to be a line of text which should not contain any additional terminator characters except those at its end. Nor should it contain an Escape (hex 0x27) character. However, if we take, for example address 10, we get the sequence: 0x57, 0x0A, then the 0x0A gets filtered but we still get the terminators added on according to the ++eos setting, so what actually gets sent is 0x57, 0x0D, 0x0A. The same would happen for address 13 and address 27.The problem with the above line is that each condition had been or'ed by mistake. This means that only one of the three conditions needed to be met in order for the statement to evaluate to true. This would result in any unexpected terminators or escape character being sent regardless. The error was corrected in later code by and'ing the conditions and changing the line to:Code:if ((data != CR) && (data != LF) && (data != ESC)) state = writeByte(data, NO_EOI);Now, as intended, all three conditions must be met for the statement to evaluate to true and for the byte to be sent over GPIB. In short, the filtering now works as intended. The write command is slightly different in the restructured code but the effect is the same. Any unfiltered byte is written to the GPIB bus without using EOI and terminators are added at the end of the transmitted sequence.The inadvertent consequence of fixing this error has resulted in the behavioral change that has been observed here. In 0.49.14, addresses 0x10, 0x13 and 0x27 will have been sent regardless so reading the cal data worked correctly. In later fixed versions, those characters are no longer sent in text mode so they are omitted and we get an erroneous reading for those addresses. Address 43 (corresponding to the + character) is not affected.The question that now arises how to deal with this appropriately. On the one hand filtering could be removed so that all characters sent regardless. On the other hand, because we are dealing with bytes rather than ASCII text, ought we to be treating the data as binary and therefore having the HP3478A set to using EOI only as terminator and the AR488 set with ++eoi 1 and ++eos 3 (no terminator characters)? It looks like the meter ignores the trailing CRLF anyway, so perhaps ++eoi 1 and leaving the meter as is would be sufficient? I am open to suggestion and perhaps will also need to re-consider whether the filtering really is necessary or whether it is more of a hindrance and should be removed.

author: djrm
author_rank: Contributor
timestamp: March 17, 2024, 10:18:23 pm
content: Quote from: fenugrec on March 17, 2024, 09:08:25 pmThe trace I made shows (#159) W<addr>\r\n but in some cases the <addr> is missed out and the subsequent \r gets interpreted as the address.David.

author: fenugrec
author_rank: Frequent Contributor
timestamp: March 17, 2024, 10:34:28 pm
content: Quote from: WaveyDipole on March 17, 2024, 10:07:18 pmAs I recall (haven't worked on this in 3y), the prologix docs had a few grey areas wrt terminations. Here's how I interpreted and implemented in my firmware :1- filter incoming bytes from host :- skip (don't change) escaped chars- convert unescaped \r to \n,- interpret \n as "end of chunk" and mark it.There may thus be two \n in a row after a conversion from \r to \n, but that is not a problem in later steps2- parse chunks as either command or data, un-escaping as required.3- if data, send on bus with EOS and EOI as required (There is no ambiguity on which chars must be sent on the bus, vs chunk termination from host)

author: pqass
author_rank: Super Contributor
timestamp: March 17, 2024, 10:40:40 pm
content: So what to do if EOI isn't on - that is, rely on \r or \n (or combo), whatever eos is set to, to signal an end of message.Stripping \r \n \e is currently a silent error since it can have side-effects to commands that accept binary data.How do you currently treat fatal errors like bus problems to control programs? Do you send error messages back?I think I recall seeing errors returned If verbose mode is on. Maybe you can return a message to say "\r \n \e were stripped, use eoi=1".At least if the user turns on verbose mode then he'll see it.

author: djrm
author_rank: Contributor
timestamp: March 17, 2024, 11:05:10 pm
content: Quote from: WaveyDipole on March 17, 2024, 10:07:18 pmI have limited experience of GPIB (now on my third day) but expecting a change in the reader programs eoi setting is a separate issue to fixing the bug. The old interface worked ok and the new one will with the bug corrected, the meter doesn't seem to care about the eoi setting. I'd be happy to use the new software with the bug corrected without any other changes.Kind regards, David.

author: lmester
author_rank: Regular Contributor
timestamp: March 18, 2024, 04:32:19 am
content: I have a real Prologix adapter. I did some testing with this adapter. I can properly read cal data with EOI 1 or EOI 0. The AR488 adapter only reads cal properly with EOI 1.Is it better to exactly match the behavior of the Prologix adapter or keep AR488 how it's operating now?I would say match the behavior of the Prologix adapter since AR488 is a replacement for the Prologix.

author: m k
author_rank: Super Contributor
timestamp: March 18, 2024, 12:11:05 pm
content: Back in the day with ASCII terminals CRLF (\r\n) was not a problem, both characters were needed.I'd say that keep everything that would be sent to controller from the device, so GPIB side.And remove everything extra from non GPIB side.488.1 is not defining any special characters for devices.EOS is just one that is defined on top of that.So if device is sending CRLF then that is how it should be.Tek 492P GPIB Concepts is using words "can" and "may" when dealing with EOI.So more like an option.

author: djrm
author_rank: Contributor
timestamp: March 18, 2024, 12:25:36 pm
content: I have edited AR488 version 0.51.28 to revert the eoi testing to use && as suggested (line 700 in AR488_GPIBus.cpp) and the new firmware works now with HP3478ACalibration.exe and HP3478A.exeI have noticed that under wine HP3478ACalibration.exe doesn't work as well as AR488 version 0.49 does, an error reading the version string nearly always occurs. (but not in WIndows)hth David.

author: m k
author_rank: Super Contributor
timestamp: March 18, 2024, 12:47:04 pm
content: I'm like almost having a recollection where something had a selector between versions 1 and 2.Was it a hardware or software thing, can't say.But no doubt, different style of EOI would require some action.

author: WaveyDipole
author_rank: Frequent Contributor
timestamp: March 18, 2024, 07:22:11 pm
content: Having "slept on it" I concur that Prologix compatibility should be maintained as this was the intention from the start. Since the filter was ineffective in 0.49.14 and earlier and that didn't seem to do any harm, yet when 'fixed', it did cause unexpected problems, it seems the logical choice is to simply remove it. To that end the program statement in question has been simplified to just send the byte to GPIB. I have left the old line commented out in the code with a note to remind me not to re-enable it again! An update has now been published to the Github repository. Hopefully someone can tell me whether the cal data is now retrieved correctly as it was previously without needing to use ++eoi 1 ?

author: djrm
author_rank: Contributor
timestamp: March 18, 2024, 08:29:28 pm
content: Quote from: WaveyDipole on March 18, 2024, 07:22:11 pmGreetings,Seems to work ok now, any particular test I should perform? attached is pulseview trace of successful data transfer from HP3478A.exe using Wine on Linux Mint.pulseview-hexdump-rawbytes-HP3478A-read-cal-AR488-v0.51.29.txt(17.18 kB - downloaded 171 times.)Kind regards, David.

author: WaveyDipole
author_rank: Frequent Contributor
timestamp: March 18, 2024, 08:40:26 pm
content: Thanks for confirming. As regards tests, the only other checks I would do would be to make sure that the correct readings are returned and that the meter can be remote controlled. I doubt however, that the this change will have had any effect on those functions. I would expect them to continue working OK.

author: radar_macgyver
author_rank: Frequent Contributor
timestamp: March 21, 2024, 04:17:52 am
content: I have a 3478Aprototype version(at least, I think it's a 3478A, it has no label or serial number). I used a Prologix GPIB to Ethernet adapter and a Python script to read the calibration RAM, and it looks rather different from what others have posted here. Almost looks like it's "partially" calibrated, though it doesn't report an error on startup.0000: 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 IIIIIIII IIIIIIII0010: 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 IIIIIIII IIIIIIII0020: 42 42 44 42 41 4c 4e 48 49 49 49 49 49 41 42 45 BBDBALNH IIIIIABE0030: 4d 43 42 4b 48 40 40 40 40 40 40 42 44 44 41 44 MCBKH@@@ @@@BDDAD0040: 4f 40 40 40 40 40 40 40 40 40 40 40 40 40 40 49 O@@@@@@@ @@@@@@@I0050: 49 47 44 43 46 42 44 41 4c 45 4c 41 49 49 49 44 IGDCFBDA LELAIIID0060: 42 47 41 4c 45 4c 42 4b 47 49 49 49 49 48 46 41 BGALELBK GIIIIHFA0070: 4c 4c 42 41 4b 41 49 49 49 49 49 45 40 45 43 49 LLBAKAII IIIE@ECI0080: 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 IIIIIIII IIIIIIII0090: 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 IIIIIIII IIIIIIII00a0: 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 IIIIIIII IIIIIIII00b0: 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 IIIIIIII IIIIIIII00c0: 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 IIIIIIII IIIIIIII00d0: 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 IIIIIIII IIIIIIII00e0: 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 IIIIIIII IIIIIIII00f0: 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 IIIIIIII IIIIIIIIAny ideas why it doesn't report an error? Or is this a quirk of the Prologix GPIB-Ethernet adapter? I did escape CR,NL,ESC and '+' (my code is attached).

author: pqass
author_rank: Super Contributor
timestamp: March 21, 2024, 05:27:47 am
content: Radar, most of your cal records fail checksum.If it is a prototype then the software probably isn't the final release version; checksum validation likely disabled.What does the sticker on the U502 ROM say? Mine says: "03478-65501", next line: "D/C 8841"However, have you compared it to another meter for each of the ranges?Note: crc=ff means record passes validation.Code:$ ./verify.sh radar.cal000001 49 49 49 49 49 49 49 49 49 49 49 49 49 >IIIIIIIIIIIII<00: raw_offset=999999 raw_gain=99999 offset=-000001 gain=0.922223 crc=fc 30 mV DC00000e 49 49 49 49 49 49 49 49 49 49 49 49 49 >IIIIIIIIIIIII<01: raw_offset=999999 raw_gain=99999 offset=-000001 gain=0.922223 crc=fc 300 mV DC00001b 49 49 49 49 49 42 42 44 42 41 4c 4e 48 >IIIIIBBDBALNH<02: raw_offset=999992 raw_gain=2421c offset=-000008 gain=1.024206 crc=12c 3 V DC000028 49 49 49 49 49 41 42 45 4d 43 42 4b 48 >IIIIIABEMCBKH<03: raw_offset=999991 raw_gain=25d32 offset=-000009 gain=1.024732 crc=ff 30 V DC000035 40 40 40 40 40 40 42 44 44 41 44 4f 40 >@@@@@@BDDADO@<04: raw_offset=000000 raw_gain=24414 offset=+000000 gain=1.024414 crc=ff 300 V DC000042 40 40 40 40 40 40 40 40 40 40 40 40 40 >@@@@@@@@@@@@@<05: raw_offset=000000 raw_gain=00000 offset=+000000 gain=1.000000 crc=00 <not used>00004f 49 49 47 44 43 46 42 44 41 4c 45 4c 41 >IIGDCFBDALELA<06: raw_offset=997436 raw_gain=241c5 offset=-002564 gain=1.024065 crc=ff AC V00005c 49 49 49 44 42 47 41 4c 45 4c 42 4b 47 >IIIDBGALELBKG<07: raw_offset=999427 raw_gain=1c5c2 offset=-000573 gain=1.006462 crc=ff 30 Ohm 2W/4W000069 49 49 49 49 48 46 41 4c 4c 42 41 4b 41 >IIIIHFALLBAKA<08: raw_offset=999986 raw_gain=1cc21 offset=-000014 gain=1.005621 crc=ff 300 Ohm 2W/4W000076 49 49 49 49 49 45 40 45 43 49 49 49 49 >IIIIIE@ECIIII<09: raw_offset=999995 raw_gain=05399 offset=-000005 gain=1.005223 crc=e5 3 kOhm 2W/4W000083 49 49 49 49 49 49 49 49 49 49 49 49 49 >IIIIIIIIIIIII<10: raw_offset=999999 raw_gain=99999 offset=-000001 gain=0.922223 crc=fc 30 kOhm 2W/4W000090 49 49 49 49 49 49 49 49 49 49 49 49 49 >IIIIIIIIIIIII<11: raw_offset=999999 raw_gain=99999 offset=-000001 gain=0.922223 crc=fc 300 kOhm 2W/4W00009d 49 49 49 49 49 49 49 49 49 49 49 49 49 >IIIIIIIIIIIII<12: raw_offset=999999 raw_gain=99999 offset=-000001 gain=0.922223 crc=fc 3 MOhm 2W/4W0000aa 49 49 49 49 49 49 49 49 49 49 49 49 49 >IIIIIIIIIIIII<13: raw_offset=999999 raw_gain=99999 offset=-000001 gain=0.922223 crc=fc 30 MOhm 2W/4W0000b7 49 49 49 49 49 49 49 49 49 49 49 49 49 >IIIIIIIIIIIII<14: raw_offset=999999 raw_gain=99999 offset=-000001 gain=0.922223 crc=fc 300 mA DC0000c4 49 49 49 49 49 49 49 49 49 49 49 49 49 >IIIIIIIIIIIII<15: raw_offset=999999 raw_gain=99999 offset=-000001 gain=0.922223 crc=fc 3A DC0000d1 49 49 49 49 49 49 49 49 49 49 49 49 49 >IIIIIIIIIIIII<16: raw_offset=999999 raw_gain=99999 offset=-000001 gain=0.922223 crc=fc <not used>0000de 49 49 49 49 49 49 49 49 49 49 49 49 49 >IIIIIIIIIIIII<17: raw_offset=999999 raw_gain=99999 offset=-000001 gain=0.922223 crc=fc 300 mA/3A AC0000eb 49 49 49 49 49 49 49 49 49 49 49 49 49 >IIIIIIIIIIIII<18: raw_offset=999999 raw_gain=99999 offset=-000001 gain=0.922223 crc=fc <not used>0000f8 49 49 49 49 49 49 49 49 >IIIIIIII<19: <padding>Attached is my verify.sh script (slightly updated from my #123 post; added switch to od command to show duplicate lines).Remove the .txt ending.

author: m k
author_rank: Super Contributor
timestamp: March 21, 2024, 07:21:33 am
content: Data lengths8, 5, 8, 6, 6, 14, 2, 11, 3, 10, 4, 9, 5, 4so8,5, 8,6, 6,14,2, 11,3, 10,4, 9,5,4Last is unknown, but others are ok, one empty.First is only 8 long starting from 0x20.

author: fenugrec
author_rank: Frequent Contributor
timestamp: March 22, 2024, 12:36:10 am
content: Quote from: radar_macgyver on March 21, 2024, 04:17:52 amInteresting... if you have a ROM dump and want to investigate, you're looking for this function :https://github.com/fenugrec/hp3478a_utils/blob/master/ROM_disasm/dc118.d48#L285may end up somewhere else but will be similar (a short loop with movx to read the RAM, bitwise 'and' with 0x0F, add every field, then check)

author: radar_macgyver
author_rank: Frequent Contributor
timestamp: March 22, 2024, 04:41:36 am
content: @pqpass, thank you for decoding my hex dump.U502 is a 24-pin ceramic DIP with no window, and no stickers on it. I guess it must be prototype firmware. I don't have an EPROM reader so I can't do a dump. Maybe I should get one...When comparing against my 6500, here's what I get:TestDMM6500HP 3478Notes30 mV29.7 mV29.7 mVWas very noisy0.3V0.30030.3003Was very noisy3V3.00283.003030V30.029030.029870V70.038570.040The max my PSU could do100mA100.000124.241.0A1.00051.244100k99.987299.980Using DMMcheck10k10.0023610.0014Using DMMcheck1k0.09996260.99955Using DMMcheck100100.1650100.155Using DMMcheck5VDC4.999855.0000Using DMMcheck5VAC4.999184.9998Using DMMcheckI used my bench power supply for the DC voltage tests except the last two, those are from a DMMcheck. The resistance tests are also from the DMMcheck. Looks like the amps ranges are clearly not calibrated, though the DC volts and ohms show very good results. This leads me to think, combined with the fact that the dump reads back the same '0x49' for all offsets < 0x20 that it may be due to the GPIB interface I'm using (0x20 = 32 = first printable char).

author: m k
author_rank: Super Contributor
timestamp: March 22, 2024, 07:57:46 am
content: Quote from: radar_macgyver on March 22, 2024, 04:41:36 amIf so then all after 0x7E can be the same, excluded for what ever reason.You can concentrate to address 0x1F and few before that.Those missing from first set should be 0x40.There are two possibilities.Either the first set is really 8 long, or those first 0 values are missing.

author: pqass
author_rank: Super Contributor
timestamp: March 22, 2024, 12:01:31 pm
content: Quote from: radar_macgyver on March 22, 2024, 04:41:36 amThere may be some funny business going on with values at addresses <0x20 and >=0x80.Have you seenthis (reply #134) version of a python scriptthat corrects for some default string conversions that may be occurring. Please re-run.Otherwise, the meter tracks pretty close to the DMM6500 (except for the amps ranges).

author: radar_macgyver
author_rank: Frequent Contributor
timestamp: March 23, 2024, 04:58:35 am
content: It seems like the Python string conversions were messing up both my code as well as the Prologix interface library that I found on github. The solution was to create a tcp socket directly to the converter rather than rely on the library. With that change, I get the following:0000: 40 40 40 40 42 42 45 42 45 4f 43 4f 4c 4e 40 40 @@@@BBEB EOCOLN@@0010: 40 40 41 42 42 44 45 41 45 4e 4b 40 40 40 40 40 @@ABBDEA ENK@@@@@0020: 42 42 44 42 41 4c 4e 48 49 49 49 49 49 41 42 45 BBDBALNH IIIIIABE0030: 4d 43 42 4b 48 40 40 40 40 40 40 42 44 44 41 44 MCBKH@@@ @@@BDDAD0040: 4f 40 40 40 40 40 40 40 40 40 40 40 40 40 40 49 O@@@@@@@ @@@@@@@I0050: 49 47 44 43 46 42 44 41 4c 45 4c 41 49 49 49 44 IGDCFBDA LELAIIID0060: 42 47 41 4c 45 4c 42 4b 47 49 49 49 49 48 46 41 BGALELBK GIIIIHFA0070: 4c 4c 42 41 4b 41 49 49 49 49 49 45 40 45 43 42 LLBAKAII IIIE@ECB0080: 45 4b 4e 40 40 40 40 41 46 40 45 45 42 4f 4d 4d EKN@@@@AF@EEBOMM0090: 49 49 49 49 49 47 41 4c 4c 4e 43 4a 41 49 49 49 IIIIIGAL LNCJAIII00a0: 49 49 45 40 45 45 42 4d 4b 44 49 49 49 49 49 48 IIE@EEBM KDIIIIIH00b0: 41 4d 4d 4e 42 49 4f 49 49 49 49 43 45 41 4d 43 AMMNBIOI IIICEAMC00c0: 41 4c 4b 45 49 49 49 49 48 49 41 4d 4e 4e 44 49 ALKEIIII HIAMNNDI00d0: 4c 40 40 40 40 40 40 40 40 40 40 40 40 40 49 49 L@@@@@@@ @@@@@@II00e0: 47 44 43 46 41 4c 43 44 41 4c 44 40 40 40 40 40 GDCFALCD ALD@@@@@00f0: 40 40 40 40 40 40 40 48 40 40 40 40 40 40 40 40 @@@@@@@H @@@@@@@@************ hp3478util, (c) 2018-2020 fenugrec ************entry# offset (rawgain) gain range00 000225 25F3F 1.024929 30 mV DC01 000012 24515 1.024515 300 mV DC02 000002 2421C 1.024206 3 V DC03 999991 25D32 1.024732 30 V DC04 000000 24414 1.024414 300 V DC05 000000 00000 1.000000 (Not used)06 997436 241C5 1.024065 ACV07 999427 1C5C2 1.006462 30 Ohm 2W/4W08 999986 1CC21 1.005621 300 Ohm 2W/4W09 999995 05325 1.005325 3 KOhm 2W/4W0A 000016 0552F 1.005519 30 KOhm 2W/4W0B 999997 1CCE3 1.005583 300 KOhm 2W/4W0C 999995 0552D 1.005517 3 MOhm 2W/4W0D 999998 1DDE2 1.006682 30 MOhm 2W/4W0E 999935 1D31C 1.007306 300 mA DC0F 999989 1DEE4 1.006784 3A DC10 000000 00000 1.000000 (Not used)11 997436 1C341 1.006341 300 mA/3A AC12 000000 00000 1.000000 (Not used)entry 0x00: OK (30 mV DC)entry 0x01: OK (300 mV DC)entry 0x02: OK (3 V DC)entry 0x03: OK (30 V DC)entry 0x04: OK (300 V DC)entry 0x05 ((Not used)): bad cks (0x00) (unused entry)entry 0x06: OK (ACV)entry 0x07: OK (30 Ohm 2W/4W)entry 0x08: OK (300 Ohm 2W/4W)entry 0x09: OK (3 KOhm 2W/4W)entry 0x0A: OK (30 KOhm 2W/4W)entry 0x0B: OK (300 KOhm 2W/4W)entry 0x0C: OK (3 MOhm 2W/4W)entry 0x0D: OK (30 MOhm 2W/4W)entry 0x0E: OK (300 mA DC)entry 0x0F: OK (3A DC)entry 0x10 ((Not used)): bad cks (0x00) (unused entry)entry 0x11: OK (300 mA/3A AC)entry 0x12 ((Not used)): bad cks (0x08) (unused entry)There seems to be two 'regimes' for the gains, one for the voltage readings and the other for everything else.Does this imply that there may be something wrong with the current sense part of the meter, given that it's so far off cal?

author: m k
author_rank: Super Contributor
timestamp: March 23, 2024, 07:44:35 am
content: Much better cal set.Drain a battery and select a level where both meters remain in one range.Then you can forget absolute values and concentrate to change.

author: pqass
author_rank: Super Contributor
timestamp: March 23, 2024, 03:04:33 pm
content: Quote from: radar_macgyver on March 23, 2024, 04:58:35 amGood to see all the records pass now.DCI and ACI just add a shunt and a three-stage amplifier+RMS converter in front of the ADC. See theservice guideschematic 1,2,3; pages 147,149, 152. So if the DCV parts are fine then all I can think of is that someone over-amp'd it and changed the 0R1 shunt ever so slightly? I'd check the fuse to confirm it's 3A.Consider this an opportunity to re-cal just the DCI and ACI records. See 4-61 DC Current Calibration (page 45) and 4-72 AC Current Calibration (page 46) in the service manual (link above). The procedures require a calibrator but I'd just use a resistor+power supply then series connect with the 3478A and DMM6500. You'll need to provide a 100mA and 1A current sources (100R and 10R @10V). However, for the ACI, you'll need a 300mA 1KHz source; maybe a function generator+amplifier? The great thing about this meter is that the source doesn't have to be precise since you can [inc|dec]rease the display value to match the DMM6500 reading; it figures out the cal entry from that.Note: crc=ff means record passes validation.Code:$ ./verify.sh radar2.cal000001 40 40 40 42 42 45 42 45 4f 43 4f 4c 4e >@@@BBEBEOCOLN<00: raw_offset=000225 raw_gain=25f3f offset=+000149 gain=1.024929 crc=ff 30 mV DC00000e 40 40 40 40 41 42 42 44 45 41 45 4e 4b >@@@@ABBDEAENK<01: raw_offset=000012 raw_gain=24515 offset=+000010 gain=1.024515 crc=ff 300 mV DC00001b 40 40 40 40 40 42 42 44 42 41 4c 4e 48 >@@@@@BBDBALNH<02: raw_offset=000002 raw_gain=2421c offset=+000002 gain=1.024206 crc=ff 3 V DC000028 49 49 49 49 49 41 42 45 4d 43 42 4b 48 >IIIIIABEMCBKH<03: raw_offset=999991 raw_gain=25d32 offset=-000009 gain=1.024732 crc=ff 30 V DC000035 40 40 40 40 40 40 42 44 44 41 44 4f 40 >@@@@@@BDDADO@<04: raw_offset=000000 raw_gain=24414 offset=+000000 gain=1.024414 crc=ff 300 V DC000042 40 40 40 40 40 40 40 40 40 40 40 40 40 >@@@@@@@@@@@@@<05: raw_offset=000000 raw_gain=00000 offset=+000000 gain=1.000000 crc=00 <not used>00004f 49 49 47 44 43 46 42 44 41 4c 45 4c 41 >IIGDCFBDALELA<06: raw_offset=997436 raw_gain=241c5 offset=-002564 gain=1.024065 crc=ff AC V00005c 49 49 49 44 42 47 41 4c 45 4c 42 4b 47 >IIIDBGALELBKG<07: raw_offset=999427 raw_gain=1c5c2 offset=-000573 gain=1.006462 crc=ff 30 Ohm 2W/4W000069 49 49 49 49 48 46 41 4c 4c 42 41 4b 41 >IIIIHFALLBAKA<08: raw_offset=999986 raw_gain=1cc21 offset=-000014 gain=1.005621 crc=ff 300 Ohm 2W/4W000076 49 49 49 49 49 45 40 45 43 42 45 4b 4e >IIIIIE@ECBEKN<09: raw_offset=999995 raw_gain=05325 offset=-000005 gain=1.005325 crc=ff 3 kOhm 2W/4W000083 40 40 40 40 41 46 40 45 45 42 4f 4d 4d >@@@@AF@EEBOMM<10: raw_offset=000016 raw_gain=0552f offset=+000014 gain=1.005519 crc=ff 30 kOhm 2W/4W000090 49 49 49 49 49 47 41 4c 4c 4e 43 4a 41 >IIIIIGALLNCJA<11: raw_offset=999997 raw_gain=1cce3 offset=-000003 gain=1.005583 crc=ff 300 kOhm 2W/4W00009d 49 49 49 49 49 45 40 45 45 42 4d 4b 44 >IIIIIE@EEBMKD<12: raw_offset=999995 raw_gain=0552d offset=-000005 gain=1.005517 crc=ff 3 MOhm 2W/4W0000aa 49 49 49 49 49 48 41 4d 4d 4e 42 49 4f >IIIIIHAMMNBIO<13: raw_offset=999998 raw_gain=1dde2 offset=-000002 gain=1.006682 crc=ff 30 MOhm 2W/4W0000b7 49 49 49 49 43 45 41 4d 43 41 4c 4b 45 >IIIICEAMCALKE<14: raw_offset=999935 raw_gain=1d31c offset=-000065 gain=1.007306 crc=ff 300 mA DC0000c4 49 49 49 49 48 49 41 4d 4e 4e 44 49 4c >IIIIHIAMNNDIL<15: raw_offset=999989 raw_gain=1dee4 offset=-000011 gain=1.006784 crc=ff 3A DC0000d1 40 40 40 40 40 40 40 40 40 40 40 40 40 >@@@@@@@@@@@@@<16: raw_offset=000000 raw_gain=00000 offset=+000000 gain=1.000000 crc=00 <not used>0000de 49 49 47 44 43 46 41 4c 43 44 41 4c 44 >IIGDCFALCDALD<17: raw_offset=997436 raw_gain=1c341 offset=-002564 gain=1.006341 crc=ff 300 mA/3A AC0000eb 40 40 40 40 40 40 40 40 40 40 40 40 48 >@@@@@@@@@@@@H<18: raw_offset=000000 raw_gain=00000 offset=+000000 gain=1.000000 crc=08 <not used>0000f8 40 40 40 40 40 40 40 40 >@@@@@@@@<19: <padding>

author: Dan N
author_rank: Contributor
timestamp: April 02, 2024, 04:28:28 am
content: Quote from: pqass on March 21, 2024, 05:27:47 amVery clever script.I noticed the leading 0 in some positive offsets causes strtonum to interpret it as octal, for example:Code:raw_offset=000611 offset=+000393Adding a leading "+" to the string at conversion forces decimal interpretation:Code:Change:coset = strtonum(oset);if (strtonum(oset)>499999) coset -= 1000000;to:coset = strtonum("+" oset);if (coset>499999) coset -= 1000000;

author: pqass
author_rank: Super Contributor
timestamp: April 02, 2024, 02:16:38 pm
content: Thank you Dan N!See latest version below (remove the .txt ending).I've taken the opportunity to clean it up, add error checks, and better comments.

author: radar_macgyver
author_rank: Frequent Contributor
timestamp: April 15, 2024, 04:48:50 am
content: I replaced the battery on my 3478A prototype without losing the existing cal. After that, I figured I will try to cal the DCI ranges per the instructions in the service manual, but I found that I was unable to switch the instrument into cal mode even though I moved the front panel cal enable switch to the vertical position. I wanted to test if the signal was making it to the main board (in case there was a bad wiper), and found that the board is somewhat different from the one shown in the service manual. I don't have a U515 anywhere on the board, this is the dual 4-input NAND gate used to gate the WR signal to the CMOS RAM.It almost looks like the switch is simply not connected to anything on the main board - probing the wiper while turning the switch between its two positions does not change the voltages on either terminal of the switch.Pin 9Maybe they hadn't implemented the self-calibration routine in the prototype.How does the firmware know what position the cal enable switch is in (in the non-prototype version)? It seems like S550 enables the microprocessor's WR signal to get connected to U512's R/W pin. Without any direct connection to the switch input, how does the micro know that U512 is not write-enabled and put up the "ENABLE CAL" message?Edit: removed an incomplete sentence

author: pqass
author_rank: Super Contributor
timestamp: April 15, 2024, 06:13:31 am
content: Quote from: radar_macgyver on April 15, 2024, 04:48:50 amU515 should be just behind the LCD and in front of the red relays. See attached photo.I think it was mentioned earlier in this thread that the meter tries to periodically write alternating values into location 0 of the cal ram. If a new value is written and it sticks, then it's in cal enable mode. Note, you must be aligned perfectly vertical in the detent; a couple of degrees either way won't close the switch.

author: m k
author_rank: Super Contributor
timestamp: April 15, 2024, 09:48:12 am
content: TP6 is write, active low, cal switch is letting it through.You can scope RAM pin 20, it goes low for write.Middle of manual Sep-87 ed. 2 E0987 has another set of schematics.There figure 6-5 cal uses C and D parts of regular two input NOR U515.Table 6-10 replaces 7420 to 7402.

author: radar_macgyver
author_rank: Frequent Contributor
timestamp: April 15, 2024, 01:23:38 pm
content: See below for a pic of my meter's front end - U515 is not at the location indicated by the assembly drawing in the service guide. Another thing that I had started to type up but forgot to finish is that the schematic indicates pin 9 from the front panel board carries the Cal Enable signal. On my board, this pin is grounded. In the attached picture, you can see the trace from the front panel connection is a thicker one, that connects to the ground plane.I think I just have the older rev board, referenced by the schematic figure 6-5 that m k mentioned above. The difference is that while that schematic shows the two-input NOR gates as U515, on my board this is labeled U508 (part number is 74LS02). Interestingly, the theory of operation section 7-F-63 specifies U508 as the device that drives the CMOS RAM's R/W pin. They must not have updated the text after the schematic change.It also turns out the plastic tab that holds the cal enable switch wiper was very brittle and a piece of it broke off while I was probing the wiper so it probably wasn't making good contact. I soldered a small jumper between pin 10 of the front panel cable. When grounded, the display shows an extra 'C' indicating cal mode.I attempted a calibration of the DCI 300 mA range and while the zero cal worked, the 1/3 scale cal gave a 'value error'. I measured the shunt resistor R107 using the 4-wire mode on my DMM6500 and it showed 0.098 ohm, so about a 2% error. This should not result in the nearly 25% error observed in the readings. The fuse installed is rated 2A.Just for fun I tried running the cal procedure again and it worked. Not clear why it failed the first time around - maybe because the initial error was so large? Repeated this in DCI 3A and all seems well. I verified the results with my DMMcheck and readings were within 0.001 mA.The service manual seems to indicate that a separate cal for the AC current is not required since the cal values for AC current are derived from DC current, though mine still showed the same ~25% error it used to. Will attempt an ACI cal, but I need to borrow some equipment from work. Thanks all for the help with this!

author: m k
author_rank: Super Contributor
timestamp: April 15, 2024, 03:24:21 pm
content: Figure 7-G-5 (03478-66501) is the older schematics.Figure 6-5 (C3478-66501) is the newer one, with 7402.So your machine has a newer configuration.What kind of U502 you have?Section 6-25 says that revision D changes it to 28 pin chip.

author: dietert1
author_rank: Super Contributor
timestamp: April 16, 2024, 11:47:12 am
content: Just managed to save the calibration of our HP 3478A. Thanks to all who contributed!Code:HP 3478A calibration datacadt.de 2024-04-16calO0@@@ACC A@LDM MJ25500013310C4D1331.096371@@@@AD AOALN LO2550000141F1CE141.090582@@@@@B AO@BO ML2550000021F02F21.090193IIIIIC AOMMN IG2559999931FDDE-71.086684IIIIII AONAD JF2559999991FE14-11.088145@@@@@@ @@@@@ @@00000000000001.000006IIIAIB AO@OC KF2559991921F0F3-8081.089937IIIBAH ANDL@ KJ2559992181E4C0-7821.083608IIICBE AMCBB LE2559993251D322-6751.073229IIIIC@ AMDLD KF2559999301D4C4-701.0736410IIIIIC AMOMM IH2559999931DFDD-71.0686711@@@@@@ ALMEN MB2550000001CD5E01.0574812@@@@@@ AMLEL MD2550000001DC5C01.0664613@@@@@@ AMNOE LO2550000001DEF501.0679514IIIHCD BMMML J@2559998342DDDC-1661.1666615IIIIHD BLMND JB2559999842CDE4-161.1568416@@@@@@ @@@@@ @@00000000000001.0000017IIIAIB AO@OC KF2559991921F0F3-8081.0899318@@@@@@ @@@@@ @@00000000000001.00000cal[248..]@@@@@@@@Regards, Dieter

author: radar_macgyver
author_rank: Frequent Contributor
timestamp: April 16, 2024, 12:35:31 pm
content: Quote from: m k on April 15, 2024, 03:24:21 pmGot it - however, the documentation is still a bit confusing since the schematics show the NOR gates as U515, while the text(and my board) references U508. In the schematic, U508 is a hex inverter.Quote from: m k on April 15, 2024, 03:24:21 pmMine is a 20-pin DIP.

author: m k
author_rank: Super Contributor
timestamp: April 16, 2024, 04:06:39 pm
content: Seems that your board is at least partially renumbered.Few pictures would be nice.Earlier U502 is a ROM chip, maybe it's missing.Older versions had two MCUs, there analog side has already embedded its code.Maybe your version has digital side code embedded also.Your earlier picture has a chip above C512 and U507 is originally placed.So I'm assuming your board still has both MCUs.

author: radar_macgyver
author_rank: Frequent Contributor
timestamp: April 17, 2024, 05:39:28 am
content: My bad - I thought you were asking about the cal RAM - the program ROM is a 24 pin ceramic DIP, no window and no label. Please see attached image of the board. The battery used is a new one I installed a few days ago, it's a half-AA Lithium cell.

author: m k
author_rank: Super Contributor
timestamp: April 17, 2024, 04:03:30 pm
content: Yes, documentation is still more than a bit confusing.I've seen rev C with 28 pin ROM and your machine has 7402 for cal.Maybe 7402 was also the original design.Normally board info is under rear inputs.

author: TaylorD93
author_rank: Regular Contributor
timestamp: September 07, 2024, 12:24:58 pm
content: Just wanted to say thank you to all the work you guys have done, ive been able to backup my SRAM data via the GPIBO@@@CHABCLOCM@@@@@CFBBEOLMB@@@@@DBBEMBNCIIIIICBB@LDKKIIIIIIBBODCJO@@@@@@@@@@@OO@@@CEGBAODLLNIIIIHBAL@DEKKIIIIIHALONCIM@@@@@@ALOLEMBIIIIII@EDN@KBIIIIII@EDC@KM@@@@@@@EDE@OAIIIIII@EAMBKD@@@BBBCEN@@NC@@@@BCCELLOLK@@@@@@@@@@@OO@@@CEGCC@O@MK@@@@@@@@@@@OO@@@@@@@@Now i just need to work out how the data is split up to complete the checksum.

author: pqass
author_rank: Super Contributor
timestamp: September 07, 2024, 12:49:48 pm
content: You're good. All records have valid checksums.See my verify.sh (Linux) scripthere.It produces the following output with your cal data.Code:$ ./verify.sh TaylorD93.cal000001 40 40 40 43 48 41 42 43 4c 4f 43 4d 40 >@@@CHABCLOCM@<00: raw_offset=000381 raw_gain=23cf3 offset=+000381 gain=1.022593 cksum=ff (pass) 30 mV DC00000e 40 40 40 40 43 46 42 42 45 4f 4c 4d 42 >@@@@CFBBEOLMB<01: raw_offset=000036 raw_gain=225fc offset=+000036 gain=1.022486 cksum=ff (pass) 300 mV DC00001b 40 40 40 40 40 44 42 42 45 4d 42 4e 43 >@@@@@DBBEMBNC<02: raw_offset=000004 raw_gain=225d2 offset=+000004 gain=1.022472 cksum=ff (pass) 3 V DC000028 49 49 49 49 49 43 42 42 40 4c 44 4b 4b >IIIIICBB@LDKK<03: raw_offset=999993 raw_gain=220c4 offset=-000007 gain=1.021964 cksum=ff (pass) 30 V DC000035 49 49 49 49 49 49 42 42 4f 44 43 4a 4f >IIIIIIBBODCJO<04: raw_offset=999999 raw_gain=22f43 offset=-000001 gain=1.021943 cksum=ff (pass) 300 V DC000042 40 40 40 40 40 40 40 40 40 40 40 4f 4f >@@@@@@@@@@@OO<05: raw_offset=000000 raw_gain=00000 offset=+000000 gain=1.000000 cksum=ff (pass) <not used>00004f 40 40 40 43 45 47 42 41 4f 44 4c 4c 4e >@@@CEGBAODLLN<06: raw_offset=000357 raw_gain=21f4c offset=+000357 gain=1.020936 cksum=ff (pass) AC V00005c 49 49 49 49 48 42 41 4c 40 44 45 4b 4b >IIIIHBAL@DEKK<07: raw_offset=999982 raw_gain=1c045 offset=-000018 gain=1.006045 cksum=ff (pass) 30 Ohm 2W/4W000069 49 49 49 49 49 48 41 4c 4f 4e 43 49 4d >IIIIIHALONCIM<08: raw_offset=999998 raw_gain=1cfe3 offset=-000002 gain=1.005883 cksum=ff (pass) 300 Ohm 2W/4W000076 40 40 40 40 40 40 41 4c 4f 4c 45 4d 42 >@@@@@@ALOLEMB<09: raw_offset=000000 raw_gain=1cfc5 offset=+000000 gain=1.005865 cksum=ff (pass) 3 kOhm 2W/4W000083 49 49 49 49 49 49 40 45 44 4e 40 4b 42 >IIIIII@EDN@KB<10: raw_offset=999999 raw_gain=054e0 offset=-000001 gain=1.005380 cksum=ff (pass) 30 kOhm 2W/4W000090 49 49 49 49 49 49 40 45 44 43 40 4b 4d >IIIIII@EDC@KM<11: raw_offset=999999 raw_gain=05430 offset=-000001 gain=1.005430 cksum=ff (pass) 300 kOhm 2W/4W00009d 40 40 40 40 40 40 40 45 44 45 40 4f 41 >@@@@@@@EDE@OA<12: raw_offset=000000 raw_gain=05450 offset=+000000 gain=1.005450 cksum=ff (pass) 3 MOhm 2W/4W0000aa 49 49 49 49 49 49 40 45 41 4d 42 4b 44 >IIIIII@EAMBKD<13: raw_offset=999999 raw_gain=051d2 offset=-000001 gain=1.005072 cksum=ff (pass) 30 MOhm 2W/4W0000b7 40 40 40 42 42 42 43 45 4e 40 40 4e 43 >@@@BBBCEN@@NC<14: raw_offset=000222 raw_gain=35e00 offset=+000222 gain=1.034800 cksum=ff (pass) 300 mA DC0000c4 40 40 40 40 42 43 43 45 4c 4c 4f 4c 4b >@@@@BCCELLOLK<15: raw_offset=000023 raw_gain=35ccf offset=+000023 gain=1.034559 cksum=ff (pass) 3A DC0000d1 40 40 40 40 40 40 40 40 40 40 40 4f 4f >@@@@@@@@@@@OO<16: raw_offset=000000 raw_gain=00000 offset=+000000 gain=1.000000 cksum=ff (pass) <not used>0000de 40 40 40 43 45 47 43 43 40 4f 40 4d 4b >@@@CEGCC@O@MK<17: raw_offset=000357 raw_gain=330f0 offset=+000357 gain=1.032990 cksum=ff (pass) 300 mA/3A AC0000eb 40 40 40 40 40 40 40 40 40 40 40 4f 4f >@@@@@@@@@@@OO<18: raw_offset=000000 raw_gain=00000 offset=+000000 gain=1.000000 cksum=ff (pass) <not used>0000f8 40 40 40 40 40 40 40 40 >@@@@@@@@<19: <padding>

author: TaylorD93
author_rank: Regular Contributor
timestamp: September 07, 2024, 12:56:17 pm
content: thanks!One question i do have, the first line of my data started with O@@@ but i see the export from you script has removed that first character.Why was the first character removed? how did you know?

author: pqass
author_rank: Super Contributor
timestamp: September 07, 2024, 01:44:42 pm
content: Quote from: TaylorD93 on September 07, 2024, 12:56:17 pmThe 13 byte cal records begin on the 2nd byte.The 1st byte is used to detect if the (front panel) cal switch is in the write position.The cal switch enables/disables the /WR line to the cal RAM so if the meter can change the 1st byte then the cal switch is in "calibrate" mode.