Several SPA100 customers have had issues 'getting to blinky' (in this case, getting a packet of data out of the SPA100) with their own software - In most cases this has been down to the way their outgoing packet has been setup and the way the outgoing checksum has been calculated.
Protocol (lifted straight from our internal document EPP1.08) - E&OE!
---------------------------------
PC>INSTRUMENT (mid level protocol structure/packets)
A packet of data consists of 8 bytes (& there attendant start/stop bits). There is to be no space between the stop bit of one byte and the start bit of the next.
Write (single location only)
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.
Read (single location only)
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 |
0 |
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.
DATA TYPE
115.2 kbps, 8N1, using a CH340C.
SPA (PC>INSTRUMENT)
An 8 byte packet of data is sent from the PC up to the instrument. This is formatted thus:
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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
SPA (INSTRUMENT>PC)
An 16 byte packet of data is sent from the INSTRUMENT to the PC. This is formatted thus:
Data returned:
2 bytes – STATUS (only 2 bits used, 14 bits reserved for future use)
2 bytes - USB voltage (12 bits) / Calibration Data (16 bits)
3 bytes - 1x 24bit current value of ADC’s
8 bytes – reserved for future use
1 byte - Checksum!
Total of 16 bytes.
Byte |
Function |
0 |
Device Status (MSB) |
1 |
Device Status (LSB) |
2 |
USB voltage (MSB) / Calibration Data (MSB) |
3 |
USB voltage (LSB) / Calibration Data (LSB) |
4 |
Reserved for future use |
5 |
Reserved for future use |
6 |
ADC raw current (MSB, b23-b16) |
7 |
ADC raw current (CSB, b15-b8) |
8 |
ADC raw current (LSB, b7-b0) |
9 |
Reserved for future use |
10 |
Reserved for future use |
11 |
Reserved for future use |
12 |
Reserved for future use |
13 |
Reserved for future use |
14 |
Reserved for future use |
15 |
Checksum |
Device Status
bits 0 to 11=unused
bit 12=USB/CAL status (0=USB voltage, 1=calibration DATA)
bit 13=CAL data start packet marker (0=no marker, 1=initial byte)
bits 14,15=unused
Notes
USB voltage is not implemented on the SPA100
ADC raw current is a signed value
Calibration data
When b13 of the status packet =1 signals the 0th word (word is 2 bytes) of the calibration data.
Word 0= DAC value at +40V source output
Word 1= DAC value at -40V source output
Word 2,3= unused
Word 4,5= Range 1+ ADC raw value (32 bit signed), known as “adcpos”
Word 6,7= Range 1- ADC raw value (32 bit signed), known as “adcneg”
Word 8-11= Range 1+ Calibration current value (64 bit float [double]), known as “ipos”
Word 12-15= Range 1- Calibration current value (64 bit float [double]), known as “ineg”
….
Word 88,89= Range 8+ ADC raw value (32 bit signed [long])
Word 90,91= Range 8- ADC raw value (32 bit signed [long])
Word 92-95= Range 8+ Calibration current value (64 bit float [double])
Word 96-99= Range 8- Calibration current value (64 bit float [double])
Scale and Offset for each range is calculated in EPIC/SPA software using the ADC raw value and calibration values.
Scale= (ipos - ineg) / (adcpos - adcneg)
Offset= ineg – (adcneg * Scale)
So to calculate the actual current (for a given range):
Current= (ADC * Scale) + Offset
---------------------------------
Below are some examples of messages you can send to the SPA100, you should use them to compare against the output from your own code:
80 01 (address 0001h)
00 01 (bits 31-16) - bit 16 set, transmission enabled
00 01 (bits 31-16) - bit 16 set, transmission enabled
00 01 (bits 31-16) - bit 16 set, transmission enabled
Note: As described in the protocol, the checksum is the 16 bit addition of the "address", "data31-16", "data15-0", "0x5555" words. If you are doing the calculation using 32 bit maths, probably wise to AND the final checksum result with 0x0000FFFF to mask off any carry forward in values in bits 16 & 17 of the result. Essentially:
Checksum = (Word1 + Word2 + Word3 + 0x5555) & 0xFFFF
If you don't want to write code that will slowly download and then reassemble the calibration data (it's fairly tedious). Then you can use the function built into the SPA PC software (v25.001 onwards) to translate the calibration file into more human readable values.
This function is found in SPA25.002 menu - UTILITIES>DEVELOPMENT ONLY>TRANSLATE CALIBRATION FILE.
An example of the translated output is shown below:
"
translated from: C:\Program Files\Electron Plus\SPA\SPA_cal.txt
DAC+40V: 5956
DAC-40V: 367
unused: 0
unused: 0
ADC Range1+: -8144915
ADC Range1-: 8212096
Calibrated Current for Range1+: 0.002007760000000 A, 2.008 mA, 2007.760 uA, 2007760.000 nA, 2007760000.000 pA
Calibrated Current for Range1-: -0.002007090000000 A, -2.007 mA, -2007.090 uA, -2007090.000 nA, -2007090000.000 pA
ADC Range2+: -6248922
ADC Range2-: 6312186
Calibrated Current for Range2+: 0.000200642050000 A, 0.201 mA, 200.642 uA, 200642.050 nA, 200642050.000 pA
Calibrated Current for Range2-: -0.000200642050000 A, -0.201 mA, -200.642 uA, -200642.050 nA, -200642050.000 pA
ADC Range3+: -8126029
ADC Range3-: 8133363
Calibrated Current for Range3+: 0.000020015000000 A, 0.020 mA, 20.015 uA, 20015.000 nA, 20015000.000 pA
Calibrated Current for Range3-: -0.000020016000000 A, -0.020 mA, -20.016 uA, -20016.000 nA, -20016000.000 pA
ADC Range4+: -6236378
ADC Range4-: 6298176
Calibrated Current for Range4+: 0.000002000400000 A, 0.002 mA, 2.000 uA, 2000.400 nA, 2000400.000 pA
Calibrated Current for Range4-: -0.000002000400000 A, -0.002 mA, -2.000 uA, -2000.400 nA, -2000400.000 pA
ADC Range5+: -7999750
ADC Range5-: 8083571
Calibrated Current for Range5+: 0.000000199739950 A, 0.000 mA, 0.200 uA, 199.740 nA, 199739.950 pA
Calibrated Current for Range5-: -0.000000200340070 A, -0.000 mA, -0.200 uA, -200.340 nA, -200340.070 pA
ADC Range6+: -6155968
ADC Range6-: 6211360
Calibrated Current for Range6+: 0.000000019957120 A, 0.000 mA, 0.020 uA, 19.957 nA, 19957.120 pA
Calibrated Current for Range6-: -0.000000019958110 A, -0.000 mA, -0.020 uA, -19.958 nA, -19958.110 pA
ADC Range7+: -8095859
ADC Range7-: 8108947
Calibrated Current for Range7+: 0.000000001994610 A, 0.000 mA, 0.002 uA, 1.995 nA, 1994.610 pA
Calibrated Current for Range7-: -0.000000001994610 A, -0.000 mA, -0.002 uA, -1.995 nA, -1994.610 pA
ADC Range8+: -6193651
ADC Range8-: 6305562
Calibrated Current for Range8+: 0.000000000199162 A, 0.000 mA, 0.000 uA, 0.199 nA, 199.162 pA
Calibrated Current for Range8-: -0.000000000199661 A, -0.000 mA, -0.000 uA, -0.200 nA, -199.661 pA
"
For the purpose's of generating "Scale" and "Offset" values for each range (see earlier in this post):
"ipos" would be ADC RangeX+
"ineg" would be ADC RangeX-
"adcpos" would be Calibrated Current for RangeX+
"adcneg" would be Calibrated Current for RangeX-
Each range has it's own calibration coefficients, i.e. replace the X with 1,2,3,etc.. Be sure to use SI units, i.e. -199.661pA would be -0.000000000199661 or -1.99661E-10. We use SI units and double precession floating point math in all our PC software.
The 8 ranges are achieved using 4 relay settings and 2 gain settings in the ADC, the two speeds (2H/10Hz) have different sample resolutions. Here is an excerpt of the SPA25.002 code base that defines those settings:
-----------------------------------
; set the samplerate
Select SPA_SampleRate
Case 2 : ALL_register($02)=50000 : ALL_register($05)=18 ; SPA_SampleDepth
Case 10 : ALL_register($02)=10000 : ALL_register($05)=16 ; SPA_SampleDepth
Case 100 : ALL_register($02)=1000 : ALL_register($05)=16 ; SPA_SampleDepth
Default : ALL_register($02)=50000 : ALL_register($05)=18 ; SPA_SampleDepth
EndSelect
; set the input relay ($03) and the PGA ($04) for the correct range
Select SPA_InputRange
Case 1 : ALL_register($03)=0 : ALL_register($04)=1 ; 1mA
Case 2 : ALL_register($03)=0 : ALL_register($04)=8 ; 100uA
Case 3 : ALL_register($03)=1 : ALL_register($04)=1 ; 10uA
Case 4 : ALL_register($03)=1 : ALL_register($04)=8 ; 1uA
Case 5 : ALL_register($03)=2 : ALL_register($04)=1 ; 100nA
Case 6 : ALL_register($03)=2 : ALL_register($04)=8 ; 10nA
Case 7 : ALL_register($03)=3 : ALL_register($04)=1 ; 1nA
Case 8 : ALL_register($03)=3 : ALL_register($04)=8 ; 100pA
Default : ALL_register($03)=3 : ALL_register($04)=1 ; 1nA - default, incase value is not set, this is safe.
EndSelect
-----------------------------------
Recalibrating an SPA100 is best done through SPA PC software. For that reason I won't describe the process of erasing the calibration coefficients and uploading new ones.
One final note, if you choose to use the incoming checksum, it is calculated using 8 bit (byte) addition of the preceding 15 bytes. We use this in our software to spot error'd communications and initiate a resynchronisation of the comms, it's very rare and somewhat of a hangover from my history of designing large RS485 networks of things back in the nineties.
-Ben