There has been some interest recently in interfacing directly with the SPA100 Source Picoammeter, in this series of posts I’ll explain how to do it.
Nearly all Electron+ instruments connect via USB to a Windows based PC. Instruments send up fairly raw data as well as calibration co-efficients (more on this later), EPIC then utilises the host computer processing power to turn this raw data into calibrated data and present this to the end-user via EPIC.
This approach allows us to reduce the processing power and complexity of the instrument, reduce the size of the firmware (reducing risk of bugs!) and reduce the bandwidth of the USB datalink – this keeps the costs lower. However this does increase the complexity for 3rd parties interfacing to our instruments vs. a protocol like SCPI.
Calibration co-efficients
These are stored within the internal microcontroller FLASH as ‘just a bunch of numbers’, these are then drip-fed from the SPA100 to EPIC over several minutes, one 16-bit number per packet. EPIC stores these numbers into text file called “SPA_cal.txt” and uses this file to create the calibration co-efficients. This is why the first time an SPA100 is connected with EPIC it will take a few minutes to produce meaningful results. In the background, EPIC will perform a cross check of SPA100 co-efficients with the contents of “SPA_cal.txt” in-case there has been a calibration, or a different SPA100 has been connected.
To make it easier for anyone writing their own interface to an SPA100, we would suggest using the contents of “SPA_cal.txt” created by EPIC rather than working out how to download this data from SPA100, the same goes for calibrating an SPA100.
Communications
The SPA100 uses a serial<>USB bridge IC internally, this is a CH340C, made by WCH. Drivers are on our website in the software section.
Communications is 115,000 baud, 8N1.Data sent from the PC>SPA100 is always in 8byte packets.
A packet of data consists of 8 bytes (& their attendant start/stop bits).
There is to be no space between the stop bit of one byte and the start bit of the next.
START | Bit 0 | Bit 1 | Bit 2 | Bit 3 | Bit 4 | Bit 5 | Bit 6 | Bit 7 | STOP |
0 | A8 | A9 | A10 | A11 | A12 | A13 | A14 | 1 | 1 |
0 | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | 1 |
0 | D24 | D25 | D26 | D27 | D28 | D29 | D30 | D31 | 1 |
0 | D16 | D17 | D18 | D19 | D20 | D21 | D22 | D23 | 1 |
0 | D8 | D9 | D10 | D11 | D12 | D13 | D14 | D15 | 1 |
0 | D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 | 1 |
0 | CS8 | CS9 | CS10 | CS11 | CS12 | CS13 | CS14 | CS15 | 1 |
0 | CS0 | CS1 | CS2 | CS3 | CS4 | CS5 | CS6 | CS7 | 1 |
A14-A0 (“ADDRESS, 15 bits): the start address of the data to be written or read
D31-D0 (“DATA”, 32 bits): this is either just the data.
CS15-CS0 (“CHECKSUM”, 16 bits): created by adding the three pairs of 16bits and 0x5555.
The SPA100 actively uses ten 32 bit sized registers to control it’s operation, there is no special requirement to write them in, or requirement on how many locations need be written – EPIC tends to write 0x001F to 0x0000 (32 locations, 256 bytes) in ‘one hit’.
Address | R/W? | Name | Units | Values |
0x0000 | W | Status | – | – |
0x0001 | W | Main Control Register b0-12=unused b12=disable STATUS LED (0=LED enabled, 1=LED disabled) b13=reset CAL sync marker data (0=no reset, 1=reset) b14=erase all calibration FLASH (0x001E must be 0xAA55) b15=write data back to calibration FLASH b16=transmit enable (0=suppress TX, 1=allow TX) b17-31=unused |
Arbitrary | 32bits |
0x0002 | W | Timebase (@100KHz) e.g. 50000=2Hz, 10000=10Hz | Arbitrary | 16bits unsigned |
0x0003 | W | Input Relay Range (0,1,2,3) | Arbitrary | 32bits unsigned |
0x0004 | W | PGA Gain (e.g. 1,2,4,8) | Arbitrary | 16bits unsigned |
0x0005 | W | Resolution (e.g.16, 18) | Arbitrary | 16bits unsigned |
0x0006 | W | Zero/Short Input Relay (0=off, 1=on/short) | Arbitrary | 16bits unsigned |
0x0007 | W | PWM output level (0-65535) | Arbitrary | 16bits unsigned |
0x0008 | W | Arbitrary | 16bits unsigned | |
0x0009 | W | Arbitrary | 16bits unsigned | |
0x000A | W | Arbitrary | 16bits unsigned | |
0x000B | W | Arbitrary | 16bits unsigned | |
0x000C | W | Arbitrary | 16bits unsigned | |
0x000D | W | Arbitrary | 16bits unsigned | |
0x000E | W | Arbitrary | 16bits unsigned | |
0x000F | W | Arbitrary | 16bits unsigned | |
0x0010 | W | Arbitrary | 16bits unsigned | |
0x0011 | W | Arbitrary | 16bits unsigned | |
0x0012 | W | Arbitrary | 16bits unsigned | |
0x0013 | W | Arbitrary | 16bits unsigned | |
0x0014 | W | Arbitrary | 16bits unsigned | |
0x0015 | W | Arbitrary | 16bits unsigned | |
0x0016 | W | Arbitrary | 16bits unsigned | |
0x0017 | W | Arbitrary | 16bits unsigned | |
0x0018 | W | Arbitrary | 16bits unsigned | |
0x0019 | W | Arbitrary | 16bits unsigned | |
0x001A | W | Arbitrary | 16bits unsigned | |
0x001B | W | Arbitrary | 16bits unsigned | |
0x001C | W | Arbitrary | 16bits unsigned | |
0x001D | W | Arbitrary | 16bits unsigned | |
0x001E | W | Calibration FLASH ADDRESS (CAL FLASH location to write) | Arbitrary | 16bits unsigned |
0x001F | W | Calibration FLASH DATA (for writing to CAL FLASH) | Arbitrary | 32bits unsigned |
A ‘keep alive’ message is sent every 250ms (4Hz) to the SPA100. This consists of 8 bytes and looks like this:
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55
If no message is received by the SPA100 (keep alive or general) for a couple of seconds, it will assume the USB link is broken and enter a ‘safe’ mode.
In Part 2, I’ll discuss SPA100>PC packet structure.