AD7705/AD7706 Library

AD7705 and AD7706 are two 16-bit Sigma Delta ADCs. Equipped with on-chip digital filters and programmable gain front ends, these chips are ideal for low frequency multi-channel signal measurements. The main difference between AD7705 and AD7706 is that AD7705 has two fully differential input channels while AD7706 has three pseudo differential input channels.

This library I created interfaces with Arduino using the standard SPI bus. Most of the complexity is hidden behind the scene, and only a single parameter — the reference voltage — is needed to initialize the library since the reference voltage can vary depending on the particular implementation.

The following code snippet illustrates how to use this library. In this example, channel 1 of AD7706 is setup in bipolar mode with a unity gain. The common pin of the pseudo differential inputs (AIN1 to AIN3) is tied to the 2.5V voltage reference. This gives a measurement range of -2.5 V to +2.5 V. Pin SCK, CS, MOSI, MISO correspond to Arduino pin 13, 10, 11 and 12 respectively.

#include <AD770X.h>

//set reference voltage to 2.5 V
AD770X ad7706(2.5);
double v;

void setup()
{
 //initializes channel 1
  ad7706.init(AD770X::CHN_AIN1);
  
  Serial.begin(9600);
}

void loop()
{
  //read the converted results (in volts)
  v = ad7706.readADResult(AD770X::CHN_AIN1);
  Serial.println(v);
  delay(100);
}

Here is the schematics I used for the sample program above:

AD7706

AD7706

For a supply voltage of 5V, the recommended voltage reference is AD780/REF192. I used two 1.25 V precision shunt voltage references ADR1581 to form a 2.5V reference instead since those are the components I have on hand.

The library also provides an overloaded init method to setup channel, gain and update rate:

void init(byte channel, byte gain, byte updRate);

The available gain settings are defined as:

  static const byte GAIN_1 = 0x0;
  static const byte GAIN_2 = 0x1;
  static const byte GAIN_4 = 0x2;
  static const byte GAIN_8 = 0x3;
  static const byte GAIN_16 = 0x4;
  static const byte GAIN_32 = 0x5;
  static const byte GAIN_64 = 0x6;
  static const byte GAIN_128 = 0x7;

And the update rate settings can be chosen from:

  static const byte UPDATE_RATE_20 = 0x0; // 20 Hz
  static const byte UPDATE_RATE_25 = 0x1; // 25 Hz
  static const byte UPDATE_RATE_100 = 0x2; // 100 Hz
  static const byte UPDATE_RATE_200 = 0x3; // 200 Hz
  static const byte UPDATE_RATE_50 = 0x4; // 50 Hz
  static const byte UPDATE_RATE_60 = 0x5; // 60 Hz
  static const byte UPDATE_RATE_250 = 0x6; // 250 Hz
  static const byte UPDATE_RATE_500 = 0x7; // 500 Hz

Other settings can be accessed via the setup register directly using the writeSetupRegister method defined below:

//Setup Register
//  7     6     5     4     3      2      1      0
//MD10) MD0(0) G2(0) G1(0) G0(0) B/U(0) BUF(0) FSYNC(1)
void AD770X::writeSetupRegister(byte operationMode, byte gain, byte unipolar, byte buffered, byte fsync)

For more details, please refer to the datasheet and the code in the download section.

AD7706 Test Setup

AD7706 Test Setup

Download AD770X.tar.gz (Obsolete)
4/18/2012: AD770X1.1.tar.gz (see this post for changes since the previous version)

Be Sociable, Share!

