AD7731 via Arduino SPI

We're using an Arduino to control an AD7731.  We think the SPI interface is working in that we can 1) trigger a reset by writing four 0xFF bytes and see the RESET pin go low via our logic analyzer and 2) After the reset, we read the Mode register and get back 0x174 as per the data sheet.  Our problem is that when we try to do a continuous conversion read operation, fully differential, AIN1(+) and AIN2(-), 0 - 1.28 V, Mode bytes as follows (MSB first)   00110001  01110100, we can't ever get the RDY pin to go low.  Is there a way to check the operation of the chip so see if conversions are being made and put in the data register at all?  I don't think we fried the chip, but we don't have a way to check.  Also, we are using the AD780 2.5V reference.  We could send you code if that would help.

Thanks,

George

  • Hi George,

    Firstly, check your code against the "Pseudo-Code for Looping AD7731 Through Three Fully-Differential Channels", on page 36 of the AD7731 datasheet rev A.

    Confirm the mode register is programmed correctly by reading the register contents back. In Continuous Conversion Mode, the AD7731 is continuously processing data and providing conversion results to the Data Register at the programmed output update rate (as determined by the Filter Register).

     

    Kind Regards, Brendan.


  • Brendan,

         We tried your suggestion with mixed success. We still don't see the RDY pin go low. I've attached our Arduino code and a screenshot of one section of the output of our logic analyzer. We were able to:

    1. Do a reset by writing 32 1's to the ADC.

    2. Read the mode register and get the default/power-up value (0x174)

    3. Write new mode bytes for continuous read, etc. (see comments in code)

    4. Read back the mode bytes and confirm that the write was accomplished

    successfully.

    Can you see our error or perhaps suggest another test that might be helpful?

    Thanks,  George

    /*Arduino sketch for AD7731 ADC

    This sketch assumes the usual SPI pin assignments found at https://www.arduino.cc/en/Reference/SPI

    for the Mega2560:

    MOSI = 51

    MISO = 50

    SCK = 52

    SS = 53

    */

    #include <SPI.h>

    //Set any handy constants and do variable declarations

    const  int  adcRDY = 30;  //Monitor pin 30 to see when data is ready for reading

    byte mode1, mode2, modedata1, modedata2;        //For mode register bits, mode1 is MSB

    void  setup()  {

      pinMode(adcRDY,INPUT);

      pinMode(MISO,INPUT);

      pinMode(MOSI,OUTPUT);

      pinMode(SCK,OUTPUT);

      pinMode(SS,OUTPUT);                   //this is the chip select line, set low to select chip

      pinMode(40,OUTPUT); digitalWrite(40,LOW);    //We're using pin 40 as a trigger for the logic analyzer

      SPI.begin();

      SPI.setBitOrder(MSBFIRST);

      SPI.setDataMode(SPI_MODE3);    //CPOL = 1, CPHA = 0, POL pin on ADC should be HIGH

      SPI.setClockDivider(SPI_CLOCK_DIV16);  //Serial clock frequency is now 1 MHz

      Serial.begin(9600);  //connection to serial monitor for output and debugging

      Serial.println("past setup");

    }

     

    void  loop()  {

      digitalWrite(40,HIGH);  //Start the logic analyzer

      digitalWrite(SS,HIGH);  //Set SS HIGH in case it matters

      digitalWrite(SS,LOW);  //Set SS LOW to select chip

      SPI.transfer(0xFF); //hardware reset with 4, 8 byte sets of 1's

      SPI.transfer(0xFF);

      SPI.transfer(0xFF);

      SPI.transfer(0xFF);

      delayMicroseconds(100);  //just in case the chip needs time to settle out

      SPI.transfer(0x12);  //Tell comm register that next operation is read from mode register

      modedata1 = SPI.transfer(0x00);  // Read first byte from the mode register

      modedata2 = SPI.transfer(0x00);  // Read second byte from the mode register

      Serial.println("Default mode register bytes are...");

      Serial.println(modedata1,BIN);  //print out mode data bytes to serial monitor

      Serial.println(modedata2,BIN);  //print out mode data bytes to serial monitor

      mode1=0b00110001;    //MSB   Continuous conversion, unipolar, no digital ports, 24 bit data,

      mode2=0b01110100;    //LSB  Vref=2.5V, 0 - 1.28 V scale, no burnout, fully differential, AIN1(-) AIN2(+)

      SPI.transfer(0x02);  //Tells communications register that next operation is write to mode register.

      SPI.transfer(mode1);  //Tell it to take the reading as described by mode's bits

      SPI.transfer(mode2); 

      Serial.println("New mode register bytes are...");

      SPI.transfer(0x12);  //Tell comm register that next operation is read from mode register

      modedata1 = SPI.transfer(0x00);  // Read first byte from the mode register

      modedata2 = SPI.transfer(0x00);  // Read second byte from the mode register

      Serial.println(modedata1,BIN);  //print out mode data bytes to serial monitor

      Serial.println(modedata2,BIN);  //print out mode data bytes to serial monitor

      delay(1000);  //sit here a while to see if RDY ever goes low

      SPI.transfer(0x30);  //stop continuous conversion

      digitalWrite(40,LOW);  //reset level of logic analyzer trigger to get ready for next sweep

      digitalWrite(SS,HIGH); //deselect chip 

      delay(5000);  //wait 5 s before looping

    }

     

    319866a4116221178feca71c97ce4d1b.tiff

  • Sorry, but I think there was an error in the comments in the code:  We have CPOL = 1 and CPHA = 1, which does indeed correspond to SPI_MODE3.

  • Hi George,

    Don't see any problem with your code. Can you send me a schematic diagram. How are you driving pin 2 the MCLK IN? And how is the filter register programmed?

    One thing to try. Once the part is programmed to operate in continuous conversion mode, stop the code there and check the RDY pin with an oscilloscope, it should be toggling at the filter register programmed output data rate.

    Regards,  Brendan.


  • Brendan,

         I've attached a diagram showing our connections to the AD7731.  We are pretty much following Figure 21 on p. 39 of the datasheet.  We're using the AD780 to supply the VREF and a 4.9152 MHz crystal across the MCLK pins, with 33 pF caps to ground from each.  On a scope, the MCLK out signal (wrt ground) is a quasi-sine wave with 1 V amplitude with a +2V offset from ground (goes between 1 V and 3 V).  We don't use optoisolators between the Arduino and the AD7731.  The filter register is unchanged from its power up values, which the data sheet says should give an update rate of 600 Hz if my calculations are correct (I haven't yet had the code do a read of the filter register).  I see nothing on the scope or on the logic analyzer to indicate that the /RDY pin is going low at any time in the process.  If I use a DMM to monitor /RDY, I do see a quick few mV drop that seems to be cyclical (remember, the Arduino code continuously loops), but that could be crosstalk from some other line (like the /CS).

    We are using a powered breadboard, which isn't the most quiet of electronic environments, but I hesitate to solder up a board with ground planes and everything if we can't make it work at all under these conditions.

    2441fa37fe78dfa939b5c82be308f798.tiff

    Thanks,

    George