CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

AD7705 not reading full 16 bits ?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
ac34856



Joined: 14 Dec 2009
Posts: 33
Location: Wales

View user's profile Send private message

AD7705 not reading full 16 bits ?
PostPosted: Fri Mar 12, 2010 11:28 am     Reply with quote

I'm back to the AD7705 which has been the only glitch with my design.
The following code reads back 22547 at 2.45V with a 2.5V reference in
unipolar mode and somewhere near 23100 at 2.49V. I seem to be missing the MSB but I cant find why ?

Anyone know what the problem is ? .. other than me.. !?
Code:

#include <18F4620.h>
#device    PASS_STRINGS=IN_RAM
#device    *= 16;         
#fuses    HS, NOPROTECT, BROWNOUT, PUT, NOLVP, NODEBUG, MCLR
//#fuses NOWDT
#fuses    WDT, WDT512 // 1024 etc. See 18F4620.h for details...
#use    DELAY(CLOCK=40MHz, RESTART_WDT)      // Modified so it restarts WDT./
#use    RS232(BAUD=115200, XMIT=PIN_C6, RCV=PIN_C7, ERRORS, STREAM=USB,  RESTART_WDT, BITS=8, PARITY=N, STOP=1)
#use    RS232(BAUD=19200 , XMIT=PIN_C0, RCV=PIN_C1, ERRORS, STREAM=USB1, RESTART_WDT, BITS=8, PARITY=N, STOP=1)
#use      SPI(MASTER, DO=PIN_C5, DI=PIN_C4, CLK=PIN_C3, MSB_FIRST, MODE=0, BITS=16, STREAM=SPI)
#use    I2C(MASTER, SDA=PIN_A2, SCL=PIN_A3, FORCE_SW)

#include <string.h>
#include <stdlib.h>
#include <float.h>

#define   VERBOSE         1
#define   SILENT         0
#define   ERASE         1
#define   NO_ERASE      0
#define   SETUP_PRESENT   0x62
#define   FIFO_SIZE      12
#define WDT_LED        PIN_D0
#define   ADC_RESET      PIN_D1
#define   ADC_DRDY      PIN_D2
#define   EEPROM_CS      PIN_D3
#define   DS106_CS      PIN_D4
#define   AD7705_CS      PIN_D5
#define   AD7243_CS      PIN_D6
//
// Pin D7   Space for MAX186 Chip Sel
#define   RS232_TXD      PIN_C0
#define   CCP1_IN         PIN_C1
#define   CPP2_IN         PIN_C2
#define   ADC_CLK         PIN_C3
#define   ADC_DI         PIN_C4
#define   ADC_D0         PIN_C5
#define   TXD            PIN_C6
#define   RXD            PIN_C7
//
// PINS A2 and A3 are for I2C...
// AD7705 Calibration Mode Settings
//
#define   ADC_NORMAL      0x00
#define   ADC_SELF      0x40
#define   ADC_ZERO_SCALE   0x80
#define   ADC_FULL_SCALE   0xC0

// AD7705 Gain Settings
#define   ADC_GAIN_1      0x00
#define   ADC_GAIN_2      0x08
#define   ADC_GAIN_4      0x10
#define   ADC_GAIN_8      0x18
#define   ADC_GAIN_16      0x20
#define   ADC_GAIN_32      0x28
#define   ADC_GAIN_64      0x30
#define   ADC_GAIN_128   0x38

// AD7705 Polar Operations
#define   ADC_BIPOLAR      0x04
#define   ADC_UNIPOLAR   0x00
#define   ADC_CORRECT      0x04

// AD7705 Update rates
#define   ADC_50         0x04
#define   ADC_60         0x05
#define   ADC_250         0x06
#define   ADC_500         0x07

typedef   unsigned char     BOOL  ;
typedef   unsigned char     UINT8 ;
typedef   unsigned int16    UINT16;
typedef unsigned int32    UINT32;

