Skip to content
This repository was archived by the owner on Aug 27, 2023. It is now read-only.

Commit 6542c28

Browse files
phordTraumflug
authored andcommitted
Optimize temperature tables for accuracy
Temperature tables are emitted by selecting arbitrary sample values to be used for the linear lookup table. This is fine in the range where the thermistor produces linear output, but it is markedly wrong near the extremes where the thermister output begins to curve. Introduce a new sample selector which chooses samples based on the "most incorrect estimate" and improves from there to ensure we get a cleaner approximation across the selected range. Traumflug: this topic is tracked here: #208
1 parent fdf6dbe commit 6542c28

File tree

1 file changed

+52
-3
lines changed

1 file changed

+52
-3
lines changed

configtool/thermistortablefile.py

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,41 @@ def BetaTable(ofp, params, names, settings, finalTable):
9999

100100
hiadc = thrm.setting(0)[0]
101101
N = int(settings.numTemps)
102-
step = int(hiadc / (N - 1))
103102

104-
for i in range(1, int(hiadc), step):
103+
# This is a variation of the Ramer-Douglas-Peucker algorithm, see
104+
# https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
105+
#
106+
# It works like this:
107+
#
108+
# - Calculate all (1024) ideal values.
109+
# - Insert the two extremes into our sample list.
110+
# - Calculate the linear approximation of the remaining values.
111+
# - Insert the correct value for the "most-wrong" estimation into our
112+
# sample list.
113+
# - Repeat until "N" values are chosen as requested.
114+
115+
# Calculate actual temps for all ADC values.
116+
actual = dict([(x, thrm.temp(1.0 * x)) for x in range(1, int(hiadc + 1))])
117+
118+
# Build a lookup table starting with the extremes.
119+
lookup = dict([(x, actual[x]) for x in [1, int(hiadc)]])
120+
121+
A = 1
122+
B = int(hiadc)
123+
error = dict({})
124+
while len(lookup) < N:
125+
error.update(dict([(x, abs(actual[x] - LinearTableEstimate(lookup, x)))
126+
for x in range(A + 1, B)]))
127+
128+
# Correct the most-wrong lookup value.
129+
next = max(error, key = error.get)
130+
lookup[next] = actual[next]
131+
132+
# Prepare to update the error range.
133+
A = before(lookup, next)
134+
B = after(lookup, next)
135+
136+
for i in sorted(lookup.keys()):
105137
t = int(thrm.temp(i))
106138
if t is None:
107139
ofp.output("// ERROR CALCULATING THERMISTOR VALUES AT ADC %d" % i)
@@ -112,7 +144,7 @@ def BetaTable(ofp, params, names, settings, finalTable):
112144

113145
vTherm = i * vadc / 1024
114146
ptherm = vTherm * vTherm / r
115-
if i + step >= int(hiadc):
147+
if i == max(lookup):
116148
c = " "
117149
else:
118150
c = ","
@@ -162,3 +194,20 @@ def SteinhartHartTable(ofp, params, names, settings, finalTable):
162194
ofp.output(" }")
163195
else:
164196
ofp.output(" },")
197+
198+
def after(lookup, value):
199+
return min([x for x in lookup.keys() if x > value])
200+
201+
def before(lookup, value):
202+
return max([x for x in lookup.keys() if x < value])
203+
204+
def LinearTableEstimate(lookup, value):
205+
if value in lookup:
206+
return lookup[value]
207+
208+
# Estimate result with linear estimation algorithm.
209+
x0 = before(lookup, value)
210+
x1 = after(lookup, value)
211+
y0 = lookup[x0]
212+
y1 = lookup[x1]
213+
return ((value - x0) * y1 + (x1 - value) * y0) / (x1 - x0)

0 commit comments

Comments
 (0)