View previous topic :: View next topic |
Author |
Message |
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
ADC maths... exercise in futility - SOLVED |
Posted: Mon Mar 04, 2013 10:26 am |
|
|
There is no problem with my code, it works fine.
I'm just looking for suggestions, its a long post.
I'm sure something good can come out of listening to all your opinions.
Code: |
+Vref=2.5V
Vin (volts) (ADC constant) ADC Val (DEC) ADC Val (HEX) ADC*Adc_const value to printf
1.55 244 635 027A 25D78 155000
1.54 244 631 0276 25990 154000
1.53 244 627 0272 255A8 153000
1.52 244 623 026E 251C0 152000
1.51 244 618 026A 24DD8 151000
1.50 244 614 0266 249F0 150000
1.49 244 610 0262 24608 149000
1.48 244 606 025E 24220 148000
1.47 244 602 025A 23E38 147000
1.46 244 598 0256 23A50 146000
1.45 244 594 0251 23668 145000
1.44 244 590 024D 23280 144000
|
The table above represents part of the ADC calculations I've done in Excel prior to coding my routine.
I'm trying to over sample an LM35 in an overachieving futile exercise to push precision and output stability for the glorious hell of it.
(its how i learn)
PIC: 16f88 (adc-10bit)
LM35 setup for 2C-155C
power input:
I have 12VDC input, through a diode, into 35V 556uF x 2 Electrolytic caps, into a LM7809, into a Pi filter (16V 100uf + 4R7uH +16V 100uf), into a LM7805, into 6.3V 1000uF x 4 Electrolytic caps... as a power supply....
its a _very_ smooth 5V supply... and excessive in every way i can imagine.
Further to that, my +Vref is a Voltage divider (10k+10k) with a 25V 10uf cap...
With the above setup, i get higher precision than with the Zeners Ive tried even when just using VDD as reference... obviously making my calculations on the actual voltage rather than just assuming 5V from the 7805.
my +Vref currently reads a cool solid 2.503 Volts.
I sample the ADC 68 times, eliminate high and low, average by 64.
and further to that, i put the result through a filter like this:
Code: | Out0 = (In0 + Out1 + Out1 + Out1) / 4; |
The signal from the LM35 comes to the ADC via a LM358 set as unit gain and through a RC filter of 100ohm and 25V 10uf electrolytic Cap.
Yes, all this excessiveness takes a whole lot of time, and the response time is terrible...(well, its like 2-3 seconds)
I would like to keep the numeric precision of the calculations above but only use 1 decimal and keep everything in 16bit vars.
How can i optimize my calculations?
Code: |
temperature/=64; // average by 16
temperature*=244; // multiply by ADC constant.
|
I know can format my decimal points with printf...
I really want to get my _math_ as precise as posible...obviously using integer maths...
I think I've implemented pretty much every trick in my book...
solid supply, narrowed the signal to reference differential, over sampled, digital low pas filter...hardware filters and buffers...
Thanks and sorry for the absurdly long post.
G. _________________ CCS PCM 5.078 & CCS PCH 5.093
Last edited by Gabriel on Thu Mar 07, 2013 8:30 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Mon Mar 04, 2013 1:11 pm |
|
|
Several comments:
First having significantly larger capacitors on the output of a regulator, than it's input, can endanger the regulator, resulting in it becoming reverse biased when you turn it off. Texas recommend a reverse biased diode across the regulator if you do this.
Then the best regulators are still an order of magnitude worse than a good voltage reference, but a zener is _not_ a good voltage reference. Look at bandgap references.
Then double check your maths. If you sample 68 times, and remove the high and low values, you still have 66 samples, not 64....
The easiest way to do this is to sum as you go:
Code: |
int16 average_reading(void) {
int32 sum=0;
int16 low=0xFFFF;
int16 high=0;
int count;
int16 val;
for (count=0;count<66;count++) {
val=read_adc();
sum +=val;
if (val>high)
high=val;
if (val<low)
low=val;
delay_us(10);
}
val-=high;
val-=low;
return (val/64);
}
|
Remember that to avoid accuracy loss you should always multiply _before_ division.
66 samples should still take under 1mSec. Delays longer than Tacq, gain you nothing.
Best Wishes |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Mon Mar 04, 2013 1:34 pm |
|
|
EDIT : Hi Ttelmah.......
(my bad... sorry about that... i glanced at your name but read my version number on my footer at the same time and it say PCM... and ... you see where im going)...
i meant 66 times... sorry for that.. typo.
Thanks for the information on the reverse bias...ill implement that immediatly...
Quote: | Remember that to avoid accuracy loss you should always multiply _before_ division. |
the code you posted is EXACTLY the same as the one im using (exept for the delay_us(10))
so, i understand it would be better to multiply the sum of the 64 values by the ADC constant and then devide by 64?
Quote: | 66 samples should still take under 1mSec. Delays longer than Tacq, gain you nothing. |
i did not understand this... could you please explain more?
i think that what you mean is that im reading the ADC faster than the ADC time constant and thus not gaining any presicion and thats why you have included a 10us delay in you posted code?
Thanks!
G- _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Mon Mar 04, 2013 1:47 pm |
|
|
The ADC functions internally as a capacitor fed by a resistor.
The resistor is a combination of internal resistances in the multiplexor, and the other circuitry. The capacitor is what is used to hold the voltage to be read, while the ADC is disconnected from the external source. The ADC is disconnected while the reading is made, and takes time to recharge. The time needed to re-acquire, is Tacq. Now this depends on the chip you are using, but is typically 10uSec on the commonest chips, dropping to just a couple of uSec on some of the newer chips. Assuming a reasonably fast clock rate, the comparisons, loop and sum, will only take a couple of uSec, which then means the capacitor _won't_ have properly recharged.
Several questions apply:
Chip?.
What clock rate?.
What clock rate are you using for the ADC?.
You talk about taking 2 to 3 seconds, but 66 readings done (say) 15uSec apart, will only take 990uSec, so what are you doing that takes so long?....
Best Wishes |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Mon Mar 04, 2013 1:58 pm |
|
|
I got it.
I'll add the delay.
I'm using a 16F88 @ 8MHz, using div_16 adc clock as per the datasheet on the TAD table.
EDIT remember i put everything through a lowpass filter (see OP)....
it take 2-3 secs for the value to stabilize in the terminal... 2-3 seconds is the time i think it takes... i see values changing immediately on the screen when i touch the sensor but because of the filter it takes a little bit to reach the final value.
Thanks for your help i really appreciate it.
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Mon Mar 04, 2013 3:51 pm |
|
|
Probably 80% of the delay is the time it takes the chip to actually heat/cool. Remember the sensor is the IC right inside the chip...
Best Wishes |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Mon Mar 04, 2013 6:59 pm |
|
|
I did a work for hire a while back - incubator stage heater system for approx human body temp center point with an LM34 - not the 35 -
even though the output is presented in cent degrees -
the servo code does not care.
I used an LM385-1.25 ref diode with 5uf on the ref input of the pic
and an 18F2423 - and it was very successful, stable and accurate.
I did use TWO LM34s and combined the data, but that is another story.
Now, does anybody care to tell me why i used:
** 1.25v ref,
** the pic that i did and the
** LM34 instead of the LM35 ??
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Tue Mar 05, 2013 1:29 am |
|
|
You missed one thing that would be degrading your result. Parameter A20 in the data sheet.
Best Wishes |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Mar 05, 2013 2:35 am |
|
|
Quote: | power input:
I have 12VDC input, through a diode, into 35V 556uF x 2 Electrolytic caps, into a LM7809, into a Pi filter (16V 100uf + 4R7uH +16V 100uf), into a LM7805, into 6.3V 1000uF x 4 Electrolytic caps... as a power supply.... | Perhaps you left them out to keep your description readable, but I'm missing the high frequency caps.
With caps it isn't always 'bigger is better'; the electrolytic caps have a relatively large internal resistance making them unsuitable to filter the high frequency noise. That's why you often see a 0.1uF tantalum or 0.33uf aluminium capacitor next to one of the larger electrolytic caps; the combination of both works more like the 'perfect' theoretical cap we always assume they are.
Note that the LM78xx regulators are known to be very good oscillators. To prevent this from happening you need the smaller capacitors: 0.33uf on the high voltage side and 0.1uf on the output side. See Fairchild data sheet typical application examples. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Tue Mar 05, 2013 4:20 am |
|
|
Yes, that is one I normally 'PIC up'.....
Best Wishes |
|
|
miro
Joined: 15 Jan 2011 Posts: 62
|
|
Posted: Tue Mar 05, 2013 5:57 am |
|
|
Quote: | Then the best regulators are still an order of magnitude worse than a good voltage reference, but a zener is _not_ a good voltage reference. Look at bandgap references. |
Not sure that this would be a good hint for this application. My hands-on experience shows you may get best results with oversampling and digital filtering only with dithering. The usage of a noise-free precise voltage reference causes the resulting values will be of a "better precision" only at the moments with input voltages near the transition levels between the "adc bit levels". Dithering helps you with creating improved precision within the adc "step levels" as well. |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Tue Mar 05, 2013 7:10 am |
|
|
Hey guys thanks for all the good info.
The small caps are onboard however, i have them closer to the PIC/Chips so i didn't include them in the description of the power source.
Ttelmah, you referenced parameter A20, which by my understanding requires a minimum +Vref of 2V.... I'm using 2.5V so i "should" be Ok... feel free to correct me.
anyways, last night i tested some code and sadly i found that although I'm getting "acceptable" results (mean values)... my LM35s have become fabulous oscilators....in the kHz range...
They are connected to the board via a ~1meter cable... its 4 wire+1 bare conductor, aluminum foil shielded cable...unused wires are tied to GND on both ends.
I checked my 5V line on board and on the LM35 with my O-scope and it was smooth as a baby's bottom... so its definitely the LM35 oscilating... probably due to capacitance on the cable...sigh.
I ended up deleting all my code and using:
Code: | int16 average_reading(void) {
int32 sum=0;
int16 low=0xFFFF;
int16 high=0;
int count;
int16 val;
for (count=0;count<66;count++) {
val=read_adc();
sum +=val;
if (val>high)
high=val;
if (val<low)
low=val;
delay_us(10);
}
val-=high;
val-=low;
return (val/64);
} |
which doesn't work by the way...
it should be:
Code: |
sum-=high;
sum-=low;
return (sum/64);
|
I've been reading the datasheet on the LM35 to control the oscillations but i don't like the presented solutions as they required alot of additional components.. but alas.. i guess I'll have to try them... (i need the sensors on long cables).
G... _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9238 Location: Greensville,Ontario
|
|
Posted: Tue Mar 05, 2013 8:04 am |
|
|
Yes the LM34/35 are good oscillators if not wired up according to the datasheets! Used them for 20+ years for remote energy control systems.
I used 1/2 an LM358(IIRC) as a buffer at the sensor end along with some power supply decoupling(22r/10mfd).Ran simple 'quad' about 150' without any problems.
A one 'chip' solution may be the DS18B20 if you don't mind the 1 second response time for max resolution.
Yes it costs more,but weighed against an LM34/opamp/passives/Vref/pcb/etc. it probably comes out cheaper and/or easier to use.
hth
jay |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Tue Mar 05, 2013 8:29 am |
|
|
@temptronic:
Jejejeje i just finished drawing up the art work for a small pcb to place at the sensor end with a LM358 for x2 amplification and buffering!
hahaha... almost exactly what you posted..
i think im going to take out the x2 amplification to save on the Resistors and extra soldering work... what do you think?
Edit: and also to avoid having MORE error introduced by resistor inacuracies... IE not exactly x2 amplification but x2.17...
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Mar 05, 2013 9:10 am |
|
|
Gabriel wrote: | Ttelmah, you referenced parameter A20, which by my understanding requires a minimum +Vref of 2V.... I'm using 2.5V so i "should" be Ok... feel free to correct me. | My guess is that the remark was meant for Asmboy. His 1.25Vref is out of spec (the 18F2423 requires 3V minimum). |
|
|
|