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

Commit

Permalink
Expand thermistortable to include precomputed slope
Browse files Browse the repository at this point in the history
Save a division at runtime by pre-calculating the slope between each
pair of adjacent thermistortable values.  Since we use the larger value
each time, save the slope between two values A and B in the table
with the B data.  Therefore the slope is that between each value and
its predecessor in the list.

Store this new value in the third element of the now 3-integers-wide
array which makes up the table. Use fixed-point 6.10 format to store
the slope.  This is almost too narrow for some slopes and maybe it
should be changed to 8.8 fixed-point. In practice this presents a
loss in accuracy, but it is still significantly better than the
previous fixed-sample-size table production method. In particular no
provision is made to handle values which scale over 65535, and it
seems we should at least warn about this if not simply fail before
letting the user go off compiling his code.

Add a new flag TEMPTABLE_FORMAT and define it as 1 to tell the code
that we are using this new and incompatible format.  This lets us
tolerate old hand-crafted thermistor tables by keeping the slower
algorithm in case one is still used.  New thermistor tables should be
defined with this new format and with the FORMAT define set accordingly.

With the default 25 samples this adds 100 bytes to the flash image for
the thermistortable storage for two different thermistors.  But the
code is simplified and saves me 134 bytes in the bargain for a net
decrease in flash size of 34 bytes.
  • Loading branch information
phord committed Apr 14, 2016
1 parent e504568 commit df3d827
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 28 deletions.
19 changes: 13 additions & 6 deletions configtool/thermistortablefile.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def generateTempTables(sensors, settings):

ofp.output("#define NUMTABLES %d" % len(tl))
ofp.output("#define NUMTEMPS %d" % N)
ofp.output("#define TEMPTABLE_FORMAT 1")
ofp.output("");

for i in range(len(tl)):
Expand All @@ -65,7 +66,7 @@ def generateTempTables(sensors, settings):
ofp.close();
return True

ofp.output("const uint16_t PROGMEM temptable[NUMTABLES][NUMTEMPS][2] = {")
ofp.output("const uint16_t PROGMEM temptable[NUMTABLES][NUMTEMPS][3] = {")

tcount = 0
for tn in tl:
Expand Down Expand Up @@ -102,6 +103,7 @@ def BetaTable(ofp, params, names, settings, finalTable):

samples = optimizeTempTable(thrm, N, hiadc)

prev = samples[0]
for i in samples:
t = thrm.temp(i)
if t is None:
Expand All @@ -117,10 +119,12 @@ def BetaTable(ofp, params, names, settings, finalTable):
c = " "
else:
c = ","
ostr = (" {%4s, %5s}%s // %4d C, %6.0f ohms, %0.3f V,"
" %0.2f mW") % (i, int(t * 4), c, int(t), int(round(r)),
vTherm, ptherm * 1000)
delta = (t-thrm.temp(prev))/(prev-i) if i!=prev else 0
ostr = (" {%4s, %5s, %5s}%s // %4d C, %6.0f ohms, %0.3f V,"
" %0.2f mW, m=%0.4f") % (i, int(t * 4), int(delta*4*256), c,
int(t), int(round(r)), vTherm, ptherm * 1000, delta)
ofp.output(ostr)
prev = i

if finalTable:
ofp.output(" }")
Expand All @@ -145,6 +149,7 @@ def SteinhartHartTable(ofp, params, names, settings, finalTable):

samples = optimizeTempTable(thrm, N, hiadc)

prev = samples[0]
for i in samples:
t = thrm.temp(i)
if t is None:
Expand All @@ -157,8 +162,10 @@ def SteinhartHartTable(ofp, params, names, settings, finalTable):
c = " "
else:
c = ","
ofp.output(" {%4d, %5d}%s // %4d C, %6d ohms" %
(i, int(t * 4), c, int(t), int(round(r))))
delta = (t-thrm.temp(prev))/(prev-i) if i!=prev else 0
ofp.output(" {%4d, %5d, %5d}%s // %4d C, %6d ohms, m=%0.4f" %
(i, int(t * 4), int(delta*4*256), c, int(t), int(round(r))), delta)
prev = i

if finalTable:
ofp.output(" }")
Expand Down
56 changes: 34 additions & 22 deletions temp.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,28 +196,40 @@ static uint16_t temp_table_lookup(uint16_t temp, uint8_t sensor) {
sersendf_P(PSTR("pin:%d Raw ADC:%d table entry: %d"),
temp_sensors[sensor].temp_pin, temp, j);

// Wikipedia's example linear interpolation formula.
// y = ((x - x₀)y₁ + (x₁-x)y₀) / (x₁ - x₀)
// y = temp
// x = ADC reading
// x₀= temptable[j-1][0]
// x₁= temptable[j][0]
// y₀= temptable[j-1][1]
// y₁= temptable[j][1]
temp = (
// ((x - x₀)y₁
((uint32_t)temp - pgm_read_word(&(temptable[table_num][j-1][0]))) *
pgm_read_word(&(temptable[table_num][j][1]))
// +
+
// (x₁-x)y₀)
(pgm_read_word(&(temptable[table_num][j][0])) - (uint32_t)temp) *
pgm_read_word(&(temptable[table_num][j - 1][1])))
// /
/
// (x₁ - x₀)
(pgm_read_word(&(temptable[table_num][j][0])) -
pgm_read_word(&(temptable[table_num][j - 1][0])));
#if (TEMPTABLE_FORMAT == 0)
// Wikipedia's example linear interpolation formula.
// y = ((x - x₀)y₁ + (x₁-x)y₀) / (x₁ - x₀)
// y = temp
// x = ADC reading
// x₀= temptable[j-1][0]
// x₁= temptable[j][0]
// y₀= temptable[j-1][1]
// y₁= temptable[j][1]
temp = (
// ((x - x₀)y₁
((uint32_t)temp - pgm_read_word(&(temptable[table_num][j-1][0]))) *
pgm_read_word(&(temptable[table_num][j][1]))
// +
+
// (x₁-x)y₀)
(pgm_read_word(&(temptable[table_num][j][0])) - (uint32_t)temp) *
pgm_read_word(&(temptable[table_num][j - 1][1])))
// /
/
// (x₁ - x₀)
(pgm_read_word(&(temptable[table_num][j][0])) -
pgm_read_word(&(temptable[table_num][j - 1][0])));
#elif (TEMPTABLE_FORMAT == 1)
// Linear interpolation using pre-computed slope
// y = y₁ - (x-x₁)*d₁
#define X1 pgm_read_word(&(temptable[table_num][j][0]))
#define Y1 pgm_read_word(&(temptable[table_num][j][1]))
#define D1 pgm_read_word(&(temptable[table_num][j][2]))

temp = Y1 - ((((int32_t)temp - X1) * D1 + (1<<7)) >> 8);
#else
#error "temptable format unrecognized"
#endif

if (DEBUG_PID && (debug_flags & DEBUG_PID))
sersendf_P(PSTR(" temp:%d.%d"), temp / 4, (temp % 4) * 25);
Expand Down

0 comments on commit df3d827

Please sign in to comment.