UINT16   read_adc_value(int1);
void   write_adc_byte(BYTE data);
void   setup_ad7705(BYTE, BYTE, BYTE, BYTE, BYTE, BYTE);

//***************************************************************************

void   init_ad7705(int1 type)
{
output_low(ADC_RESET);
output_high(ADC_CLK);
output_high(AD7705_CS);
output_high(ADC_RESET);

fprintf(USB, "\r\n");
delay_ms(1000);   fprintf(USB, "\r...Initialising AD7705 ADC : (3 Seconds)");
delay_ms(1000);   fprintf(USB, "\r...Initialising AD7705 ADC : (2 Seconds)");
delay_ms(1000);   fprintf(USB, "\r...Initialising AD7705 ADC : (1 Second) ");
if (type)   // Used for calibration.
   {   read_adc_value(0);
      setup_ad7705(ADC_NORMAL,     ADC_GAIN_1, 0x4, ADC_50, 0x2, 0x0);   delay_ms(100);
      setup_ad7705(ADC_ZERO_SCALE, ADC_GAIN_1, 0x4, ADC_50, 0x2, 0x1);   delay_ms(100);
      setup_ad7705(ADC_NORMAL,     ADC_GAIN_1, 0x4, ADC_50, 0x0, 0x0);   delay_ms(100);
      fprintf(USB, "\r\n\n ");
      read_adc_value(1);
      setup_ad7705(ADC_NORMAL,     ADC_GAIN_1, 0x4, ADC_50, 0x2, 0x0);   delay_ms(100);
      setup_ad7705(ADC_ZERO_SCALE, ADC_GAIN_1, 0x4, ADC_50, 0x2, 0x1);   delay_ms(100);
      setup_ad7705(ADC_NORMAL,     ADC_GAIN_1, 0x4, ADC_50, 0x0, 0x0);   delay_ms(100);
      read_adc_value(1);
   }   //   setup_wdt(WDT_ON);
}

//***************************************************************************

void   setup_ad7705(BYTE calmode, BYTE gainsetting, BYTE operation, BYTE rate, BYTE fsync, BYTE buffered)
{      write_adc_byte(0x20);   // Communications register
      write_adc_byte(rate);
      write_adc_byte(0x10);   // Access setup register.
      write_adc_byte(calmode|gainsetting|operation|fsync|buffered);
}
//***************************************************************************
//   DESCRIPTION:     Converts string pointed to by s to a float
//   RETURN:       Result of the conversion
//   ALGORITHM:     None
//***************************************************************************
// And now the functions for the ADC AD7705

void   write_adc_byte(BYTE data)
{      BYTE   i;

      output_low(AD7705_CS);
      for (i=1; i<=8;++i)
         {   output_low(ADC_CLK);
            output_bit(ADC_DI, shift_left(&data,1,0));
            output_high(ADC_CLK);
         }   output_high(AD7705_CS);
}

//***************************************************************************

long int read_adc_word()
{       BYTE   i;
       long   data;

      output_low(AD7705_CS);
      delay_us(20);
      for (i=1;i<=16;++i)   {   output_low(ADC_CLK);
                        output_high(ADC_CLK);
                        shift_left(&data,2, input(ADC_D0));
                     }   output_high(AD7705_CS);
      return(data);
}
//***************************************************************************

UINT16      read_adc_value(int1 ch)
{
long long   retries=0;
UINT16      value;

while (input(ADC_DRDY))
   {   restart_wdt();
      delay_us(100);      // &&&&&&&& This used to be 100 uS.
      if (retries++ > 0xfff)
         {   // fprintf(USB, "\r\n ADC Timed Out !");
            break;
         }
   };
if (ch)   write_adc_byte(0x39);
else   write_adc_byte(0x38);
if (retries >= 0xfff) return(0xffff);
value = read_adc_word();
return(value);
}

void   main(void)
{
UINT16    adc;
init_ad7705(1);
while(1)
   {
   restart_wdt();
   adc=read_adc_value(1);
   if (adc == 0xffff) init_ad7705(0);
   fprintf(USB, "\r\n ADC Value : %Lu", adc);
   delay_ms(500);   
   }
}
dyeatman



