![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
aodj
Joined: 20 Dec 2006 Posts: 40 Location: Reading, UK
|
Storing large lookup tables |
Posted: Tue Feb 06, 2007 10:43 am |
|
|
In my current project I'm using a lookup table to linearise a PTC thermister. unfortunately since the ADC varies across 600 or so values I need to store 600 different linearised values.
Does anyone know of a way to store a table of this size, or perhaps a better method to linearise my sensor data? |
|
![](templates/subSilver/images/spacer.gif) |
sjbaxter
Joined: 26 Jan 2006 Posts: 141 Location: Cheshire, UK
|
|
Posted: Tue Feb 06, 2007 11:09 am |
|
|
You can do it by two ways:
1) Approximate the curve by a series of straight lines then do a bit of code to find the real value based on the segment you are in. i.e.
Code: | ADC Real Value
0 0
100 10
200 20
300 35
400 56
500 80
600 100
|
now put this in a table (much smaller) if you get an ADC value of 322, lookup in the table for the values above and below (300 and 400) and get their corresponding 'real' values (35 and 56). Now work out how far between these is your actual value .. approx 39.62 !
You can expand the table to reduce the apporoximation errors between known points.
You can also validate the reading by flagging an error if the ADC value is lower than the first value (not in this example !!) or higher than the top value (600) this could indicate an open circuit or defective sensor.
2) Use a polynomial curve fit that uses the formula:
y = ax^3 + bx^2 + cx + d
This uses a third degree polynomial (4 values). You may need to extend it upto 6 or 7 to get a good fit. But you'll still have a table (calibration) that is smaller than you are doing at present.
BTW: You can use MS Excel to generate the polynomial values based on a known ADC vs Value table as above. _________________ Regards,
Simon. |
|
![](templates/subSilver/images/spacer.gif) |
aodj
Joined: 20 Dec 2006 Posts: 40 Location: Reading, UK
|
|
Posted: Tue Feb 06, 2007 11:24 am |
|
|
sjbaxter wrote: | 2) Use a polynomial curve fit that uses the formula:
y = ax^3 + bx^2 + cx + d
This uses a third degree polynomial (4 values). You may need to extend it upto 6 or 7 to get a good fit. But you'll still have a table (calibration) that is smaller than you are doing at present.
BTW: You can use MS Excel to generate the polynomial values based on a known ADC vs Value table as above. |
I've used Excel to generate a 3rd degree polynomial that fits the sensor behaviour. It's pretty accurate, but I'm unsure how I would translate this polynomial into something I can generate code for. The y it would solve for is the resistance/temperature, but I would have to use int32's for this. Surely the time taken to solve a polynomial is longer than looking up a table, even one as large as mine? |
|
![](templates/subSilver/images/spacer.gif) |
sjbaxter
Joined: 26 Jan 2006 Posts: 141 Location: Cheshire, UK
|
|
Posted: Tue Feb 06, 2007 11:31 am |
|
|
I'll post some example code when I get home.
You don't do the full calculation for each adc reading as it is written down in the formula, but an incremental multiplication of x (to give you the powers of x) and a running total in y (a double ideally). All the polynomial values need to be doubles or floats.
I agree the time will be slightly longer, but its more flexible, saves valuable memory space and is more accurate (as the polynomial values are doubles or floats) so the calibration table will only consume about 32 bytes.
You'll see what I mean in an hour or so. _________________ Regards,
Simon. |
|
![](templates/subSilver/images/spacer.gif) |
sjbaxter
Joined: 26 Jan 2006 Posts: 141 Location: Cheshire, UK
|
|
Posted: Tue Feb 06, 2007 1:24 pm |
|
|
aodj,
Code: | const float Temperature[4] = {
-0.1429f, // constant
-2.4048f, // x
3.5714f, // x^2
-0.1667f // x^3
};
float GetCalibratedTemperature(float fValue)
{
int8 i;
float fReturn;
float fX;
fReturn = Temperature[0];
fX = fValue;
for (i=1; i<4; i++)
{
fReturn += (fX * Temperature[i]);
fX *= fValue;
}
return fReturn;
}
void main()
{
int16 adcvalue;
float temperature;
// init adc, etc ....
for(;;)
{
...
adcvalue = (read_adc() & 0x03FF); // Internal ADC used is a 10 bit A/D
temperature = GetCalibratedTemperature((float) adcvalue);
...
}
}
|
It may not be perfect (as I've cut and pasted the relavent code from one of my projects), but you'll get the idea. _________________ Regards,
Simon. |
|
![](templates/subSilver/images/spacer.gif) |
C Turner
Joined: 10 Nov 2003 Posts: 40 Location: Utah
|
|
Posted: Tue Feb 06, 2007 4:22 pm |
|
|
Look into the "Steinhart-Hart" Equation - the polynomial equation of which the others have spoken.
For some good information, look up "Thermistor" on Wikipedia and a spreadhseet (that will work nicely under OpenOffice) may be found here:
http://www.benchtest.com/downloads/index.html
(Look down and get the file "steinhart.zip")
On more than one occasion, I have taken a thermistor with unknown coefficients and plugged those into the spreadsheet with excellent results. Sometimes, you get a thermistor with just one known resistance-versus-temperature value, sometimes you get a thermistor with a chart, but sometimes you get just the thermistor: It is up to the user to carefully measure various resistance values at known temperatures and log them.
In those instances where I've had to divine the properties of the thermistor, I've wire-tied the temperature probe and thermistor together (so that they are next to each other) and immersed them in a small container of oil (because it's non-conductive) and then proceeded with heating/cooling the thermistor, taking the time to allow everything to come to equalibrium. If you do this carefully, you can get a set of coefficients that nicely fit the actual properties of the device.
(You said PTC thermistor - is that really what you are using? NTC's are more commonly used for temperature measurement and obey the equation over a much larger range.)
It is worth saything that for using a thermistor over a really large temperature range, 10 bits may not cut it: At one extreme or another, you'll suffer from loss of resolution. There are a number of schemes where a lower or higher value of divider resistor is switched in/out with one of the PIC's pins to extend the range.
Best of luck.
CT |
|
![](templates/subSilver/images/spacer.gif) |
aodj
Joined: 20 Dec 2006 Posts: 40 Location: Reading, UK
|
|
Posted: Wed Feb 07, 2007 2:58 am |
|
|
Thankyou for your replies, I'll endeavour to apply them to my project.
C Turner, I am indeed using a PTC thermistor, the probe range I'm intending to read is from -50 to +100 Celsius. However due to ADC on the chip I'm using, 16f914, I can only achieve a 0.25 celsius resolution with a 10 bit ADC. The calibrated Vrefs need to be 2V apart to ensure correct functioning of the ADC, hence why I was after a table of 600 or so. (150 Celsius range, @ 0.25 resolution).
sjbaxter, I had worked out a rough draft for some code simimlar in essence to what you've written, but i'll give it a second look at since its something I can actually write code for rather than a 600 entry lookup table! |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Wed Feb 07, 2007 3:29 am |
|
|
Beware...
The ADC, won't give ten bit accuracy, with the 'calibrated Vrefs 2v apart'.
Table 19-15 in the data sheet, entry A20...
You will only get about 9.5bit accuracy from the ADC, using 2v reference separation.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
aodj
Joined: 20 Dec 2006 Posts: 40 Location: Reading, UK
|
|
Posted: Wed Feb 07, 2007 4:55 am |
|
|
Ah, good catch, I hadn't realised that I had gone from 2.5v min to 2v min! |
|
![](templates/subSilver/images/spacer.gif) |
C Turner
Joined: 10 Nov 2003 Posts: 40 Location: Utah
|
|
Posted: Wed Feb 07, 2007 3:43 pm |
|
|
>... I am indeed using a PTC thermistor,
That's interesting. It must be a special-purpose PTC: A lot of PTC thermistors have rather nasty curves that don't nicely follow formulas (possibly explaining your need for a lookup table) - and many don't even have a constant sign of their slope over a really large temperature range - that is, they exhibit both PTC and NTC characteristics over their curve. Also, some PTC devices also exhibit a rather poor retrace characteristic where the same resistance doesn't necessarily mean the same temperature every time.
In measuring temperature with a PIC, when I have had the option, I've used an LM335 (or one of the many similar devices offered by many other manufacturers) as the '335 exhibits a very nice 10 millivolt/Kelvin temperature-versus-voltage output, essentially eliminating the need for anything other than integer math to scale it, and they are spec'd to operate from -40 to +100C (or -55 to +150C for the more expensive LM135.) Of course, one needs to have a fairly precise voltage reference for best accuracy - whereas the thermistor is simply ratiometric and the reference voltage isn't particularly important.
In one instance where I needed much higher temperature resolution (1/16th of a degree C) I used a Dallas DS18B20 (or the less-accurate DS1822 - both are rated to operate from -55 to +125C) with the significant advantage that I didn't need to supply a precise voltage reference for the A/D - or even use an A/D channel - but I had the added code complexity of dealing with a 1-wire device.
Of course, if you don't need really high accuracy, a thermistor can't really be beat in terms of being cheap in comparison with either type of silicon temperature sensor mentioned above.
CT |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|