View previous topic :: View next topic |
Author |
Message |
cerr
Joined: 10 Feb 2011 Posts: 241 Location: Vancouver, BC
|
adc_read() |
Posted: Wed Sep 14, 2011 12:26 pm |
|
|
Hi There,
I got some funny results from the temperature chamber today:
I read the voltage over a 10k ntc connected to GND and the PIC's (18F86K22) adc with a 10k pullup to +5V.
I got following results:
read_adc() read 4086 (12bit adc) at -10.3C (it's 4095 when I go slightly lower) & the voltmeter showed 4.25V across the NTC. A little calculation tells me that the ntc was at 56.6k and the datasheet tells me it oughta be at 46k at -10C but that's not the problem, the problem is that assuming the adc reads 4095 at 5V, it should read 3480 at 4.25V, right? My reference voltage is det to default which should be the +5V of the MCU, right?
Any clue what might be going on here?
Thank you!
Ron |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Wed Sep 14, 2011 12:40 pm |
|
|
post your CODE and compiler version !
12 bits is only 4095 so you are close to top scale
be sure you are formatted properly
to read 12 bits make sure you have:
#device adc=16
and stuff the results into an unsigned INT16
for starters
you could just as easily be having a circuitry problem here too
what value do you see if you read teh NTC part with an ohm meter
and do the scalar ration bit ??
if you really have a solid 5.0v and 1% 10 k pullup
your adc reading near full scale
says its WAY more than 50K ohms --
as in 500K ohms more like it
are you SURE your therm connection is SOLID ?
and that your CLOCKING of the ADC is within spec??
Last edited by asmboy on Wed Sep 14, 2011 1:01 pm; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9174 Location: Greensville,Ontario
|
|
Posted: Wed Sep 14, 2011 12:58 pm |
|
|
All sorts of 'well it could be'......
Non regulated, non precise 5 volt supply....
Wiring not shielded...long lines,etc.
Someone's cellphone or wireless router reset during a reading..
'Glitches' on the power supply feed,EMI,RFI,etc....
NTCs are very nonlinear,prone to selfheating effects...
Make/model of the NTC , any buffer between it and the PIC ?
Adequate bypass caps ???
that outght to be a start ???!!! |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Sep 14, 2011 1:09 pm |
|
|
You're doing a new thread for every aspect of the same NTC problem
so the previous info isn't readily available. But I recall that you don't have
any sort of opamp buffer or instrumentation amplifier circuit on your NTC.
The 18F86K22 data sheet says this, regarding the maximum source
impedance of the external circuit that's feeding the A/D:
Code: |
Param
No. Symbol Characteristic Min Typ Max
A30 ZAIN Recommended - - 2.5 Kohm
Impedance of Analog
Voltage Source
|
This info is from a table on page 523 in the Acrobat reader in the data sheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/39960d.pdf
It says it can't have a source resistance any higher than 2.5K. But your
NTC and the other resistor in the divider are much higher than that. So
the A/D is not getting the amount of current that it needs to operate within
parameters. This is most likely the main reason why you have accuracy
problems.
I think you need to need to add a suitable Op-Amp circuit to buffer the NTC. |
|
![](templates/subSilver/images/spacer.gif) |
cerr
Joined: 10 Feb 2011 Posts: 241 Location: Vancouver, BC
|
|
Posted: Wed Sep 14, 2011 3:00 pm |
|
|
asmboy wrote: | post your CODE and compiler version !
be sure you are formatted properly
|
4.119
right aligned format (ADCON2|=0x80;)
I have
#device adc=12 - had adc=16 before, no change, played around with that aleady, see other thread: #device adc=10 instead of =12
The result isn't even buffered as of right now, I got following:
Code: |
fprintf(PC, "LPR temperature %Ld\r\n",read_adc()); |
I haven't measured the resistance yet...
the clocking of the adc is set to setup_adc (ADC_CLOCK_INTERNAL); just changed this now to ADC_CLOCK_DIV_32 as I recall that ADC_CLOCK_INTERNAL is really bad, isn't it?
Looking at the circuitry now as I have an impedance that's way higher than 2.5K in my circuitry. There actually also is a low pass filter with a 10k resistor in series and a 0.1uF cap towards ground. I'll measure if there's any voltage over the resistor (current flowing) and will see if bypassing it will change/improve results.
Thank you very much to everyone for the help. |
|
![](templates/subSilver/images/spacer.gif) |
cerr
Joined: 10 Feb 2011 Posts: 241 Location: Vancouver, BC
|
|
Posted: Wed Sep 14, 2011 3:21 pm |
|
|
Reading 10 - 13mV RMS across that serial filter resistor with the PIC side being at the higher end. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Sep 14, 2011 3:36 pm |
|
|
This is what is important, and you are grossly violating it:
Quote: |
23.3 A/D Acquisition Requirements
For the A/D Converter to meet its specified accuracy,
the Charge Holding (CHOLD) capacitor must be allowed
to fully charge to the input channel voltage level. The
analog input model is shown in Figure 23-5. The
source impedance (RS) and the internal sampling
switch (RSS) impedance directly affect the time
required to charge the capacitor CHOLD. The sampling
switch (RSS) impedance varies over the device voltage
(VDD).
The source impedance affects the offset voltage at the
analog input (due to pin leakage current). The maximum
recommended impedance for analog sources is 2.5K. |
|
|
![](templates/subSilver/images/spacer.gif) |
cerr
Joined: 10 Feb 2011 Posts: 241 Location: Vancouver, BC
|
|
Posted: Wed Sep 14, 2011 4:11 pm |
|
|
right, I saw this! So we better be looking at re scaling these resistors? We wanna avoid adding another OPamp into our design if possible...
Thanks for the suggestions!
Ron |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Wed Sep 14, 2011 6:29 pm |
|
|
if you have a nominal 10k thermistor
i would be very interested to see how you can rescale anything
to get out of the hole you are in.
an opamp buffer is really the correct solution.
B U T ......
there is a cheaters way out with caveats
if you did not expect to take reading more than once half
minute or so
there is a little known but actually effective way to cheat this, especially at only 10 or 12 bits.
add a low leak film capacitor.
U C, with your choice of scaling Resistance - you have to take RC / integrating time of the A/D storage cap into account.
but for an infrequent measurement of a slow changing value like temperature -put a .22uf low leakage FILM capacitor from the PIC A/D
input pin to ground.
the "effective impedance" of this - over the sample time of the A/D conversion cycle will be low enough to get a good reading - so long as you do not read too often. with 10k and .22uf TC1 =2.2ms
using 100xTC1 - ( 220 ms between readings)
you can get a pretty good reading - in spite of the
apparent violation of the DC input impedance spec.
the reality of the PIC input spec is about IMPEDANCE / abilty to transfer charge - not a simple input resistance value.
been there done that have a nice t-shirt too. |
|
![](templates/subSilver/images/spacer.gif) |
cerr
Joined: 10 Feb 2011 Posts: 241 Location: Vancouver, BC
|
|
Posted: Thu Sep 15, 2011 10:41 am |
|
|
asmboy,
Thanks for this! Great suggestion, we will look at this a little closer later today. But why do you think I can't "Just" switch to a 1K NTC and a 1K pull up resistor? Shouldn't that help? (assuming the serial 10K filter resistor gets removed alltogether)... |
|
![](templates/subSilver/images/spacer.gif) |
cerr
Joined: 10 Feb 2011 Posts: 241 Location: Vancouver, BC
|
|
Posted: Thu Sep 15, 2011 11:18 am |
|
|
I got some more very interesting findings: I took a second isolated power supply and turned it up to +5V, I conntected it over the NTC and read the adc value, it reads 3519. I measured the voltage difference between the adc input on the pic and the Vdd of the pic which is 0.08V - why would the adc not read 4095 now? I'm confused. The serial filter resistor of 10k got bypassed. So i put +5V directly into the adc....I'm confused...
Thanks for assistance! |
|
![](templates/subSilver/images/spacer.gif) |
cerr
Joined: 10 Feb 2011 Posts: 241 Location: Vancouver, BC
|
|
Posted: Thu Sep 15, 2011 11:44 am |
|
|
Okay,
I now made a little test program to display my issue:
Code: |
#include <18F86K22.h>
#device HIGH_INTS=TRUE, adc=16, ICD=TRUE
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HSM //Hi-Speed crystal oscillator
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOPLLEN //No PLL enabled
#FUSES BBSIZ1K //1K words Boot Block size
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#use delay(clock=20000000)
#use rs232(baud=19200,parity=N,xmit=PIN_G2,rcv=PIN_G1,UART2,bits=8,stream=PC, ERRORS)
//#bit ADFM = ADCON2.7
#byte ADCON2 = getenv("sfr:ADCON2")
#define FILTER 10
void main (void)
{
//test=1;
SIGNED int16 adcval=0,value=0;
float flt=0;
SIGNED int8 i=0;
setup_adc(ADC_CLOCK_DIV_32);
ADCON2|= 0x80;
while (true) {
set_adc_channel(14);
delay_us(10);
adcval=read_adc();
value = (value * FILTER + adcval) / (FILTER + 1);
flt = (flt *FILTER + adcval) / (FILTER + 1);
fprintf(PC,"%f - ",flt);
for (i=15;i>=0;i--) {
if (i==7)
fprintf(PC," ");
if (((value>>i)&0x01)==1)
fprintf(PC,"1");
else
fprintf(PC,"0");
}
fprintf(PC," - 0x%Lx %Ld\r\n", adcval, adcval);
delay_ms(100);
}
}
|
The maximum value it ever reads is adcval = 3327 even when i got over 5V with my isolated power source... |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu Sep 15, 2011 11:49 am |
|
|
1- 3327 is a very interesting number when expressed in binary.
it makes me think of formatting issues
2- i note you are using a SIGNED int16 to get adc_read()
why not UNSIGNED int 16 ?
( as the output IS unsigned )
3- and this ?? ADCON2|= 0x80;
hmmmmm? |
|
![](templates/subSilver/images/spacer.gif) |
cerr
Joined: 10 Feb 2011 Posts: 241 Location: Vancouver, BC
|
|
Posted: Thu Sep 15, 2011 12:06 pm |
|
|
asmboy wrote: | 1- 3327 is a very interesting number when expressed in binary.
it makes me think of formatting issues
2- i note you are using a SIGNED int16 to get adc_read()
why not UNSIGNED int 16 ?
( as the output IS unsigned )
3- and this ?? ADCON2|= 0x80;
hmmmmm? |
3327 = 1100 1111 1111 - formating issues, how?
turned SIGNED into UNSIGNED and there's no difference...adcval still stays at 3327....But interesting is, the first read ever after reprogramming the PIC returns 4095
ADCON2|= 0x80; just right aligns the values read.
hmmmmmmmm... what am i doing wrong i'm wondering, any hints?
Thanks,
Ron |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu Sep 15, 2011 12:08 pm |
|
|
AND IF YOU COMMENT THAT ADCON MANIPULATION OUT ???
I ALSO CANT FIND THIS RATHER IMPORTANT LINE
setup_adc_ports( AN0_AN1_AN3 );
of course CONFIGURED FOR YOUR pic PART to make sure 'chan 14' is properly
initialized for analog input in the first place
lastly - lose the data manipulation and cut to the chase
just show yourself the RAW adc count ADCVAL
a number from 0 -4095 ( %Lu ) |
|
![](templates/subSilver/images/spacer.gif) |
|