Post Go back to editing

AD7797 false read ADC value

Hi everyone,

I am working on AD7797, created a custom PCB with atmega328p chip(arduino uno) and also written firmware for this. I am able to communicate with AD7797 but while reading ADC value it false data. Same data repeats. Please help me i am attaching PCB schematic and arduino code. Kindly share some library or code for AD7797.

Regards

Suman

#include <SPI.h>    // include the SPI library:
#define cs 10
void setup()
{
  Serial.begin(9600);                    // initialize serial port
  pinMode(SCK, OUTPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(cs, OUTPUT);
  digitalWrite(cs, HIGH);

  SPI.begin();                           // wake up the SPI
  SPI.setDataMode(SPI_MODE3);            // datasheet p6-7
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV32);  // datasheet p6

  Serial.println("AD7797 Test");

  initAD7797();


}

void initAD7797()
{
  beginAD7797();
  resetAD7797(); //reset device
  delay(2);
  if (!(getID() % 2))
  {
    Serial.println("ID : AD7796");
  }
  else
  {
    Serial.println("ID : AD7797");
  }
  Serial.print("Configuration : "); Serial.println(readCFG(), BIN);
}

void beginAD7797() //must be mode3
{
  //SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA)|(1<<SPR0); //mode3, 1MHz
  SPCR = (1 << SPE) | (1 << MSTR) | (1 << CPOL) | (1 << CPHA); //mode3, 4MHz
}

void resetAD7797() //p14
{
  digitalWrite(cs, LOW); //reset IC by sending out 32b of 1s
  transferAD7797(0xFF);
  transferAD7797(0xFF);
  transferAD7797(0xFF);
  transferAD7797(0xFF);
  digitalWrite(cs, HIGH);
}

uint8_t getID() //WORKS!
{
  uint8_t output = 0;
  digitalWrite(cs, LOW);
  transferAD7797(0x60); //01100000 0x60
  output = transferAD7797(0x00);
  digitalWrite(cs, HIGH);
  return output;
}

//read value from ADC,
long readAD7797()
{
  long value = 0; //uint16_t byte1, byte2, byte3;

  //selectCH(ch);
  selectMode();

  while (readST() > 127); //wait until !RDY

  digitalWrite(cs, LOW);
  transferAD7797(0x58); //select DATA register (01011000)(0x58) //one read  try (01011100)(0x5C) for CREAD

  value = (transferAD7797(0x00) << 16) & 0xFF0000;
  value += (transferAD7797(0x00) << 8) & 0xFF00; //grab top byte
  value += transferAD7797(0x00) & 0xFF; //grab bottom byte

  digitalWrite(cs, HIGH); //pull CS high to disengage

  return value; //return( ((byte1<<8) | byte2) & 0xFFFF);
}

uint16_t readCFG() //works!
{
  long output = 0;
  digitalWrite(cs, LOW);
  transferAD7797(0x50); //select CONFIGURATION register (01010000)(0x50)
  output = (transferAD7797(0x00) << 8) & 0xFF00; //grab top byte
  output += transferAD7797(0x00) & 0xFF; //grab bottom byte
  digitalWrite(cs, HIGH);
  return output;
}

uint8_t readST() //works!
{
  long output = 0;
  digitalWrite(cs, LOW);
  transferAD7797(0x40); //select STATUS register (01000000)(0x40)
  output = transferAD7797(0x00); //grab byte
  digitalWrite(cs, HIGH);
  return output;
}

//select adc channel
void selectCH(uint8_t ch)
{
  if (ch > 2)
    ch = 2;
  ch |= 0x90;

  digitalWrite(cs, LOW); //pull CS low to engage
  transferAD7797(0x10); //select configuration register 00010000 (0x10)

  transferAD7797(0x10); //Write 16 bits to CONFIGURATION register:
  //bias voltage: disabled 0 0
  //burnout current: disabled 0
  //bipolar operation: 0 or 1?
  //boost: disabled 1
  //gain: disabled 0 0 0
  //top 8b: 00011000 (0x18), disable boost yields 00010000 (0x10)

  transferAD7797(ch);   //internal reference 1
  //0 0
  //buffer 1
  //0
  //000 (CH1) 001(CH2) 010(CH3)
  //channel select = AIN1(+) - AIN1(-)
  //bottom 8b: 10010000 (0x90)  10010001 (0x91) read CH2  10010010 (0x92) read CH3
  digitalWrite(cs, HIGH); //pull CS high to disengage
}

void selectMode()
{

  digitalWrite(cs, LOW); //pull CS low to engage

  transferAD7797(0x08); //select MODE register (00001000)(0x08)
  //Write 16 bits to MODE register on page 16 Table 15
  transferAD7797(0x20); //0x00 for continuous
  //0x20 for single conversion  preferred
  //0x40 for idle
  //0x60 for power down
  //0x80 internal zero scale calibration
  //0xA0 internal full scale calibration
  //0xC0 system zero scale calibration
  //0xE0 system full scale calibration

  //update rate on page 16/17
  transferAD7797(0x0C); //0x00    X    X
  //0x01  470Hz 4mS
  //0x02  242Hz 8mS
  //0x03  123Hz 16mS
  //0x04   62Hz 32mS
  //0x05   50Hz 40mS
  //0x06   39Hz 48mS
  //0x07 33.2Hz 60mS
  //0x08 19.6Hz 101mS -90dB for 60Hz
  //0x09 16.7Hz 120mS -80dB for 50Hz
  //0x0A 16.7Hz 120mS -65dB for 50/60Hz
  //0x0B 12.5Hz 160mS -66dB for 50/60Hz
  //0x0C   10Hz 200mS -69dB for 50/60Hz
  //0x0D 8.33Hz 240mS -70dB for 50/60Hz
  //0x0E 6.25Hz 320mS -72dB for 50/60Hz
  //0x0F 4.17Hz 480mS -74dB for 50/60Hz
  digitalWrite(cs, HIGH);
}


uint8_t transferAD7797(uint8_t data)
{
  beginAD7797(); //set correct SPI settings for devices
  SPDR = data;
  while (!(SPSR & (1 << SPIF))); //wait until transfer is done
  return SPDR; //return received byte
}

void loop()
{
  delay(100);
  Serial.println(String("ADC Read : ") + readAD7797());
}

PCB Schematic