I'm trying to interface an AD7321 ADC with the Arduino Uno/Mega or Raspberry Pi for data acquisition of signals from my breadboard to computer.
I am able to communicate with the ADC through SPI with an Arduino Uno by sending the required 16 initialization bits, however the output of the ADC does not correctly represent the analog value when observed with an oscilloscope.
The image below is a snippet from the datasheet of the expected I/O for the SPI pins.
Since this is a 13bit (12+sign) ADC, I would expect a digital range from 0-4096 excluding the sign, however the images attached show otherwise.
This is a graph showing the ADC output at 5V DC.
This is a graph showing the ADC output at 0V DC.
The 2 return bytes given by the ADC in 0V DC graph
00001100 00010100 (Flat line) Which is when converted into decimal is 3092.
From the first image of the datasheet, the first 3 bits can be ignored when finding the absolute value of the desired signal.
I am trying to use this ADC to sample my signal (+-10V) at 100ksps which this ADC is capable of, however I cannot get an accurate reading from it.
Could someone who is more familiar with the AD732x chip shed some light on the behaviour of this chip?
EDIT: Thanks for the comments, I have amended the post to ensure the information is available.
This is the schematic, there are a few decoupling capacitors from Vdrive/Vcc to ground and both analog and digital grounds are connected at a star junction to reduce wire inductance noise.
The graphs above have Vdd = 5V and Vss = 0V, however I have also tried Vdd = 10V, 7V and Vss = -10V, -7V and -5V, but encounter the same issues.
In terms of code I have attached them below. The initial bits sent to the ADC are currently configured to read at +-5V single ended mode, no sequencing, binary code from channel 0.
#include <SPI.h>
#define CS_PIN 10 //Pin 10 defined as the CS Pin.
void setup()
{
Serial.begin(115200); //Initalise port to print in serial terminal
pinMode(CS_PIN,OUTPUT); //Pin 10 as CS
digitalWrite(CS_PIN,HIGH);
SPI.begin(); //Intialise SPI PORT
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV4);
initialise();
}
void loop()
{
uint16_t adcOut;
float value;
initialise();
adcOut = readADC(0);
adcOut = (adcOut<<3); // Bitshift to take last 13bits
value = (adcOut>>3);
Serial.println(value);
delayMicroseconds(1); //Delay
}
uint16_t readADC(int channel)
{
uint16_t output;
digitalWrite(CS_PIN,LOW);
byte msb = SPI.transfer(0x00);
byte lsb = SPI.transfer(0x00);
digitalWrite(CS_PIN,HIGH); // Deselect slave by pulling CS_PIN HIGH.
output = (msb << 8 | lsb); //Combine MSB with LSB to form the 16 Bit Analog read Value.
return output; //Output Value
}
void initialise()
{
digitalWrite(CS_PIN, LOW); //Select the connected chip by pulling CS_PIN LOW.
SPI.transfer(0b10111001); //Defines range register -> | Write (1) | 0 | Register Select (1) | Vin0A | Vin0B | 0 | 0 | Vin1A |
SPI.transfer(0b10000000); // | Vin1B | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
digitalWrite(CS_PIN, HIGH);
delayMicroseconds(1);
digitalWrite(CS_PIN, LOW);
SPI.transfer(0b10000000); //Defines control register -> | Write (1) | 0 | Register Select (0) | 0 | 0 | ADD0 | Mode1 | Mode0 |
SPI.transfer(0b00110000); // | PM1 | PM0 | Coding | Ref | Seq1 | Seq2 | 0 | 0 |
digitalWrite(CS_PIN, HIGH);
delayMicroseconds(1);
}
delayMicroseconds(x)
after the slave (de)selection, to meet the minimum required dead timet2
/t1
as shown in the timing diagram. Consult the datasheet for suitable values ofx
. \$\endgroup\$