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

external ADC AD7476

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



Joined: 12 Jan 2009
Posts: 33

View user's profile Send private message

external ADC AD7476
PostPosted: Thu Mar 19, 2009 7:28 am     Reply with quote

Hi, Im having a bit of trouble with my ADC. I do get results, and they are very close to what they should be. however they shift about an awful lot with each reading.

i.e. with a 4volt input i should read 0xCCC, but instead get 1.CFC 2.CFD 3.D03

Code:

   uint8_t   adc_val1 = 0x00;
   uint8_t    adc_val2 = 0x00;
   uint16_t   adc_result = 0x0000;
   
   LATA5   =   0;      //select ADC
   LATA5   =   1;      //de-select ADC

   LATA5   =   0;      //select ADC

   Delay10TCYx(2);               //wait for 20

   SSPBUF   =   0xFF;            //send dummy data
   while(!bit_BF){}      //wait for buffer to fill
   adc_val1 = SSPBUF;            //read first byte

   SSPBUF   =   0xFF;            //send dummy data
   while(!bit_BF){}      //wait for buffer to fill   
   adc_val2 = SSPBUF;            //read second byte

        LATA5   =   TRUE;      //de-select ADC
   
   adc_result    =   adc_val1;
   adc_result = adc_result<<8;
   adc_result = adc_result^adc_val2;



any advice would be great as i really need this to be much more accurate.

matt
Ttelmah
Guest







PostPosted: Thu Mar 19, 2009 9:46 am     Reply with quote

Some questions/comments apply:
1) Show your SPI setup.
2) What clock rate are you using on the chip?.
3) What are you using as Vdd to the chip?.
4) Why not use the CCS functions?.

Best Wishes
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Thu Mar 19, 2009 9:49 am     Reply with quote

the variation from reading to reading is basically usually NOISE

and the cure is to loop and take say 16 readings and then average ,
by adding them together as you get them - and since they are 10 bit a single long integer ( int16) will serve as he accumulator
then at the end , perform a >>4 to average the 16 readings to ONE value

i think you will be happy with the result
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 19, 2009 12:36 pm     Reply with quote

You have a 5v input range, with a 12-bit A/D. This is 4096 steps.
5v/4096 steps = 1.22 mv/step.

Quote:

with a 4volt input i should read 0xCCC, but instead get 1.CFC 2.CFD 3.D03

You have an offset, and also you have a variation. The offset is probably
caused by your reference voltage not being exactly 5.000 volts. Or, your
input voltage may not be exactly 4.000 volts.
Your input variation is +/- 3 or 4 steps, centered around 0xD00, and
is about 4 to 5 millivolts. That's actually pretty good, given the amount
of noise that's in a normal digital system.
mshearer



Joined: 12 Jan 2009
Posts: 33

View user's profile Send private message

PostPosted: Fri Mar 20, 2009 2:34 am     Reply with quote

1)
Code:

   SSPSTAT   = 0x00;   /* SPI status Register     */
   SSPCON1 = 0x21;   /* SPI control Register 1  */


2) 10Mhz Crystal through HSPLL to 40Mhz

3) Should be 5V, comes in just above so using 5.01/4096

4) need it to be easily transferable away from ccs :S


Thanks for all the replies btw.

A loop to take an average seems a sensible option, I think i'm stuck with a ridiculously small amount of clock cycles for this function however :(


matt
Ttelmah
Guest







PostPosted: Fri Mar 20, 2009 3:42 am     Reply with quote

If you are just using the PIC 5v, then this is your problem.
Look at the data sheet, and how to run the ADC, from a low noise Vref. A typical 5v regulator, will only manage stability in the short term, as loads vary inside the processor, of around 1% _at best_. You are seeing variations, well below this. I'd say the circuit was performing better than expected...
I was asking what you were clocking the _ADC_ off, not the PIC. The noise performance of the ADC, varies with it's clock rate.
Realistically, if you are writing the code in CCS, use the CCS functions. It is never going to be possible to port embedded code, without a fairly major 'rewrite', so why make things more likely to be wrong?. Basically, using the internal functions makes it much easier to port to another chip (all register changes are then done for you), which in normal use, is the more 'likely' change to be needed.
You can generate a 'rolling' average, very efficiently, with something like:
Code:

