Introduction
The ADC is used to convert an analogue input signal (an analogue voltage within a specific range) to a corresponding digital data that can be processed and used by the PIC. The PIC, without the conversion to digital, can do almost nothing with an analogue input (unless you use the analogue comparator). But you probably already know this much.
I have seen that many people, especially newbies, are not clear regarding the modalities of using the ADC module of PIC microcontroller. Many even assume it to be a daunting task after looking at all the possible settings and configurations. Hence, here I have made an effort to explain everything I could about the ADC module of the PIC microcontroller, by using the popular PIC 16F877A as reference.
The PIC 16F877A has a 10-bit ADC. That means that the ADC result can have 2^10 (2 to the power 10) values. That's 1024 values. So, the ADC reading can vary from 0 to 1023.
______________________________________________________________________________________________________________
Voltage Reference and ADC result
The ADC has a reference voltage. For now, let's say that the reference voltage is 5V.
So, your input voltage has to range from 0V to 5V. You can't input anything higher than 5V since that's your positive reference voltage. You can't input anything lower than 0V since that's your negative reference voltage. Anything in between is read and converted by the PIC ADC.
So, what is the conversion value/result you obtain?
If the ADC input is 5V, the output is maximum as the input is at its maximum level. So, ADC conversion result is 1023. If ADC input is 0V, the output is minimum as the input is at its minimum level. So, ADC conversion result is 0. If ADC input is 2.5V, you might have figured out that the ADC conversion result would be 511. Since the input is midway between its maximum and minimum possible values, so is the output. So the input and output have a pretty simple linear relationship. One thing to note here is that the ADC conversion result is 511, not 512, not 511.5. Even though 1023/2 = 511.5, the ADC cannot give results in decimal points and it will only output an integer. Thus 511 is obtained. Take note that the output is NOT rounded off. That's why it's not 512. So, if you had gotten an expected ADC conversion result of say 511.8, the real result would be 511. There is no rounding off, so you get 511.
The simple linear relationship between ADC input and output is given by:
ADC result = (Vin * 1023) / Vref
= (Vin / Vref) * 1023
This is because (ADC result / 1023) = (Vin / Vref)
You probably figured this out. It's quite simple. The ratio of ADC conversion result to maximum possible reading is equal to the ratio of input voltage (Vin) to maximum possible input voltage (Vref). This is because the input voltage is a fraction of the maximum possible voltage and hence the ADC output result is the same fraction of the maximum possible value – 1023 in our case.
______________________________________________________________________________________________________________
Example:
So, for a reference of 5.00V, what will be the ADC result when input voltage is 1.23V?
Solution:
Expected value = (1.23 / 5.00) * 1023 = 251.658
So, ADC conversion result = 251 as you can't have a fractional result.
______________________________________________________________________________________________________________
Above, the situation considered was simple as reference voltage is 5V with respect to ground.
Now the thing to understand is, for reference, the PIC has two pins: VREF+ and VREF-. So, for 5V reference, 5V is to applied at VREF+ and 0V (ground) is to be applied at VREF-. The PIC has facilities for using an internal reference. So, if you want 5V reference, a specific configuration of the ADC registers will allow you to select the PIC VDD to be used as VR)EF+ and PIC VSS to be used as VREF-. (We will look at the register configurations later in the tutorial).
The advantage here is that you do not need to connect +5V and 0V externally. This means that you can save 2 I/O pins. What you have to understand here is that the internal reference is equal to VDD, not 5V. So, if VDD = 5V, VREF+ = 5V. But if VDD = 3.3V, VREF+ = 3.3V. In both cases, VSS is 0V, so VREF- is 0V.
Now, let's say we want to measure an input that we know will always be less than 2V. So, we know that the maximum ADC reading in such a situation will be that for the maximum voltage of 2V in this case. That would produce a corresponding ADC conversion result of: (2/5)*1023 = 409. So, we know that we'll never have a result greater than 409. So, the result is in 409 steps and effectively the resolution is (log 409 / log 2) = 8.7. So, in this case, we're not utilizing the entire 10-bit range of the ADC. So, now, to improve accuracy, we can use an external reference voltage of 2.5V. So, maximum ADC result now is: (2/2.5)*1023 = 818. The resolution now is (log 818 / log 2) = 9.7. In this case, we've made much better use of the ADC. In terms of accuracy, since we have a higher resolution for a reference voltage of 2.5V, this will give more accurate readings. Let's consider the situation with 5V reference voltage: For 2V, the ADC conversion result is 409. So, that's 409 steps for 2V. Each step corresponds to (2/409) = 0.0049V. For the second situation, we have 818 steps. Each step corresponds to (2/818) = 0.0024V. So, we have twice as much accuracy with a 2.5V reference than for a 5V reference.
Let's consider another situation. Let's say we have an input that will vary between 2.5V and 3.3V, never less than 2.5V, never greater than 3.3V. As you may have already guessed, instead of using a 5V reference, to improve resolution and accuracy, we can use a 3.5V reference. So, maximum reading will be (3.3/3.5)*1023 = 964. In this case, we should also consider minimum reading: (2.5/3.5)*1023 = 730. So, the reading varies between 730 and 964. One thing to note here is, although we've used a 3.5V reference, the range is still very small as we have (964-730+1) = 235 steps. We could improve this situation. But how, you may ask.
Remember, I mentioned that the PIC had 2 pins for reference: VREF+ and VREF-. All this while, we've talked about VREF+. Now, we'll go on to VREF-. If VREF+ is at 5V and VREF- is at 0V (which is the situation we've considered thus far), the reference voltage is (5-0) = 5V. But let's say, VREF- is at 3V, and not 0V. What's the reference voltage now? Is it still 5V as VREF+ is at 5V? The answer is: NO. You must remember that all this while, the reference voltage was 5V as VREF+ was at a potential of 5V with reference to VREF-. So, if VREF+ is 5V and VREF- is 3V, while VREF+ is at a potential of 5V above ground, what really matters is its potential with reference to VREF-. With reference to VREF-, VREF+ is at a potential of 2V. So, the reference voltage is in fact 2V, with VREF- of 3V and VREF+ of 5V. So, the acceptable input voltage range is 3V to 5V.
So, for the said situation of input between 2.5V and 3.3V, we can improve accuracy and resolution by altering the reference voltage. We've already used 3.5V as VREF+. We know input will always be above 2.5V, so we can use 2.0V for VREF-. Thus, our reference voltage is (3.5-2.0) = 1.5V. So, when input voltage is 2.5V, what is the ADC result now? Let's revise our previous formula a bit now.
Previously, I mentioned this:
ADC Result = (Vin / Vref) * 1023
Vin is actually (Input Voltage) – (Ref-)
Vref is actually (Ref+) - (Ref-)
So, ADC Result = [(Vin-VREF-) / (VREF+ - VREF-)] * 1023
For the above situation, VREF+ = 3.5V, VREF- = 2.0V, Vin = 2.5V
So, ADC Result = [(2.5-2.0)/(3.5-2.0)]*1023
= 341
This is the minimum value.
For 3.3V input, ADC Result = [(3.3-2.0)/(3.5-2.0)]*1023
= 886
So, our range of values now lies between 341 and 886. That's (886-341+1) = 546 steps. We've more than doubled the accuracy by altering the reference voltage.
I hope you've understood how to use the VREF+ and VREF- pins. I'll move on to the coding later. There are a few more things to consider here that are covered in part 6.
______________________________________________________________________________________________________________
Example:
A circuit is set up for analogue to digital conversion using the PIC's internal ADC, with VREF+ = 4.0V and VREF- = 2.0V. A few input voltages are measured: 2.2V, 2.35V, 2.8V, 3.36V, 3.46V, 3.9V. What are the corresponding ADC conversion results?
Solution:
For 2.2V:
ADC conversion result = [(2.2-2.0)/(4.0-2.0)]*1023 = 102
For 2.35V:
ADC conversion result: [(2.35-2.0)/(4.0-2.0)]*1023 = 179
For 2.8: Result = 409
For 3.36V: Result = 695
For 3.46V: Result = 746
For 3.9V: Result = 971
______________________________________________________________________________________________________________
Continued in Part 2................
The ADC is used to convert an analogue input signal (an analogue voltage within a specific range) to a corresponding digital data that can be processed and used by the PIC. The PIC, without the conversion to digital, can do almost nothing with an analogue input (unless you use the analogue comparator). But you probably already know this much.
I have seen that many people, especially newbies, are not clear regarding the modalities of using the ADC module of PIC microcontroller. Many even assume it to be a daunting task after looking at all the possible settings and configurations. Hence, here I have made an effort to explain everything I could about the ADC module of the PIC microcontroller, by using the popular PIC 16F877A as reference.
The PIC 16F877A has a 10-bit ADC. That means that the ADC result can have 2^10 (2 to the power 10) values. That's 1024 values. So, the ADC reading can vary from 0 to 1023.
______________________________________________________________________________________________________________
Voltage Reference and ADC result
The ADC has a reference voltage. For now, let's say that the reference voltage is 5V.
So, your input voltage has to range from 0V to 5V. You can't input anything higher than 5V since that's your positive reference voltage. You can't input anything lower than 0V since that's your negative reference voltage. Anything in between is read and converted by the PIC ADC.
So, what is the conversion value/result you obtain?
If the ADC input is 5V, the output is maximum as the input is at its maximum level. So, ADC conversion result is 1023. If ADC input is 0V, the output is minimum as the input is at its minimum level. So, ADC conversion result is 0. If ADC input is 2.5V, you might have figured out that the ADC conversion result would be 511. Since the input is midway between its maximum and minimum possible values, so is the output. So the input and output have a pretty simple linear relationship. One thing to note here is that the ADC conversion result is 511, not 512, not 511.5. Even though 1023/2 = 511.5, the ADC cannot give results in decimal points and it will only output an integer. Thus 511 is obtained. Take note that the output is NOT rounded off. That's why it's not 512. So, if you had gotten an expected ADC conversion result of say 511.8, the real result would be 511. There is no rounding off, so you get 511.
The simple linear relationship between ADC input and output is given by:
ADC result = (Vin * 1023) / Vref
= (Vin / Vref) * 1023
This is because (ADC result / 1023) = (Vin / Vref)
You probably figured this out. It's quite simple. The ratio of ADC conversion result to maximum possible reading is equal to the ratio of input voltage (Vin) to maximum possible input voltage (Vref). This is because the input voltage is a fraction of the maximum possible voltage and hence the ADC output result is the same fraction of the maximum possible value – 1023 in our case.
______________________________________________________________________________________________________________
Example:
So, for a reference of 5.00V, what will be the ADC result when input voltage is 1.23V?
Solution:
Expected value = (1.23 / 5.00) * 1023 = 251.658
So, ADC conversion result = 251 as you can't have a fractional result.
______________________________________________________________________________________________________________
Above, the situation considered was simple as reference voltage is 5V with respect to ground.
Now the thing to understand is, for reference, the PIC has two pins: VREF+ and VREF-. So, for 5V reference, 5V is to applied at VREF+ and 0V (ground) is to be applied at VREF-. The PIC has facilities for using an internal reference. So, if you want 5V reference, a specific configuration of the ADC registers will allow you to select the PIC VDD to be used as VR)EF+ and PIC VSS to be used as VREF-. (We will look at the register configurations later in the tutorial).
The advantage here is that you do not need to connect +5V and 0V externally. This means that you can save 2 I/O pins. What you have to understand here is that the internal reference is equal to VDD, not 5V. So, if VDD = 5V, VREF+ = 5V. But if VDD = 3.3V, VREF+ = 3.3V. In both cases, VSS is 0V, so VREF- is 0V.
Now, let's say we want to measure an input that we know will always be less than 2V. So, we know that the maximum ADC reading in such a situation will be that for the maximum voltage of 2V in this case. That would produce a corresponding ADC conversion result of: (2/5)*1023 = 409. So, we know that we'll never have a result greater than 409. So, the result is in 409 steps and effectively the resolution is (log 409 / log 2) = 8.7. So, in this case, we're not utilizing the entire 10-bit range of the ADC. So, now, to improve accuracy, we can use an external reference voltage of 2.5V. So, maximum ADC result now is: (2/2.5)*1023 = 818. The resolution now is (log 818 / log 2) = 9.7. In this case, we've made much better use of the ADC. In terms of accuracy, since we have a higher resolution for a reference voltage of 2.5V, this will give more accurate readings. Let's consider the situation with 5V reference voltage: For 2V, the ADC conversion result is 409. So, that's 409 steps for 2V. Each step corresponds to (2/409) = 0.0049V. For the second situation, we have 818 steps. Each step corresponds to (2/818) = 0.0024V. So, we have twice as much accuracy with a 2.5V reference than for a 5V reference.
Let's consider another situation. Let's say we have an input that will vary between 2.5V and 3.3V, never less than 2.5V, never greater than 3.3V. As you may have already guessed, instead of using a 5V reference, to improve resolution and accuracy, we can use a 3.5V reference. So, maximum reading will be (3.3/3.5)*1023 = 964. In this case, we should also consider minimum reading: (2.5/3.5)*1023 = 730. So, the reading varies between 730 and 964. One thing to note here is, although we've used a 3.5V reference, the range is still very small as we have (964-730+1) = 235 steps. We could improve this situation. But how, you may ask.
Remember, I mentioned that the PIC had 2 pins for reference: VREF+ and VREF-. All this while, we've talked about VREF+. Now, we'll go on to VREF-. If VREF+ is at 5V and VREF- is at 0V (which is the situation we've considered thus far), the reference voltage is (5-0) = 5V. But let's say, VREF- is at 3V, and not 0V. What's the reference voltage now? Is it still 5V as VREF+ is at 5V? The answer is: NO. You must remember that all this while, the reference voltage was 5V as VREF+ was at a potential of 5V with reference to VREF-. So, if VREF+ is 5V and VREF- is 3V, while VREF+ is at a potential of 5V above ground, what really matters is its potential with reference to VREF-. With reference to VREF-, VREF+ is at a potential of 2V. So, the reference voltage is in fact 2V, with VREF- of 3V and VREF+ of 5V. So, the acceptable input voltage range is 3V to 5V.
So, for the said situation of input between 2.5V and 3.3V, we can improve accuracy and resolution by altering the reference voltage. We've already used 3.5V as VREF+. We know input will always be above 2.5V, so we can use 2.0V for VREF-. Thus, our reference voltage is (3.5-2.0) = 1.5V. So, when input voltage is 2.5V, what is the ADC result now? Let's revise our previous formula a bit now.
Previously, I mentioned this:
ADC Result = (Vin / Vref) * 1023
Vin is actually (Input Voltage) – (Ref-)
Vref is actually (Ref+) - (Ref-)
So, ADC Result = [(Vin-VREF-) / (VREF+ - VREF-)] * 1023
For the above situation, VREF+ = 3.5V, VREF- = 2.0V, Vin = 2.5V
So, ADC Result = [(2.5-2.0)/(3.5-2.0)]*1023
= 341
This is the minimum value.
For 3.3V input, ADC Result = [(3.3-2.0)/(3.5-2.0)]*1023
= 886
So, our range of values now lies between 341 and 886. That's (886-341+1) = 546 steps. We've more than doubled the accuracy by altering the reference voltage.
I hope you've understood how to use the VREF+ and VREF- pins. I'll move on to the coding later. There are a few more things to consider here that are covered in part 6.
______________________________________________________________________________________________________________
Example:
A circuit is set up for analogue to digital conversion using the PIC's internal ADC, with VREF+ = 4.0V and VREF- = 2.0V. A few input voltages are measured: 2.2V, 2.35V, 2.8V, 3.36V, 3.46V, 3.9V. What are the corresponding ADC conversion results?
Solution:
For 2.2V:
ADC conversion result = [(2.2-2.0)/(4.0-2.0)]*1023 = 102
For 2.35V:
ADC conversion result: [(2.35-2.0)/(4.0-2.0)]*1023 = 179
For 2.8: Result = 409
For 3.36V: Result = 695
For 3.46V: Result = 746
For 3.9V: Result = 971
______________________________________________________________________________________________________________
Continued in Part 2................