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 support@ccsinfo.com

ADC in PIC 16f877a

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



Joined: 13 Jun 2013
Posts: 5
Location: India

View user's profile Send private message Send e-mail

ADC in PIC 16f877a
PostPosted: Mon Aug 19, 2013 1:04 am     Reply with quote

volts = (float)(adc_value0 * 5)/1023.0;

please kindly explain this line
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

Re: ADC in PIC 16f877a
PostPosted: Mon Aug 19, 2013 5:36 am     Reply with quote

rdevendrakumar1989 wrote:
volts = (float)(adc_value0 * 5)/1023.0;

please kindly explain this line


I use something similar for generic scaling:
#define ADC_VREF 4.096
#define ADC_COUNTS 1024 // 12 bit mode
Volts = (float)adc_value * (ADC_VREF/ADC_COUNTS);

ADC_COUNTS is 2^ADC_BITS, for a 10 bit ADC, ie. most commonly used in PICs, ADC_COUNTS is 1024. Note that's not the 1023 you commonly see, as in your example, but the error is, of course, small.

The voltage reference is the reference voltage applied to the ADC. Many applications simply use the 5V supply as the reference, hence the 5 in your example. However, the supply is rarely precisely 5V, and is often noisy and varies, so its not a good reference. If you need greater precision than maybe 7 or 8 bits, and 10 bits implies that you do, then you generally need a proper reference, generally that'll be some external IC, but some PICs have a fairly respectable internal reference.

My example has an external 4.096V reference and 12 bit ADC. That gives a precise 4mV per bit scaling. My choice of placement of the brackets is also worth noting, as it allows the compiler to collapse the constants so that the division is not performed at run-time, only a single float multiplication.
Ttelmah



Joined: 11 Mar 2010
Posts: 19359

View user's profile Send private message

PostPosted: Mon Aug 19, 2013 8:05 am     Reply with quote

Actually the use of 1023/1024, is much more complex than you may think.....

It depends on what the actual transfer function of the ADC 'is'. Some, though having 1024 steps, have the end steps 'at' the supply rails, so though there are 1024 'levels', there are only 1023 actual 'risers' (thinking in staircase terms) in the span. This is where the '1023' comes from. The earliest PIC 10bit ADC's behave like this. However some years ago, TI, deliberately altered the way their ADC's worked so that you could use the binary 'span', for much faster maths, and some years ago, Microchip did the same. So for the current ADC's, the correct divisor is 1024.
However you have to be careful with this, since they got the 1024 steps, by adding half a step at the bottom of the ADC range. So the '0' count actually spans up to (technically) 0.5 counts, and the base point of the linear conversion is actually -0.5 step.
If you are really trying to get best accuracy, this becomes important. However most people don't have a sufficiently good reference, or input circuitry to ever see the difference.
Microchip used to have an AN about the span, and best fit code, with reference also to some of the earliest ADC's and the effects these have.
The code I use, based upon the best fit function for the current ADC's is:

((ADC*2)-1)/2048 * (VrefH-VrefL/2048).

This exactly matches the curves published by Microchip, with the step points being where described from top to bottom of the range.

Best Wishes
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Mon Aug 19, 2013 10:01 am     Reply with quote

Ttelmah wrote:
Actually the use of 1023/1024, is much more complex than you may think.....

It depends on what the actual transfer function of the ADC 'is'. Some, though having 1024 steps, have the end steps 'at' the supply rails, so though there are 1024 'levels', there are only 1023 actual 'risers' (thinking in staircase terms) in the span. This is where the '1023' comes from. The earliest PIC 10bit ADC's behave like this. However some years ago, TI, deliberately altered the way their ADC's worked so that you could use the binary 'span', for much faster maths, and some years ago, Microchip did the same. So for the current ADC's, the correct divisor is 1024.

However you have to be careful with this, since they got the 1024 steps, by adding half a step at the bottom of the ADC range. So the '0' count actually spans up to (technically) 0.5 counts, and the base point of the linear conversion is actually -0.5 step.
If you are really trying to get best accuracy, this becomes important. However most people don't have a sufficiently good reference, or input circuitry to ever see the difference.
Microchip used to have an AN about the span, and best fit code, with reference also to some of the earliest ADC's and the effects these have.
The code I use, based upon the best fit function for the current ADC's is:

((ADC*2)-1)/2048 * (VrefH-VrefL/2048).

This exactly matches the curves published by Microchip, with the step points being where described from top to bottom of the range.

Best Wishes


