2
\$\begingroup\$

I am using an Atmega32-A microcontroller and an AD7798 external ADC. I am able to set the ADC registers and read back ADC values. I have written the following code:

  statusreg = AD7798_8(0x40, 0xFF);          // read STATUS register default value
  Id = AD7798_8(0x60, 0xFF);                 // read ID register  default value
  mode = AD7798_16(0x48, 0xFFFF);            // read MODE register default value
  conf = AD7798_16(0x50, 0xFFFF);            // read conf register default value

   AD7798_16(0x10, 0x0010);            // write Configuration reg = 0x0010.  2.5V range  
   value = AD7798_16(0x50, 0xFFFF);         // read Configration register 

   if (value != 0x0010) 
   printf("unexpected conf setting %04x\r\n", value);

   while ((statusreg & 0x80) != 0);                         // wait till ADC is ready 
   adc = AD7798_16(0x58, 0xFFFF);                           // read register 
   printf("ADC value is %04d\r\n", adc);    

From the above code, I am reading the ADC values. According to the AD7798 datasheet and according to my configuration register setup, I have to find out the analog input voltage using following formula:

When the ADC is configured for bipolar operation, the output code is offset binary, with a negative full-scale voltage resulting in a code of 000...000, a zero differential input voltage resulting in a code of 100...000, and a positive full-scale input voltage resulting in a code of 111...111. The output code for any analog input voltage can be represented as

Code = 2N – 1 × [(AIN × GAIN / VREF) + 1]

where:
AIN is the analog input voltage.
N = 16 for the AD7798, and N = 24 for the AD7799.

I am getting an ADC value of 1EF2(hex) for 0.6V analog input. I have measured using an oscilloscope. I have calculated the analog input voltage using the above formula and I am getting 0.15V. Here GAIN is 1, VREF = 2.5V. Which is wrong because I have to get 0.6V. I have converted resultant hex ADC value into decimal 7922 and also binary 0001111011110010. My analog input voltage is varying from 0V to 0.6V. According to my analog input voltage my ADC output is also changing from 0002 to 1EF2.

If I change the configuration register setup to any other setup like bipolar to unipolar (from 0x0010 to 0x1010), at that time I am getting an ADC value of 0000 always. It is giving an ADC value of 0000 for any configuration other than 0x0010 in the configuration register.

More over, I am not able to understand what the following sentence means:

with a negative full-scale voltage resulting in a code of 000...000, a zero differential input voltage resulting in a code of 100...000, and a positive full-scale input voltage resulting in a code of 111...111.

How do I properly convert resultant digital signal to an analog voltage?
Are my ADC readings right or wrong?
Why does my code not work for any other configuration?

\$\endgroup\$
1
\$\begingroup\$

The AD7798 is a differential ADC. It has a negative input and a positive input. When configured for bipolar operation:

  • When the voltage between in+ and in- is positive (in+ > in-) at full scale the output will be all one.

  • When the voltage between in+ and in- is 0 (in+ == in-) the output will be 1000...0000.

  • And When the voltage between in+ and in- is negative (in+ < in-) at full scale the output will be all zero.

\$\endgroup\$
  • \$\begingroup\$ I have checked my AIN(+)=0.6(+) and AIN(-)=2.5(+), which means AIN(+)<AIN(-) then i have to get output as all zero's but I am getting values from "0000" to "1EF2". \$\endgroup\$ – verendra Oct 18 '12 at 14:15
  • \$\begingroup\$ Now I understand clearly. ADC is a diffrential amplifier so it will give difference of two inputs as output so here AIN(-) is 2.6 and AIN(+) is 0.6. so I am getting negative -1.9 voltage as output. my ADC result also giving same value. am I correct. \$\endgroup\$ – verendra Oct 18 '12 at 14:37
0
\$\begingroup\$

As Blup1980 mentioned, the AD7798 is a differential ADC. That means that it takes the difference of the two inputs and converts that value.

You have:

AIN(+) = +0.6V with reference to GND
AIN(-) = +2.5V with reference to GND

But the difference between the two is:

$$AIN = 0.6 - 2.5 = -1.9$$

So we have the following:

$$Code = 2^{N – 1} × [(AIN × GAIN/VREF) + 1]$$ $$7922 = 32768 × [(AIN × 1/2.5) + 1]$$ $$0.24176025390625 = (AIN × 1/2.5) + 1$$ $$-0.75823974609375 = AIN × 1/2.5$$ $$-1.895599365234375 = AIN$$

Which, is correct.

Converted into C code, we have:

int      code_dec;
float    code_flt;
float    ain_valu;

/* Initialize variables */
code_dec = 0U;
code_flt = 0.0F;
ain_valu = 0.0F;

code_dec = AD7798_16(0x58, 0xFFFF);                   /* Get Code from ADC */ 
code_flt = (float)code_dec;                           /* Cast Code into float */ 
ain_valu = ((code_flt / 32768.0F) - 1.0F) / 0.4F;     /* Perform calculation */

printf("Voltage is: %f\n", ain_valu);                 /* Print voltage value */

Casting the code value into a float and then using float values during every part of the calculation is good practice. Then you need the %f format specifier to ensure that the value is printed out as a floating point number which will include the negative sign if the value is negative. If you wish to include the positive sign for positive values, use %+f instead.

\$\endgroup\$
  • \$\begingroup\$ I have simplified the above formula implemented in c , Ain=((adc/32768)-1)/0.416 ; here 0.416=(1/2.5), adc means code value(7922). but the problem is I am not able to print Ain value. I want to print it as float value. It will give negative value. I want to print negative value. \$\endgroup\$ – verendra Oct 19 '12 at 7:51
  • \$\begingroup\$ @verendra See my edit for example C code \$\endgroup\$ – embedded.kyle Oct 19 '12 at 13:05
  • \$\begingroup\$ :kyle I have declared code_dec as unsigned int. but still am not able to print. nothing is printing. \$\endgroup\$ – verendra Oct 19 '12 at 13:15
  • \$\begingroup\$ @verendra Nothing is printing? Maybe the problem isn't with the conversion but with the connection to whatever screen you're using. Can you try printf("Hello World!\n");? Does that print out? \$\endgroup\$ – embedded.kyle Oct 19 '12 at 13:19
  • \$\begingroup\$ Yes hello world is printing and the code also it is printing like "voltage is: ". Nothing is printing means it is not printing any value. \$\endgroup\$ – verendra Oct 19 '12 at 13:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.