problem controlling an AD7715 using SPI with an Arduino Uno

Hi,

I'm struggling to get an analogue devices AD7715 to work with an arduino R3. I have read the data sheet and example code a thousand times but I just can't see where I'm going wrong. Does anyone have any experience with this device that can help?

Here is the code:

// arduino SPI code for driving an ADC7715
// 11/06/2012

#include "SPI.h" // Uses the SPI library

#define DATAOUT 11 //MOSI
#define DATAIN 12 //MISO - not used, but part of builtin SPI
#define SPICLOCK 13 //sck
#define cs 10 //cs


int drdy=8; // I'm using digital pin 8 on the arduino for Data Ready Pin for data ready select
int del=200; // used for various delays
byte dataRegHighByte; //High part of data read in from ADC
byte dataRegLowByte; //Low part of data read in from ADC 
int adcData; //value of adc register after combining the bytes received

void setup()
{
  pinMode(cs, OUTPUT); // we use this for SS pin
  pinMode(drdy, INPUT); // we use this for drdy pin
  SPI.begin(); // wake up the SPI bus.
  SPI.setBitOrder(MSBFIRST);
  // AD7715 requires data to be sent MSB (most significant bit) first??
  SPI.setDataMode(SPI_MODE0);  // SCLK idle low (CPOL=0), MOSI read on rising edge (CPHI=0)
  SPI.setClockDivider(SPI_CLOCK_DIV16);  // ATmega328P at 16 MHz, so SPI = 1 MHz
  Serial.begin(9600);
  setupAD7715();
}

void setupAD7715()
{
  
  digitalWrite(cs, LOW);
  SPI.transfer(0x10);  // set the gain to 1, standby off and set the next operation as write to the setup register 
  SPI.transfer(0x66);  // set unipolar mode, buffer on, no filter sync, confirm clock as 2.4576MHz, set output rate to 50Hz and do a self calibration 
  digitalWrite(cs, HIGH);
  if (drdy!=HIGH){
    Serial.println("Data Ready pin has gone LOW!");
    Serial.println("Self Calibration complete!");
    delay(1000);
    readADCDataRegister();
  }
  
  else Serial.println("Data Ready pin is HIGH");  

}  

void readADCDataRegister()
{
  int adcRead;
  digitalWrite(cs, LOW);
  adcRead = SPI.transfer(0x38);  // read the 1st byte
  adcRead <<= 8;                      // shift the byte to the high 8 bits
  adcRead |= SPI.transfer(0x38); // read the 2nd byte and OR to the low 8 bits of adcRead 
  digitalWrite(cs, HIGH);
  Serial.print("Data has been read from ADC! :");
  Serial.print("Data Received was: ");
  Serial.println(adcRead,DEC);
  delay(1000);  
  
}  
void loop()
{
  readADCDataRegister();
}

Cheers

