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

Parents
  • Hi,

    Do you have a scope shot of your digital interface upon reading the data register? Are you also monitoring the RDY bit or RDY pin upon reading the data register? May I know also what is your input range and so what data output are you getting from these input values?

    We have a software driver for the AD779x family. This can be also applicable for the AD7797. So you can use this as your reference code. Hope this will help. Kindly refer to the link. AD7793 IIO Low Power Sigma-Delta ADC Linux Driver [Analog Devices Wiki]

    Thanks,

    Jellenie

  • Hi thanks for the response. I read your solution on other related post accordingly i am trying, kindly can you check the above attached code. Also the reference code which you shared is bit complex and i am not expert in programming. If you tell me simple way it will be great help. Also please explain the sequence of data read write. 

    I followed figure 17 of datasheet (page 23) AD7797 for making PCB. I just want a simplest way to read ADC 24 bit value. Please provide some sample code written in C or C++ or Arduino

Reply
  • Hi thanks for the response. I read your solution on other related post accordingly i am trying, kindly can you check the above attached code. Also the reference code which you shared is bit complex and i am not expert in programming. If you tell me simple way it will be great help. Also please explain the sequence of data read write. 

    I followed figure 17 of datasheet (page 23) AD7797 for making PCB. I just want a simplest way to read ADC 24 bit value. Please provide some sample code written in C or C++ or Arduino

Children
No Data