Joined: 06 Sep 2003
Posts: 1934
Location: Norman, OK

View user's profile Send private message

PostPosted: Fri Mar 12, 2010 11:47 am     Reply with quote

You don't need to start a new thread every time you have something
different with the AD7705. Every time you add to the existing thread it
will move to the top.
_________________
Google and Forum Search are some of your best tools!!!!
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Fri Mar 12, 2010 12:07 pm     Reply with quote

In bipolar mode, the full scale ouput range is 0x8000..0x7fff. so you dont' miss a MSB with an output in the range of 22000.

Furthermore it seems to me, that you you are performing a system zero calibration without providing zero input signal.
ac34856



Joined: 14 Dec 2009
Posts: 33
Location: Wales

View user's profile Send private message

PostPosted: Sat Mar 13, 2010 6:19 am     Reply with quote

Apology for posting a similar thread.. running to a deadline I'm afraid and didnt think to check.

I changed the mode between BIPOLAR and UNIPOLAR but didnt get
anywhere incidentally .. but it appears I left it in BIPOLAR mode when
I posted the code.

I dont think that is the problem..
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sun Mar 14, 2010 3:38 am     Reply with quote

Quote:
I dont think that is the problem..

Clearly you won't get the expected output in bipolar mode. In so far it is a problem. The output coding in bipolar
mode is offset binary rather than two's complement, by the way. As I mentioned, your calibration scheme seems to
me dubious as well. Yes, I think, there are other problems too.

But I'm basically convinced, that you are able to figure it out. Many programmers have been using the various
ADI and other manufacturers ADC chips before and succeeded at last. Happy developing.
ac34856



Joined: 14 Dec 2009
Posts: 33
Location: Wales

View user's profile Send private message

PostPosted: Sun Mar 14, 2010 7:53 am     Reply with quote

Well I see your point if it were working in bipolar mode but alas it isnt
working in offset binary format so I think the issue with the mode is that the mode command definitions must have an error - which were pointed out in other posts on this.

Will stick with it ... its amazing isnt it how stressful these things can become when working to a deadline and then how quickly they are forgotten about !

I guess we are in this game cos we must like it.
ac34856



Joined: 14 Dec 2009
Posts: 33
Location: Wales

View user's profile Send private message

PostPosted: Sun Mar 14, 2010 7:55 am     Reply with quote

Postscript:
I believe that the AD7705 internally disconnects the input when it does
a zero calibration so assuming this is correct it shouldnt matter whats going on with the input pins so long as they are below 2.5V
mindstorm88



Joined: 06 Dec 2006
Posts: 102
Location: Montreal , Canada

View user's profile Send private message

PostPosted: Sun Mar 14, 2010 8:32 am     Reply with quote

In Self-Calibration it is internally shorted, but for Zero-Scale System Calibration and Full-Scale System Calibration you must put proper signal at the inputs !!! Read datasheet carefully (page 18)!!
ac34856



Joined: 14 Dec 2009
Posts: 33
Location: Wales

View user's profile Send private message

PostPosted: Sun Mar 14, 2010 10:42 am     Reply with quote

Well it sounds like I need to get reading again.

thanks
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sun Mar 14, 2010 12:05 pm     Reply with quote

Quote:
it sounds like I need to get reading again

Yes. System zero calibration exactly means what the name says: A system (overall) calibration in contrast
to an internal self calibration. The latter does, what you apparently intended.
ac34856



Joined: 14 Dec 2009
Posts: 33
Location: Wales

View user's profile Send private message

Fixed .. well sort of
PostPosted: Wed Mar 24, 2010 1:25 pm     Reply with quote

Just in case anyone wondered what the outcome was, .. simple .. as I couldnt get it to read above 30,000 just multiply the output by 2 and add or subtract 1 periodically ..

Cheating yes but noone will ever know .. and I get to do something else ! Smile
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group