Alex

  if (drdy!=HIGH){

This isn't reading the drdy pin. It is just comparing 8 with HIGH and they will never be equal.
Try:

if(digitalRead(drdy) != HIGH) {

Pete

Hi people

Still struggling with this device....I just can't seem to get it to respond. If anyone can help that would be much appreciated!

Here is my code:

/*

 Circuit:

 DRDY: pin 8
 CSB: pin 10
 MOSI: pin 11
 MISO: pin 12
 SCK: pin 13
 
 */

// the sensor communicates using SPI, so include the library:
#include <SPI.h>

// pins used for the connection with the sensor
// the other you need are controlled by the SPI library):
const int dataReadyPin = 8;
const int chipSelectPin = 10;

long adcRead1=0;
long adcRead2=0;

int i=0;

/*

Control Register
|  7   |   6  |  5  |  4  |  3  |  2   | 1  | 0  | 
|/DRDY | ZERO | RS1 | RS0 | /RW | STBY | G1 | G0 |

Select Communications Register
| RS1  | RS0  |
|  0   |   0  |

Select Setup Register
| RS1  | RS0  |
|  0   |   1  |

Select Test Register
| RS1  | RS0  |
|  1   |   0  |

Select Data Register
| RS1  | RS0  |
|  1   |   1  |

Setup Register
|  7   |   6  |  5  |  4  |  3  |  2  |  1  |   0   | 
| MD1  | MD0  | CLK | FS1 | FS0 | /BU | BUF | FYSNC |


0b00010000 = 0x10 = - access setup register 
0b01100110 = 0x68 = - send data to setup register that sets clock speed, unipolar mode, no filter sync and output rate to 50Hz 

0b00001000 = 0x8 = 8 - access control register and prepare to write command to the control register
0b00000000 = 0x0 = 0 - clear control register??

*/

void setup() {
  Serial.begin(9600);

  // start the SPI library:
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);  // AD7715 requires data to be sent MSB (most significant bit) first??
  SPI.setDataMode(SPI_MODE3); // SCLK idle low (CPOL=0), MOSI read on rising edge (CPHI=0)
  SPI.setClockDivider(SPI_CLOCK_DIV16);  // ATmega328P at 16 MHz, so SPI = 1 MHz
 // SPI.setClockDivider(SPI_CLOCK_DIV16);  // ATmega328P at 16 MHz, so SPI = 1 MHz
 
  
  // initalize the  data ready and chip select pins:
  pinMode(dataReadyPin, INPUT);
  pinMode(chipSelectPin, OUTPUT);
  
  setupADC();
    
}

void setupADC()
{ 
 
  digitalWrite(chipSelectPin, LOW);
  SPI.transfer(0x10);  // set the gain to 1, standby off and set the next operation as write to the setup register 
  SPI.transfer(0x68);  // set unipolar mode, buffer on, no filter sync, confirm clock as 2.4576MHz, set output rate to 50Hz and do a self calibration 
  digitalWrite(chipSelectPin, HIGH);
  
  while(!(dataReadyPin & 0x80))  /* wait for /DRDY to go low */
    {  
      writeToADCDataRegister();
    }
    
}  

void writeToADCDataRegister()
{
  digitalWrite(chipSelectPin, LOW);
  SPI.transfer(0x08);
  SPI.transfer(0x68);
  digitalWrite(chipSelectPin, HIGH);
  
  while(!(dataReadyPin & 0x80))  /* wait for /DRDY to go low */
    {  
      readFromADCDataRegister();
    }   
}


void readFromADCDataRegister()
{
     
  int adcRead;
  digitalWrite(chipSelectPin, LOW);
  adcRead = SPI.transfer(0x38);  // read the 1st byte
  adcRead <<= 8;                      // shift the byte to the high 8 bits
  adcRead |= SPI.transfer(0x38); // read the 2nd byte and OR to the low 8 bits of adcRead 
  digitalWrite(chipSelectPin, HIGH);     
 
    
//    Serial.print("ADC1 Data: ");
//    Serial.println(adcRead1,DEC);
//    Serial.print("ADC2 Data: ");
//    Serial.println(adcRead2,DEC);

//writeToADCDataRegister();

    
     
}

void loop()
{
setupADC();  
//writeToADCDataRegister();
}

Try re-reading and understanding my previous response, particularly the code I posted.

Pete

Pete,

I did read yor response and try out the code section you suggested. It made absolutely no difference whatsoever. I have also been looking at the datasheet and code example for the device and the manufacturers are suggesting to use a while statement for the polling of the /DRDy pin which is what ultimately the device requires to show that a register command has been received and processed.

{if(digitalRead(drdy) != HIGH) - your code for polling the /DRDy pin

digitalRead(dataReadyPin)  /* wait for /DRDY to go low */
if (dataReadyPin == 0)
  {
   writeToADCDataRegister();
  }
  • My code re-written after your help
while(!(dataReadyPin & 0x80))  /* wait for /DRDY to go low */
    {  
      writeToADCDataRegister();
    }
  • What I think the manufacturer recommends for polling the /DRDY pin

Your code snippet looks at the /drdy pin for a change of state from high to low which is one way of achieving what I did with my second code example. I accept my original code was incorrect but not my second effort after your assistance. None of the above made the device work which is why I asked for some more help. The issue is I think, with the device itself and not with the code as I have looked at the data lines using a logic analyser and I never see the /DRDY pin change state after sending an SPI command.

If anyone has any ideas, I'm open to suggestions on how to prove the device is working.

Cheers

Alex

The statement:

while(!(dataReadyPin & 0x80))  /* wait for /DRDY to go low */

does NOT wait for /DRDY to go low. It compares the value of dataReadyPin to 0x80. Since you have declared dataReadyPin to be an integer constant with a value of 8, the result of "8 & 0x80" is always zero and so the while loop will never terminate.
If you want to wait until Pin 8 goes low you need:

while(digitalRead(dataReadyPin))  /* wait for /DRDY to go low */

This will read the value of Pin 8 and if it is non-zero (HIGH) it will stay in the while loop. Once the value of pin 8 goes low, the while loop will terminate.

Pete

Pete,

Thank you for you help in the coding. I still don't have the device working but I can now see the /DRDY pin going high and low sometimes on the logic analyser. I must be still doing something wrong in terms of the code. I also think I need to use a proper layout with a ground plane. My circuit is very jittery.

Thanks again,

Alex

hi,

make sure, your chip select pin is low, while you are waiting for dr pin to go low. otherwise the chip goes into idle mode.

i had the same problem with ad7734.

Alex,

Did you ever resolve your problem?

I can set the register (thanks for sharing your code helped me get started!) but the DRDY never goes down.

Regards,
Gus

Hi Langster!

Langster:

digitalWrite(chipSelectPin, LOW);

adcRead = SPI.transfer(0x38);  // read the 1st byte
adcRead <<= 8;                      // shift the byte to the high 8 bits
adcRead |= SPI.transfer(0x38); // read the 2nd byte and OR to the low 8 bits of adcRead
digitalWrite(chipSelectPin, HIGH);

The correct code for reading the SPI is:

digitalWrite(chipSelectPin, LOW);
SPI.transfer(0x38);     // send the reading instruction
adcRead = SPI.transfer(0);    // read the 1st byte
adcRead <<= 8;                  // shift the byte to the high 8 bits
adcRead |= SPI.transfer(0);   // read the 2nd byte and OR to the low 8 bits of adcRead
digitalWrite(chipSelectPin, HIGH); 
SPI.endTransaction(); // -  not obligatory, but may be

@Filipx_cz: What's the point of reviving a thread that's been dead for about four and a half years?

Pete

Hello Filipx_cz. :slight_smile:
Thank you for your code...
may you can share the complete working code just to copy and paste?

i have found 10 pcb for pt100 with an AD7714 on it. The Pins MOSI, MISO, SCLK, SYNC and DRDY are inverted by an integrated IC. I am not sure if i can use the code in same way. :frowning:
hopefully someone can help.

THX

Could anyone help me to write code to interface AD7734 with arduino.Thanks