This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Issues operating ADS8326 with a high-level SPI library

Other Parts Discussed in Thread: TXB0104, ADS8326, LM358, REF5040, OPA365

OBJECTIVE

To measure DC voltage in a flexible, automated test rig for high voltage power supplies, with the system based on a Raspberry Pi or similar inexpensive single-board computer.

Software will be written in Python for maximum flexibility and use standard libraries - spidev for SPI communication.

CIRCUIT

I won't attach my schematic, as it's several sheets, and not very readable - was done with the sole intent of producing CAD output!

ADS8326 is powered from a 5V supply (LM2931 powered at 9V, with 100uF output capacitor,) and interfaced to the Raspberry Pi through a TXB0104 level translator.

The reference voltage for the ADS8326 is provided by a REF5040, which is feeds both channels of an LM358 (powered from 9V supply,) configured as voltage followers. One channel supplies the reference pin of the ADS8326, the other is provided as a reference voltage that can be connected to the ADC input for test and calibration purposes.

The input of the ADS8326 is buffered through an OPA365 (powered from 5V rail,) followed by a 10 Ohm resistor, and 1nF capacitor to ground.

PROBLEMS

I am having a little trouble getting my head around what I need to do with SPI communcations, as the datasheet only gives sketchy detail at a bit-bang level, whereas I am working with a very high-level library.

After reading through a few times, and a little experimentation, it appears that SPI mode 3 is required - CPOL = 1, CPHA = 1. (Otherwise what I get out appears to be total nonsense.)

Whilst I am getting data transferred, the only way I can get a sensible result out is when I ground the input. The value retrieved appears to correspond to the slight voltage offset of the buffer, as confirmed with a voltmeter.

I am unsure as to whether I am using the correct bits of the three received bytes to make up the value; the following code is how I am interpreting the timing diagram, but the results don't make a lot of sense.


CODE

This is the section of the Python code that retrieves and processes the data from the ADS8326. It appears to work - partially:

# Whole process takes 24 clock cycles = 3 bytes.
# The xfer2 method sends the given values, with CS
# being held low for the full duration. Values of zero
# are sent, just to get the clock cycles.

adcval = spi.xfer2([0x00, 0x00, 0x00])

# My understanding is that the first 6 bits
# received will be garbage, so the last 2 bits
# of the first byte in will be the 2 most
# significant bits of the MSB.
#
# So mask the first six bits out (probably
# unneccessary) and left shift by 6.
msbupper = adcval[0] & 0b00000011
msbupper <<= 6

# Remaining 6 bits of MSB are the upper 6
# of the second byte received. Mask and
# shift right by 2.
msblower = adcval[1] & 0b11111100
msblower >>= 2

# Bitwise-OR the previous two results to
# get our MSB, then shift the whole thing
# left by 8.
msb = msbupper | msblower
msb <<= 8

# Upper 2 bits of LSB come from lower 2
# bits of the second byte received - mask and shift
# as per how we got the upper part of the MSB.
lsbupper = adcval[1] & 0b00000011
lsbupper <<= 6

# Lower 6 bits of LSB are the upper 6 bits of
# the third byte received. Lowest 2 bits of third
# byte received treated as garbage. Mask, shift
# right by 2, bitwise-or with previous result
# to get LSB.
lsblower = adcval[2] & 0b11111100
lsblower >>= 2
lsb = lsbupper | lsblower

# Bitwise-OR MSB and LSB to get final value.
value = msb | lsb


So what do I actually get out of this?

Applying the test reference voltage to the input, I would expect to get very close to 0xFFFF out. Here's the output from my code:

CPOL = 1, CPHA = 1
Reference voltage defined as 4.096V
Bytes received: 0x03 0xEF 0xBE
msb: 64256
lsb: 239
Average of 1 samples at maximum 10000sps.
Proportional value 64495 LSBs (6.25e-05V)
Volts 4.0309375

The MSB is exactly 1024 short of what it should be, and I can't see how!

Connect a 1.5V dry cell (1.567V measured after the buffer, I see:

Bytes received: 0xF9 0xF3 0xE7
msb: 31744
lsb: 249
Average of 1 samples at maximum 10000sps.
Proportional value 31993 LSBs (6.25e-05V)
Volts 1.9995625

Measure again, everything comes back as zero - including bytes received. Disconnect and reconnect the cell, goes back to normal.

Now measure two cells in series - I get EXACTLY the same values back as when I connect to the reference voltage. Measure again, comes back as zero again.

I have checked and re-checked voltages on the VDD and REF pins of the ADC, and am totally stumped as to what is going on.

Ideas?