Hmm, its not even that simple, err, even more complicated than that. I went digging in Microchip's application notes. I found a few relevant ones, most notably AN693 and 1152. Both are internally confused on this point, and are not consistent with each other. For example, the text of AN1152 says "Voltage resolution of an ADC is defined as the ratio of full scale voltage range to the number of digital levels that are accommodated in that range." If we're talking about a 10bit ADC there are clearly 2^n, i.e. 1024 "digital levels". Therefore the resolution is Vref/1024, and there are 1023 intervals or steps. Where we place the decision points for those levels is a simple matter of offsetting; the "gain", i.e. the scaling, is determined by the resolution. Then AN1152 references equation 1 which states "Voltage Resolution 1 Least Significant bit (LSb) value = full scale voltage range/ (2^n - 1). That's contradictory to the text, something's clearly wrong. A later 12 bit example gives the resolution for 3V range as 0.7326mV per bit, which is 3V/4095, or 3V/(2^n -1).

AN693 does things differently. In equation 1 it states the OutputCode = F.S. * Vin/Vref where F.S. is presumably full scale, though it never explicitly states it. For a 10 bit convertor, full scale ADC output is 1023. Substituting and rearranging that gives the familiar Vin = OutputCode * Vref/1023. However, later it states, "The largest value that can be obtained from the A/D converter is (N-1)/N, where N is
the resolution in bits. Referring to Figure 2, the largest output value that the 3-bit A/D converter can produce is 7/8ths of the full-scale reference voltage" and in figure 2 it gives a graphical representation of the decision points for a hypothetical three bit converter, clearly showing the maximum output code as 7, i.e. 2^3 -1. These together show that the maximum output code is not equivalent to Vref, it is one bit BELOW Vref, and that equation 1 should have been OutputCode = (F.S. + 1) * Vin/Vref, or Vin = OutputCode * Vref/1024. Later, in the section on Code Width below Figure 2, there is this, "So 1 LSb = VREF/2^N, where N is the number of bits of resolution. For example, if a 4.096 volt reference is used
with a 12-bit converter, 1 LSb will have a weight of 4.096 V/2^12, or 1 mV." That's "1024" scaling, not "1023". Microchip, make up your mind!

Putting the decision points halfway between voltage levels works fine. For example with a 4.096V reference and a 10 bit convertor, it ensures that 4mV is consistently 0x001, and that if the ADC were perfect and there was no noise, anything from 2mV <= Vin < 6mV give output code of 0x001. Note 0x000 represents anything from 0V <= Vin < 2mV and that 0xFFF is anything from 4.090V upwards, and is thus at least 6mV wide. This would unbalance the output histogram for random voltages across the whole input range, but that doesn't matter much. If we consider what happens with a decent amount, eg. over 1 lsb, of noise, and apply averaging to the result, we still get much the same results. With the decision points half a bit higher, i.e. at 4mV, 8mV ... 4.092V we'd end up with 4mV averaging to half a bit, which is clearly not what we might expect.

Bipolar ADC present related problems which rarely concern PIC users as PIC ADCs are generally unipolar. The problem stems, just as the resolution thing above in fact, from the range of digital values that can be represented. ADCs with two's complement outputs, and that means most but by no means all, have an inherently unbalanced voltage range, with the negative region being one bit's worth more. If we consider a 13 bit two's comp bipolar ADC with 4.096V Vref, its range would typically be -4.096V <= Vin <= 4.092V, with resolution of 4mV per bit. You might expect the codes to be equally distributed, but they are not. This is because there are 1024 negative digital codes, one for zero, but 1023 positive codes making 2048, or 13 bits worth, in all. The half-bit offset of the decision point makes anything -2mV <= +2mV give 0 as an output, which is fine. Some high resolution ADCs have sign and magnitude representation, and these have equal positive and negative ranges, both of 2^(n-1) - 1, but also have two zeros, positive and negative, which probably overlap, or are half a bit wide each. Which a convertor will give probably depends on which sign the voltage has recently been as these sorts of convertors are often delta-sigma types with heavy digital filtering. They also tend to have built-in processors of PICish power level to do all the processing.
Ttelmah



Joined: 11 Mar 2010
Posts: 19359

View user's profile Send private message

PostPosted: Mon Aug 19, 2013 11:17 am     Reply with quote

I agree.
You will find that Microchip disagree with themselves over the step points and the transfer function, in the published notes.
However they have (or did have a little while ago), a note available 'on request' (for some reason they don't publish it), which 'purports' to give the transfer functions for all their ADC's.
It agrees with what is measured (on PIC8's etc.), and this is the function I posted.
I was trying to keep things reasonably 'simple'.

Fun.....
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