Refactor temp table optimization for any algorithm

This should be squashed but is separated here for comparison.
This commit is contained in:
Phil Hord 2016-04-13 17:26:50 -04:00 committed by Markus Hitter
parent b7a2d58b31
commit 090be579d1
1 changed files with 50 additions and 43 deletions

View File

@ -100,46 +100,9 @@ def BetaTable(ofp, params, names, settings, finalTable):
hiadc = thrm.setting(0)[0]
N = int(settings.numTemps)
# This is a variation of the Ramer-Douglas-Peucker algorithm, see
# https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
#
# It works like this:
#
# - Calculate all (1024) ideal values.
# - Keep only the ones in the interesting range (0..500C).
# - Insert the two extremes into our sample list.
# - Calculate the linear approximation of the remaining values.
# - Insert the correct value for the "most-wrong" estimation into our
# sample list.
# - Repeat until "N" values are chosen as requested.
samples = optimizeTempTable(thrm, N, hiadc)
# Calculate actual temps for all ADC values.
actual = dict([(x, thrm.temp(1.0 * x)) for x in range(1, int(hiadc + 1))])
# Limit ADC range to 0C to 500C.
MIN_TEMP = 0
MAX_TEMP = 500
actual = dict([(adc, actual[adc]) for adc in actual
if actual[adc] <= MAX_TEMP and actual[adc] >= MIN_TEMP])
# Build a lookup table starting with the extremes.
A = min(actual)
B = max(actual)
lookup = dict([(x, actual[x]) for x in [A,B]])
error = dict({})
while len(lookup) < N:
error.update(dict([(x, abs(actual[x] - LinearTableEstimate(lookup, x)))
for x in range(A + 1, B)]))
# Correct the most-wrong lookup value.
next = max(error, key = error.get)
lookup[next] = actual[next]
# Prepare to update the error range.
A = before(lookup, next)
B = after(lookup, next)
for i in sorted(lookup.keys()):
for i in samples:
t = int(thrm.temp(i))
if t is None:
ofp.output("// ERROR CALCULATING THERMISTOR VALUES AT ADC %d" % i)
@ -150,7 +113,7 @@ def BetaTable(ofp, params, names, settings, finalTable):
vTherm = i * vadc / 1024
ptherm = vTherm * vTherm / r
if i == max(lookup):
if i == max(samples):
c = " "
else:
c = ","
@ -179,9 +142,10 @@ def SteinhartHartTable(ofp, params, names, settings, finalTable):
hiadc = thrm.setting(0)[0]
N = int(settings.numTemps)
step = int(hiadc / (N - 1))
for i in range(1, int(hiadc), step):
samples = optimizeTempTable(thrm, N, hiadc)
for i in samples:
t = int(thrm.temp(i))
if t is None:
ofp.output("// ERROR CALCULATING THERMISTOR VALUES AT ADC %d" % i)
@ -189,7 +153,7 @@ def SteinhartHartTable(ofp, params, names, settings, finalTable):
r = int(thrm.adcInv(i))
if i + step >= int(hiadc):
if i == max(samples):
c = " "
else:
c = ","
@ -201,6 +165,49 @@ def SteinhartHartTable(ofp, params, names, settings, finalTable):
else:
ofp.output(" },")
def optimizeTempTable(thrm, length, hiadc):
# This is a variation of the Ramer-Douglas-Peucker algorithm, see
# https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
#
# It works like this:
#
# - Calculate all (1024) ideal values.
# - Keep only the ones in the interesting range (0..500C).
# - Insert the two extremes into our sample list.
# - Calculate the linear approximation of the remaining values.
# - Insert the correct value for the "most-wrong" estimation into our
# sample list.
# - Repeat until "N" values are chosen as requested.
# Calculate actual temps for all ADC values.
actual = dict([(x, thrm.temp(1.0 * x)) for x in range(1, int(hiadc + 1))])
# Limit ADC range to 0C to 500C.
MIN_TEMP = 0
MAX_TEMP = 500
actual = dict([(adc, actual[adc]) for adc in actual
if actual[adc] <= MAX_TEMP and actual[adc] >= MIN_TEMP])
# Build a lookup table starting with the extremes.
A = min(actual)
B = max(actual)
lookup = dict([(x, actual[x]) for x in [A, B]])
error = dict({})
while len(lookup) < length:
error.update(dict([(x, abs(actual[x] - LinearTableEstimate(lookup, x)))
for x in range(A + 1, B)]))
# Correct the most-wrong lookup value.
next = max(error, key = error.get)
lookup[next] = actual[next]
# Prepare to update the error range.
A = before(lookup, next)
B = after(lookup, next)
return sorted(lookup)
def after(lookup, value):
return min([x for x in lookup.keys() if x > value])