-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
table.py
113 lines (92 loc) · 4.06 KB
/
table.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/env python3
import sys
from math import exp, inf, log
from typing import Tuple
from click import command, echo, option, style
# This is just 25 °C converted to Kelvin.
T25 = 298.15
@command()
@option('--t1', type=float, required=True, help='Temperature of the first measurement in Celsius.')
@option('--t2', type=float, required=True, help='Temperature of the second measurement in Celsius.')
@option('--r1', type=float, required=True, help='Resistance of the first measurement in Ohms.')
@option('--r2', type=float, required=True, help='Resistance of the second measurement in Ohms.')
@option('--rf', type=float, required=True, help='Resistance of the fixed resistor in Ohms.')
@option('--min-t', type=float, default=-inf, help='Minimum temperature to generate.')
@option('--max-t', type=float, default=+inf, help='Maximum temperature to generate.')
def main(t1: float, r1: float, t2: float, r2: float, rf: float, min_t: float, max_t: float):
"""
Generate `table.h` for ADC-to-temperature conversion.
Prints `table.h` out to the stdout.
Debug messages are printed out to the stderr.
Floating point calculations on Arduino are expensive and not really needed because
you deal with the fixed number of different ADC values. Thus, I pre-generate the
conversion table and use array lookup to get actual temperature.
"""
r25, beta = get_parameters(t1, r1, t2, r2)
echo(f'R₂₅: {style(f"{r25:.2f}", fg="green", bold=True)} Ohm', err=True)
echo(f'β: {style(f"{beta:.2f}", fg="green", bold=True)} K', err=True)
print_header()
start_adc, end_adc = print_array(r25, beta, rf, min_t, max_t)
echo(f'Start ADC: {style(f"{start_adc}", fg="green", bold=True)}', err=True)
echo(f'End ADC: {style(f"{end_adc}", fg="green", bold=True)}', err=True)
print_footer(start_adc, end_adc)
def get_parameters(t1: float, r1: float, t2: float, r2: float) -> Tuple[float, float]:
"""
Gets NTC model parameters from the provided measurements.
I've used the model from the following link: http://www.giangrandi.ch/electronics/ntc/ntc.shtml
"""
t1 += 273.15
t2 += 273.15
beta = (log(r1) - log(r2)) / (1 / t1 - 1 / t2)
r25 = r1 / exp(beta * (1 / t1 - 1 / T25))
return r25, beta
def print_header():
"""Prints out `table.h` header."""
echo(f'/*')
echo(f' * ADC-to-temperature conversion table.')
echo(f' * Generated by `{" ".join(sys.argv)}`')
echo(f' */')
echo(f'')
echo(f'#ifndef NTC_TABLE_H_')
echo(f'#define NTC_TABLE_H_')
echo(f'')
def print_array(r25: float, beta: float, rf: float, min_t: float, max_t: float) -> Tuple[int, int]:
start_i = None
echo('const static float TABLE[] PROGMEM = {')
for i in range(0, 1024):
if i == 0:
# Zero NTC resistance is impossible in real life but may occur because of a mistake.
adc = 1 / 1023
elif i == 1023:
# Infinite NTC resistance is impossible in real life but may crash the program.
adc = 1022 / 1023
else:
# Scale ADC value to the range of 0..1.
adc = i / 1023
r = rf * adc / (1 - adc) # NTC resistance calculated from the ADC value.
t = 1 / (log(r / r25) / beta + 1 / T25) - 273.15 # NTC temperature.
if t < min_t:
break
if t < max_t:
if start_i is None:
start_i = i
# Print out the conversion array item.
echo(f' {t:+.2f}f, // ADC={i} index={i - start_i} R={r:.2f}')
echo('};')
return start_i, i
def print_footer(start_adc: int, end_adc: int):
echo('')
echo('float adcToTemperature(int adcValue) {')
echo(f' if (adcValue < {start_adc}) {{')
echo(f' adcValue = 0;')
echo(f' }} else if (adcValue > {end_adc - 1}) {{')
echo(f' adcValue = {end_adc - start_adc - 1};')
echo(f' }} else {{')
echo(f' adcValue -= {start_adc};')
echo(f' }}')
echo(f' return pgm_read_float_near(TABLE + adcValue);')
echo('}')
echo('')
echo('#endif')
if __name__ == '__main__':
main()