33 Comments

  1. pfg says:

    Hi there Kerry,
    I’ve just tested your library and it works great.
    You’ve done a pretty good job!

    although, I’ve got a question: How can I read all the analog input channels?

    Keep up the good work!

    pfg

    • kwong says:

      Thanks pfg. You can just initialize both AD770X::CHN_AIN1 and AD770X::CHN_AIN2 and use them in your code.

      • pfg says:

        Thanks Kerry for the quick reply.
        I’ve tried that already:

        In the setup section I added:
        ad7706.init(AD770X::CHN_AIN2);
        ad7706.init(AD770X::CHN_AIN3);

        and in the loop section:
        x = ad7706.readADResult(AD770X::CHN_AIN2);
        y = ad7706.readADResult(AD770X::CHN_AIN3);

        Is this right?

        I get only one value, the same for the three reading and it’s also wrong.
        If the code is OK then I should check my circuit again…

        Thanks in advance,
        pfg

  2. Chris says:

    Hi, Kerry,

    I wired up a AD7706 and used a AD680 as a voltage reference, exactly as in your example (Vcc I drew from 5V in Arduino). I got the example to compile and upload alright, but when I opened up the serial monitor, it was blank and nothing shows up.

    Thanks,

    Chris

    • kwong says:

      Hmm… I guess I’ll need more detailed description in order to understand why nothing shows up on serial monitor. Question, if you do a Serial.print in the same program does anything come out?

      • Chris says:

        Yes, with the same circuit, if I run one of the sample code from Arduino like “AnalogReadSerial” here: http://arduino.cc/en/Tutorial/AnalogReadSerial, it will print out numbers.

        In fact, I find the code to be stuck on this line “ad7706.init(AD770X::CHN_AIN1);”
        in the setup, as well as this line in the loop “v = ad7706.readADResult(AD770X::CHN_AIN1)”, in a sense that if I asks it to just print something, like “1”, I need to comment both lines (like below), and if either line is active, the code will not reach to the print line.

        #include

        AD770X ad7706(2.5);
        double v;

        void setup()
        {
        //ad7706.init(AD770X::CHN_AIN1);

        Serial.begin(9600);
        }

        void loop()
        {
        // v = ad7706.readADResult(AD770X::CHN_AIN1);
        Serial.println(“1”);
        delay(100);
        }

        Thanks,

        Chris

        • kwong says:

          OK. Check your MISO/MOSI pin connections and make sure that they are not reversed. The symptom you described sounds like issue with the SPI bus. The MOSI and MISO are connected to Arduino digital pin 12 and 11, correct (chip pin 17 and 18). These two pins are reserved for SPI operations.

          • Chris says:

            Hi, Kerry,

            I checked my circuit, and MISO and MOSI were indeed reversed. I’ve corrected it as you said (although I think you meant the chip pins 13 and 14, not 17 and 18), so now MISO (chip pin 13) is hooked to Arduino pin 11, and MOSI (chip pin 14) is hooked to Arduino pin 12, but still nothing shows up on the serial monitor… The problem encountered as described in my last post still persists.

            Thanks,

            Chris

          • Chris says:

            Also, I think in your post you had the two pins reversed too, “Pin SCK, CS, MOSI, MISO correspond to Arduino pin 13, 10, 11 and 12 respectively. “

          • Chris says:

            On another note, I’m using Arduino Mega 2560, maybe that’s the case?

            Thanks,

            Chris

          • kwong says:

            I don’t have ATmega 2560, but from the schematics (http://arduino.cc/en/uploads/Main/arduino-mega2560-schematic.pdf) it seems that the MOSI/MISO are 50/51. The code should work with all Arduino boards. Good luck!

          • Chris says:

            Hi, Kerry,

            Thank you for your advice! Now I have the pins hooked up to the right Arduino pins, I am able to see numbers popping up on the monitor. However, they are _always_ the same as the reference voltage I set in the beginning. So if I wrote:

            AD770X ad7706(2.5);

            I’ll get “2.50” or “-2.50” printed one or the other, and which one to be printed is rather arbitrary, although neg seems to be preferred. Same if I type in arbitrary number (like 330) in the reference voltage variable, so the ADC seems to not be converting at all, and the readADResult(byte channel) function doesn’t seem to be working, in a sense that if I let it return “0” or “2*VRef”, it will still return VRef.

            Additional curiosity. If I say:

            AD770X ad7706(AD770X::CHN_AIN2);

            All channels (1, 2, 3, COMM) will give me 1.00 volt, and if I set the Vref to be CHN_AIN1, I will get 0.00V on all channels; CHN_AIN3 for 3V, and CHN_COMM for 2V.

            And it seems that the function init is read through but does not do anything, that is, it doesn’t matter if I initiate any channel at all to go to the loop.

            Also, just for curiosity, the function “spiTransfer()” is not defined in the library, and it seems the standard usage is to include the SPI library and then call SPI.transfer().

            Regards,

            Chris

  3. Chris says:

    sorry, the “include” line above I have is incomplete, should be “#include ” as in your example.

  4. NorthStar says:

    Hi
    I am using yor library, and thankyou for such a big job.
    But I have some problems:
    My project is weighting system with pressure sensor. Which is very sensitive – it ranges 6 kg = 3mV on 5V supply.
    When I try to change GAIN to 128 – the answer is only 0. What can be a problem.
    I also try to change bipolar-unipolar mode on GAIN 1, but nothing changes. On GAIN 1 it works fine, but I need to mesure very low voltage. Please help.

  5. NorthStar says:

    Thank you for your answer! Now I more understand my problem and it devided in two:
    1 In any case – chip sometimes show normal result and sometimes give only zeros. I do nothing, just turn it on and off and chip sometime work and sometime not.
    2 I try to read setup register and find out that my chip does not remember them. I read the same data as I set only first time and on next read I get the same random data. So I add init function to loop and it works (but problem 1 still exist)
    Now I have only one idea – my chip is damaged.
    I heve two capactors 10 мкф and 0.1 мкф on supply voltage. My schema is the same as on figure 22 from datasheet.

  6. arlukas says:

    Dear Kwong.
    First of all thanks for your great work. I have tested the library and works fine. One question: Could I change CS pin? I tried it but no successfully (I changed pinCS definition in the *.h file)
    Thanks in advance. Regards

  7. Vasiliy says:

    Hello K.Vong, I apologize for my English, because I am from Russia. I did all of your scheme, but it does not work. In the output I see -2.5 volts, ie, negative reference voltage. And does not react to the supply voltage to the analog inputs of the chip. Could you lay out a more detailed diagrams or photos of the device while operating … Since the on y7our scheme no nominal capacity after the crystal oscillator

    • kwong says:

      I am not sure why you would see a negative voltage from the output if you are using a single supply like the way I connected in the diagram. In regarding to the load capacitors, since I used a ceramic oscillator instead of a crystal the two load capacitors are not needed. But if you are using a crystal, you should add the appropriate load capacitors. Hope it helps.

      • Vasiliy says:

        Hello K.Wong! Thank you very much for your advice, I put the generator into the circuit and it worked!
        But I have now another problem arose:
        In the void setup (), I initialize all three channels:
        ad7706.init (AD770X :: CHN_AIN1);
        ad7706.init (AD770X :: CHN_AIN2);
        ad7706.init (AD770X :: CHN_AIN3);
        And in the void loop () output their values
        v = ad7706.readADResult (AD770X :: CHN_AIN1);
        Serial.print (v);
        Serial.print (“|”);
        a = ad7706.readADResult (AD770X :: CHN_AIN2);
        Serial.print (a);
        Serial.print (“|”);
        b = ad7706.readADResult (AD770X :: CHN_AIN3);
        Serial.print (b);
        Serial.println ();
        delay (100);
        But at the ground the third channel, I see -2.5, and the same values ​​on channels 1 and 2 by applying 5 volts on channel 3, and again, I see 2.5 on all three channels. That is, changing the voltage on the three channel maps at 1 and 2.

        But with supply 5 volts at 1 and 2 channel, I see 0 volts at the output of all channels, and at ground 1 or 2 channels, I see -2.5 volts on all channels.

        That is, Channel 3 is working fine, measures the voltage as it should, but why is the value displayed on the 3 channels 1 and 2 …. A channel 1 and 2 do not work correctly.

        Because what could it be?

        Thanks in advance!

        • kwong says:

          Hi Vasiliy,

          Did you try calling AD770X::readADResult() immediately after calling AD770X::init()? In other words, try using init(channel) and readADResult as a pair and let me know if it works. If not I will have to take a look to see where the issue might be. Thanks.

  8. Vasiliy says:

    Hello K.Wong again!
    I did as you said, used to initialize the values ​​of reading. When I used the initialization with only one parameter (the port number, like this: ad7706.init (AD770X :: CHN_AIN1) ;) then the Arduino boot time I saw real value, but then they were repeated, ie, values ​​are not updated, and displayed only the first value.

    Then I began to pass all parameters in the initialization function (ad7706.init (AD770X :: CHN_AIN1, AD770X :: GAIN_128, AD770X :: UPDATE_RATE_100) ;), then it work again, but began to work the same way as I described last time.

    Initialization void setup () using all the parameters, too, did not produce the desired effect, as the inputs were not working as it should …

    • kwong says:

      Hi Vasiliy,

      Let me take a look to see whether any portion of the code could be changed to make it a bit easier to use. It has been a while, but I didn’t remember running into this issue when I was using the chip. I will reply back when I get a chance to take a closer look.

      • kwong says:

        Hi Vasiliy,

        I have just tried using both CHN_AIN1 and CHN_AIN2 at the same time. And the following code works for me:

        #include <AD770X.h>
        
        AD770X ad7706(2.5);
        double v;
        
        void setup()
        {
          ad7706.init(AD770X::CHN_AIN1);  
          delay(100);
          ad7706.init(AD770X::CHN_AIN2);
          delay(100);  
          Serial.begin(9600);
        }
        
        void loop()
        {
          delay(100);
          v = ad7706.readADResult(AD770X::CHN_AIN1);
          Serial.print(v);
          delay(100);
          v = ad7706.readADResult(AD770X::CHN_AIN2);
          Serial.print(" : ");
          Serial.println(v);
        }
        

        According to the datasheet, you will need some delays between the reads (ideally you should poll the DRDY bit in the communication register or poll the dedicated DRDY pin, for simplicity reason I didn’t use that in the code library. And if timing is not critical, simple delays works fine). Also, if your clock frequency is different (I used 2Mhz), you may need to use the tweak the parameters according to the datasheet.

        AD7706 isn’t the easiest chip to work with in my opinion, one thing is that the power-on sequence is somewhat important. According to the datasheet (Rev. C. P30)

        “it is important that power is applied to
        the AD7705/AD7706 before signals are applied at the REF IN,
        AIN”

        And also the chip expects a write to the communication register upon power up.

        The library code I provided only offers very basic functionalities (e.g. bi-polar, 50Hz update rate and x1 signal gain), the chip is capable of doing much more and you will need to read the datasheet to implement these additional functionalities if needed.

  9. kwong says:

    I have updated the library to make it easier to use. You can find the change details in this post.

  10. francesco says:

    HI to everyone!

    I’m pretty new to electronics but i have to use an adc to make a data logger.

    I might seem a little bit dummy but since i don’t have a big knowledge in electronics, can somebody say to me which kind of oscillator has used?
    in digikey.com i find tons of them, but i’m nor really sure on just grabbing one of 2MHz. any advice?

    cheers,
    francesco

  11. Smalldog says:

    Just wanted to say thanks for a great library. It’s been very helpful to get my project off the ground.

    I do have a question though. Can you explain your math for returning the voltage in the line below:

    return readADResult() * 1.0 / 65536.0 * VRef – refOffset

    I understand VRef and refOffset, but what’s the significance of dividing by 65536.0?

    I’ve translated the code into a .NET library for use on a Raspberry Pi 2 running Windows 10 IoT.

    Thanks,
    Jeff

  12. ernesto says:

    thanks for the library.
    i wanted to know if i can put negative voltage on ain1+ in ad7705 in bipolar mode and how, in bipolar mode i read at zero input 32768 that is maybe fine representing the middle point between -2.5 , 0 , +2.5 ok but dont want to fry the adc if putting negative voltages someone have been tried to read negative voltages? the datasheet is something confuse at this point.

  13. Ajesh says:

    Hi
    AD 7705 library is not supporting my Arduino UNO board. any suggestion…. please help me…..

  14. Micheal liu says:

    hi kwong,
    According to the circuit diagram, I made a module,Crystals choose 4.9152 M,22 pf the resonance capacitance,choose your AD770X1.1.tar program.but it doesn’t work!display 0.because DRDY pin has always been a high level(4.9V).what is the matter??

Leave a Reply