I'm still trying to make the ADC on a PIC16F877 work correctly.
I've wired a potentiometer to pin 2 (AN0) of the 'F877 . AN3 is wired to
a very precise +5V voltage reference. I'm summing 2048 10bits ADC readings
to a float TOTAL variable. Then I divide TOTAL by 1023 (max reading) and
multiply it by 5 (max voltage). Here is an example of my readings:
PIC ADC Multimeter on AN0
0.002V 0.000V
0.370V 0.000V
0.372V 0.001V
0.800V 0.355V
1.000V 0.600V
2.000V 1.650V
3.000V 2.755V
4.000V 3.911V
5.000V 4.958V
5.180V and up 4.980V
Can someone please help me with this?
Best regards,
Brusque
-----------------------------------
Edson Brusque
Research and Development
C.I.Tronics Lighting Designers Ltda
(47) 323-2685 / (47) 9993-6453
Blumenau - SC - Brazil
-----------------------------------
I'm still trying to make the ADC on a PIC16F877 work correctly.
I've wired a potentiometer to pin 2 (AN0) of the 'F877 . AN3 is wired to
a very precise +5V voltage reference. I'm summing 2048 10bits ADC readings
to a float TOTAL variable. Then I divide TOTAL by 1023 (max reading) and
multiply it by 5 (max voltage). Here is an example of my readings:
PIC ADC Multimeter on AN0
0.002V 0.000V
0.370V 0.000V
0.372V 0.001V
0.800V 0.355V
1.000V 0.600V
2.000V 1.650V
3.000V 2.755V
4.000V 3.911V
5.000V 4.958V
5.180V and up 4.980V
Can someone please help me with this?
Best regards,
Brusque
-----------------------------------
Edson Brusque
Research and Development
C.I.Tronics Lighting Designers Ltda
(47) 323-2685 / (47) 9993-6453
Blumenau - SC - Brazil
-----------------------------------
> How long is Tad in your application? Does this meet the specifications in
the
> data sheet?
Here's my ADC convertion function (in C):
float get_analog_voltage()
{
word x;
float total;
total = 0;
for (x = 0; x < 2048; x++) {
delay_us(20);
ADCON0.GO = 1;
while(ADCON0.GO);
total += (ADRESH * 256 + ADRESL);
}
total /= 2048;
total /= 1023;
total *= 5;
return total;
}
As you can see, I'm *waiting* until the GO bit is cleared by the ADC,
telling that the convertion is over. I don't think I have to care with TAD
this way.
> What clock are you using to drive the ADC? The internal RC or off the CPU
> clock? What frequency CPU clock?
CPU is working at 20MHz. I'm using the CPU Clock (FOSC/32).
> Bypass caps on the '877?
No bypass. Have I use any? What value? How is it wired?
> How do you have ADCON0 and ADCON1 set up?
ADCON1 = 0b10000101; // Bit 7 = ADFM (A/D Result format select)
// 1 = Right Justified
// 0 = Left Justified
// Bit 6:4 = Unimplemented
// Bit 3:0 = Port Configuration
// 0000 = All Analog
// 0100 = RA0,1,3 Analog
// 0101 = RA0,1 Analog, RA3 VREF+
// 1110 = RA0 Analog
adresult = ((UINT16)(adresh)) << 8) | (UINT16)(adres);
total += adresult;
Also, you would do better mathmatically to change the sequence of the mult/divs
to
total = total / 2048 * 5 / 1023;
This is a constant expression, and since total is already float you can have the
compiler optimize it better for you. It'll run faster, too, because only one
floating point op will be performed rather than 3.
> Off the top of my head, I don't have the data sheet handy, but as I recall
you
> can't use Fosc/32 at 20MHz. You need to go to the FRC mode.
The PIC16F87X datasheet says (DS30292A-page 127) that "When the device
frequencies is greater than 1MHz, the RC A/D conversion clock source is only
recommended for sleep operation".
Regards,
Brusque
-----------------------------------
Edson Brusque
Research and Development
C.I.Tronics Lighting Designers Ltda
(47) 323-2685 / (47) 9993-6453
Blumenau - SC - Brazil
-----------------------------------
> Hello,
>
> I'm still trying to make the ADC on a PIC16F877 work correctly.
>
> I've wired a potentiometer to pin 2 (AN0) of the 'F877 . AN3 is wired to
> a very precise +5V voltage reference. I'm summing 2048 10bits ADC readings
> to a float TOTAL variable. Then I divide TOTAL by 1023 (max reading) and
> multiply it by 5 (max voltage). Here is an example of my readings:
>
> PIC ADC Multimeter on AN0
> 0.002V 0.000V
What value should you get for 0/n? (Answer is ZERO!!!)
What value should you get for 0*n? (Answer is ZERO!!!)
Obviously, either the equation is NOT doing this,
or the A-D is NOT giving you a ZERO for the zero volt input.
Did you tell it to Right justify the 10 bit result?
> Can someone please help me with this?
>
> Best regards,
>
> Brusque
>
> -----------------------------------
> Edson Brusque
> Research and Development
> C.I.Tronics Lighting Designers Ltda
> (47) 323-2685 / (47) 9993-6453
> Blumenau - SC - Brazil
> -----------------------------------
--
*
| __O Thomas C. Sefranek .....tcsKILLspam.....cmcorp.com
|_-\<,_ Amateur Radio Operator: WA1RHP
(*)/ (*) Bicycle mobile on 145.41, 448.625 MHz
ARRL Instructor, Technical Specialist, VE Contact.
hamradio.cmcorp.com/inventory/Inventory.html http://www.harvardrepeater.org
>Edson Brusque wrote:
>
>> Hello,
>>
>> I'm still trying to make the ADC on a PIC16F877 work correctly.
>>
>> I've wired a potentiometer to pin 2 (AN0) of the 'F877 . AN3 is wired
to
>> a very precise +5V voltage reference. I'm summing 2048 10bits ADC
readings {Quote hidden}
>> to a float TOTAL variable. Then I divide TOTAL by 1023 (max reading) and
>> multiply it by 5 (max voltage). Here is an example of my readings:
>>
>> PIC ADC Multimeter on AN0
>> 0.002V 0.000V
>
>What value should you get for 0/n? (Answer is ZERO!!!)
>What value should you get for 0*n? (Answer is ZERO!!!)
>
>Obviously, either the equation is NOT doing this,
>or the A-D is NOT giving you a ZERO for the zero volt input.
>
>Did you tell it to Right justify the 10 bit result?
>
>
>
>> Can someone please help me with this?
>>
>> Best regards,
>>
>> Brusque
>>
>> -----------------------------------
>> Edson Brusque
>> Research and Development
>> C.I.Tronics Lighting Designers Ltda
>> (47) 323-2685 / (47) 9993-6453
>> Blumenau - SC - Brazil
>> -----------------------------------
>
>--
> *
> | __O Thomas C. Sefranek RemoveMEtcsTakeThisOuTcmcorp.com
> |_-\<,_ Amateur Radio Operator: WA1RHP
> (*)/ (*) Bicycle mobile on 145.41, 448.625 MHz
>
>ARRL Instructor, Technical Specialist, VE Contact.
>hamradio.cmcorp.com/inventory/Inventory.html
>http://www.harvardrepeater.org
>
> You need 2 x Tad times between starting measurements.
delay_us(20); // 20us
total += (ADRESH * 256 + ADRESL); // about 18us
This makes for a total of 38us between measurements. That's not
enough???
> It looks like you need a pot below 7K, but I'm not sure on that yet.
I've tried a 1K trimpot. The values seems much better, but it's still
not what I was expecting.
> Tacq needs to be about 12 uS or longer
Can you please explain TAD, TACQ, etc? I'm explicitly waiting 20us
before I set the GO bit.
> 20 MHz on the 'C77 is the absolute limit for the Fosc/32 mode. See what
happens when you try to run the whole thing slower (use FRC mode).
I've tried FRC. Almost same results.
> Check your C compiler's output to make sure that it's doing
> <snip>
> adresult = adresh;
> adresult <<= 8;
> adresult |= adres;
> total += adresult;
This seems to make a diference!!! I'm not sure why.
I make that other line as:
total = total * 5 / 2048 / 1023;
Now I have:
with the 1K trimpot and FOSC/32
Multimeter PIC ADC
0.000V 0.003V
1.000V 0.972V
2.000V 1.996V
2.500V 2.570V
3.000V 3.030V
4.000V 4.065V
5.000V 5.000V
with the 1K trimpot and FRC
Multimeter PIC ADC
0.000V 0.001V
1.000V 0.966V
2.000V 1.992V
2.500V 2.511V
3.000V 3.016V
4.000V 4.052V
5.000V 5.000V
with the 10K trimpot and FRC
Multimeter PIC ADC
0.000V 0.002V
1.000V 0.960V
2.000V 1.989V
2.500V 2.506V
3.000V 3.022V
4.000V 4.060V
5.000V 5.000V
This means, more precise results with smaller resistance knobs. Also FRC
is more precise than FOSC/32 (@20MHz clock).
Regards,
Brusque
-----------------------------------
Edson Brusque
Research and Development
C.I.Tronics Lighting Designers Ltda
(47) 323-2685 / (47) 9993-6453
Blumenau - SC - Brazil
-----------------------------------
IIRC, 10k was the absolute limit for the ADC, in that at that resistance the
internal holding cap would take too long to charge. In theory, this would be a
linear relationship, which it is in your case.
At the lower voltages you are as much as .3 v off, when the pot is giving close
to 10k of resistance to the ADC. At 5v you are only .033 off, corresponding to
nearly zero resistance. If you have to have such a large resistance for the
ADC, you should consider an op-amp or other device to take your resistance and
convert it to a voltage.
For some applications (such as using a thermister) this is ok, since the
relationship is linear, and you're going to calibrate the thermister anyway, so
the error is not so much of an issue.
Also, it sounds like you may be unsure of what we mean when we talk about the
Tad. I haven't checked your figures, but make sure the a/d is set up to either
the cpu clock or the internal rc clock in such as way that Tad is sufficient.
It has nothing to do with waiting for the conversion to complete, it has to do
with how much time the cap needs to charge, and a few other factors as well.
> > What size pot? Too large and it won't work.
>
> Here's another table I've made using a small size, precision 20-turn 10K
> trimpot. Pin 1->GND, 2->PICADC, 3->VCC.
>
> Multimeter vs. ADC input
> 0.198V 0.000V
> 1.000V 0.753V
> 1.274V 1.000V
> 2.000V 1.783V
> 2.220V 2.000V
> 3.000V 2.850V
> 3.168V 3.000V
> 4.000V 3.922V
> 4.080V 4.000V
> 5.000V 4.966V
> 5.070V (and up) 4.980V
>
> > How long is Tad in your application? Does this meet the specifications in
> the
> > data sheet?
>
> Here's my ADC convertion function (in C):
>
> float get_analog_voltage()
> {
> word x;
> float total;
>
> total = 0;
> for (x = 0; x < 2048; x++) {
> delay_us(20);
>
> ADCON0.GO = 1;
> while(ADCON0.GO);
>
> total += (ADRESH * 256 + ADRESL);
> }
> total /= 2048;
> total /= 1023;
> total *= 5;
>
> return total;
> }
>
> As you can see, I'm *waiting* until the GO bit is cleared by the ADC,
> telling that the convertion is over. I don't think I have to care with TAD
> this way.
>> "The maximum recommended
>> impedance for analog sources is 10 kohm. As the
>> impedance is decreased, the acquisition time may be
>> decreased."
>
> Mmmm, I think I'll make a dumb question, but... what about if I put a
>pair of resistors on the input:
>
> VDD
> |
> /
> \ 4K7 <-- R1
> /
> \
> |
> +---- to pic ADC input
> |
> /
> \ 4K7 <-- R2
> /
> \
> |
> GND
>
> would it lower the impedance?
>
If you stand on the ADC input node and look out at the ckt, the
effective resistance is 4K7/2 = ~2K3. Of course Vadc is also
lower ~Vdd/2. Thevenin equivalent of above:
___
/Voc\______ Rth _______
\___/ \/\/\/
|
Gnd
> Also, it sounds like you may be unsure of what we mean when we talk about
the
> Tad. I haven't checked your figures, but make sure the a/d is set up to
either
> the cpu clock or the internal rc clock in such as way that Tad is
sufficient.
> It has nothing to do with waiting for the conversion to complete, it has
to do
> with how much time the cap needs to charge, and a few other factors as
well.
Tad is the convertion time, right? I think FOSC/32 @ 20MHz (3.2us) would
be more than sufficient. FRC gives about (4us). TACQ is the aquisition time
(the time allowed the charge the capacitor). My application is taking 65.2uS
between the aquisitions, that would be enough too.
Now I'm using 10MHz as the final application would probably run on 4MHz
anyway.
with the 1K trimpot and FRC
Multimeter PIC ADC
0.000V 0.004V
1.000V 0.975V
2.000V 2.001V
2.500V 2.518V
3.000V 3.030V
4.000V 4.063V
4.990V 5.000V
with the 1K trimpot and FOSC/32
Multimeter PIC ADC
0.000V 0.002V
1.000V 0.969V
2.000V 1.998V
2.500V 2.513V
3.000V 3.025V
4.000V 4.060V
5.015V 5.000V
It's still not the precision I'm looking for. Maybe at 4MHz and FOSC/32
(?).
> Mmmm, I think I'll make a dumb question, but... what about if I put a
> pair of resistors on the input:
>
> VDD
> |
> /
> \ 4K7
> /
> \
> |
> +---- to pic ADC input
> |
> /
> \ 4K7
> /
> \
> |
> GND
>
> would it lower the impedance?
Yes, it is something I'm doing with a circuit of mine. The trade-off here is
that when you do this you are lowering the voltage range you can reach with the
pot, and unless you lower the Vref accordingly you'll lose some of the A/D range
(which may be acceptable to you if you don't need all ten bits) As well as
having to use 1% resisters (or calibrate the ones you do use.)
> Edson Brusque wrote:
>
> > Hello,
> >
> > I'm still trying to make the ADC on a PIC16F877 work correctly.
> >
> > I've wired a potentiometer to pin 2 (AN0) of the 'F877 . AN3 is wired to
> > a very precise +5V voltage reference. I'm summing 2048 10bits ADC readings
> > to a float TOTAL variable. Then I divide TOTAL by 1023 (max reading) and
> > multiply it by 5 (max voltage). Here is an example of my readings:
> >
> > PIC ADC Multimeter on AN0
> > 0.002V 0.000V
>
Assuming the software it's ok, you have 80% a measuring error or
noise problem. First, this looks like an offset error. Have you use
some sort of breadboard without nice ground lay-out? Make a
measurement with a good voltmeter (4 1/2 digits ) between 877
ground and adc input pin, you will get something... change the
ground point let say near the power supply, you will get something
else...
Have you filtered the analogic input signal ?
Finally I've manage with my 10bites adc readings ( it was a
compiler problem, of course at bank switching ) and I haven't this
problem... all measured points are in +- 2LSB with a 10K pot and a
good 5.00V supply.
> Tad is the convertion time, right? I think FOSC/32 @ 20MHz (3.2us) would
>be more than sufficient. FRC gives about (4us). TACQ is the aquisition time
>(the time allowed the charge the capacitor). My application is taking 65.2uS
>between the aquisitions, that would be enough too.
Fosc/32 @ 20Mhz = 1.6uS (at least according to the tables in the data books).
> You need 2 x Tad times between starting measurements.
delay_us(20); // 20us
total += (ADRESH * 256 + ADRESL); // about 18us
This makes for a total of 38us between measurements. That's not
enough???
> It looks like you need a pot below 7K, but I'm not sure on that yet.
I've tried a 1K trimpot. The values seems much better, but it's still
not what I was expecting.
> Tacq needs to be about 12 uS or longer
Can you please explain TAD, TACQ, etc? I'm explicitly waiting 20us
before I set the GO bit.
> 20 MHz on the 'C77 is the absolute limit for the Fosc/32 mode. See what
happens when you try to run the whole thing slower (use FRC mode).
I've tried FRC. Almost same results.
> Check your C compiler's output to make sure that it's doing
> <snip>
> adresult = adresh;
> adresult <<= 8;
> adresult |= adres;
> total += adresult;
This seems to make a diference!!! I'm not sure why.
I make that other line as:
total = total * 5 / 2048 / 1023;
Now I have:
with the 1K trimpot and FOSC/32
Multimeter PIC ADC
0.000V 0.003V
1.000V 0.972V
2.000V 1.996V
2.500V 2.570V
3.000V 3.030V
4.000V 4.065V
5.000V 5.000V
with the 1K trimpot and FRC
Multimeter PIC ADC
0.000V 0.001V
1.000V 0.966V
2.000V 1.992V
2.500V 2.511V
3.000V 3.016V
4.000V 4.052V
5.000V 5.000V
with the 10K trimpot and FRC
Multimeter PIC ADC
0.000V 0.002V
1.000V 0.960V
2.000V 1.989V
2.500V 2.506V
3.000V 3.022V
4.000V 4.060V
5.000V 5.000V
This means, more precise results with smaller resistance knobs. Also FRC
is more precise than FOSC/32 (@20MHz clock).
Regards,
Brusque
-----------------------------------
Edson Brusque
Research and Development
C.I.Tronics Lighting Designers Ltda
(47) 323-2685 / (47) 9993-6453
Blumenau - SC - Brazil
-----------------------------------
>> Tad is the convertion time, right? I think FOSC/32 @ 20MHz (3.2us)
would
>Fosc/32 @ 20Mhz = 1.6uS (at least according to the tables in the data
books).
Oops, sorry. I mean Fosc/32 @ *10*MHz.
> Why are you using a float anyway?
> A 32-bit integer will fit AND be more accurate AND faster!!
CCS-PCM doesn't have 32-bit integers.
> Assuming the software it's ok, you have 80% a measuring error or
>noise problem. First, this looks like an offset error. Have you use
>some sort of breadboard without nice ground lay-out? Make a
>measurement with a good voltmeter (4 1/2 digits ) between 877
>ground and adc input pin, you will get something... change the
>ground point let say near the power supply, you will get something
YES!!! I have 60mV of voltages betweem some points on the breadboard.
I've corrected it putting some wires between various ground points. Now it's
2mV max.
>else...
> Have you filtered the analogic input signal ?
Do you mean putting a capacitor between the analog input and ground?
What value? I was thinking that my *software* filter was enough. I'm
averaging 2048 readings. It's a lot, I know. I hope to use no more than 256
on the final product.
> Finally I've manage with my 10bites adc readings ( it was a
>compiler problem, of course at bank switching ) and I haven't this
>problem... all measured points are in +- 2LSB with a 10K pot and a
>good 5.00V supply.
I'm not making tests with a 25-turn 5K precision trimpot. I'm using
FOSC/32 and 4MHz clock. Here is my last results.
This values are usable on my application. Hope in the PCB it will work
better.
Now, I will have some headaches with the precision AC/DC converter.
Ouch. Someone have a T**3 (tested, tried and true) precision AC/DC converter
circuit that works over the entire PIC ADC voltage range and 1:1 gain? I
mean 0-5VAC input, 0-5VDC output.
Thanks to everyone that helped me with this.
Regards,
Brusque
-----------------------------------
Edson Brusque
Research and Development
C.I.Tronics Lighting Designers Ltda
(47) 323-2685 / (47) 9993-6453
Blumenau - SC - Brazil
-----------------------------------
> Would you mind doing a summary of what to do when using the ADC.
> Do's and don'ts. As I'm just about to start using it and it would be nice
to
> have a piece of code and guidelines for future users.
I will make it, but I'm still researching to find better results. Now I
want to try some other voltage references, like a 3.3V zenner diode or the
precision voltage references from National Semiconductors.
Best regards,
Brusque
-----------------------------------
Edson Brusque
Research and Development
C.I.Tronics Lighting Designers Ltda
(47) 323-2685 / (47) 9993-6453
Blumenau - SC - Brazil
-----------------------------------
>
> I will make it, but I'm still researching to find better results. Now I
> want to try some other voltage references, like a 3.3V zenner diode
Don't waste your precious time trying a zenner with other
temperature coeficcient that near zero. Will not work properly .
You may try standard DZ6v2 or DZ6v8 or better a good reference
voltage chip. Of course keep the VREF+ in maximum ratings
characteristic.
> Hello,
> I'm still trying to make the ADC on a PIC16F877 work correctly.
> I've wired a potentiometer to pin 2 (AN0) of the 'F877 . AN3 is wired
to {Quote hidden}
> a very precise +5V voltage reference. I'm summing 2048 10bits ADC readings
> to a float TOTAL variable. Then I divide TOTAL by 1023 (max reading) and
> multiply it by 5 (max voltage). Here is an example of my readings:
>
> PIC ADC Multimeter on AN0
> 0.002V 0.000V
> 0.370V 0.000V
> 0.372V 0.001V
> 0.800V 0.355V
> 1.000V 0.600V
> 2.000V 1.650V
> 3.000V 2.755V
> 4.000V 3.911V
> 5.000V 4.958V
> 5.180V and up 4.980V
>
> Can someone please help me with this?
The two things that caught me out regarding measurement errors on my first
A/D project were the source impedance of the voltage to be converted (hacked
by putting a cap from A/d pin to deck, 10n or 100n from memory - a proper
input buffer is the solution for production of course) and using the wrong
oscillator clock rate.
It really is worth reading the A/D section of the datasheet *several times*,
then read it again the next day - there are a few things that can catch you
out there. The sections 11.1 and 11.2 are especially helpful.