static int32 sum;
int16 reading

   reading=get_adc_reading(); //read the ADC here
   sum+=reading;
   reading=sum/8; //Use a _binary_ division here, for efficiency
   sum-=reading;



Best Wishes
Guest








PostPosted: Fri Mar 20, 2009 3:47 am     Reply with quote

thanks Ttelmah
very much appreciated
mshearer



Joined: 12 Jan 2009
Posts: 33

View user's profile Send private message

PostPosted: Sat Mar 21, 2009 10:22 am     Reply with quote

actually, one more quick thing. Any idea why my first result is always something way off. Think it used to be always 0xFFF but not sure what it is now.

matt
Ttelmah
Guest







PostPosted: Sat Mar 21, 2009 10:28 am     Reply with quote

OK.
As written, it'll take several cycles, for the 'sum' to build to the required value.
If you want 'instant lock' on the first reading, then modify as follows:
Code:

static int32 sum;
int16 reading;
int1 live=false;

   reading=get_adc_reading(); //read the ADC here
   if (live)
      sum+=reading;
   else {
      sum=reading*8;
      live=true;
   }
   reading=sum/8; //Use a _binary_ division here, for efficiency
   sum-=reading;


Best Wishes
mshearer



Joined: 12 Jan 2009
Posts: 33

View user's profile Send private message

PostPosted: Tue Mar 24, 2009 9:56 am     Reply with quote

great Smile results seem a bit more solid now, as in I'm always getting the same thing.
I think this is probably going to be more down to how I'm providing/measuring my inputs but I seem to get increased inaccuracy the higher the voltage

for example

0.5030V through adc should give 410.923 but gives 410.333 meaning a differnce of 0.590117941. which is pretty acceptable

however this gradually increases up to
4.5023V through adc should give 3678.132 but gives 3695.666 meaning a difference of -17.53415241. which ain't great.



thanks again Ttelmah,

matt
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Tue Mar 24, 2009 10:39 am     Reply with quote

Instead of looking on measurements of arbitrary input voltages, you should rather do a complete transfer function. It will reveal what's wrong with your circuit.
Ttelmah
Guest







PostPosted: Tue Mar 24, 2009 10:47 am     Reply with quote

The 'odds' are that the voltage inside the chip, and possibly on your input, are not what you think they are.
First, what is the actual 'accuracy of you DVM. When was it last calibrated?. What does it use as it's sample 'basis' (depending on how a DVM is designed, for a voltage carrying noise, some will return the peak voltage, while others return the average..). Beware also, that DVM accuracies, are usually quoted as a percentage of 'full scale'.
It actually sounds as if your DVM, may be recording some noise on the 5v rail, to give a higher voltage, than is being seen by the chip.
If the reference 'seen' by the chip, was actually 4.99v, then for 4.5023v, the expected reading would be 3695.67.....

Best Wishes
Ttelmah
Guest







PostPosted: Tue Mar 24, 2009 11:05 am     Reply with quote

Amend that.
You need always with ADC's to look carefully at the transfer function specified by the manufacturer. Look carefully at figure 12. Note that the top of the transfer function, is _not_ Vdd.
The chip actually gives it's maximum reading, 1.5 bits 'above' Vdd, and gives a count of '1', at Vdd/4096. So, the best transfer function, is:

(Reading * (Vdd/4096)) -( Vdd/8192).

So, for a reading of 3695.66, wth a Vin, of 4.5023, the Vref being seen by the chip, is 4.9907v. Remarkably close to 5v!.....

Best Wishes
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