summaryrefslogtreecommitdiffstats
path: root/src/tempmodule/temperature.c
blob: 79865855b7b88262cb07372e5f1c9902c5d2cda8 (plain)
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
#include <stddef.h>
#include "temperature.h"

/*
 * formula by applying Ohms law:
 *
 * Rt:	Thermistor resistance
 * Ra:	Voltage divider resistor
 * Vt:	Tap voltage
 * Vcc:	Input Voltage (3.31V)
 *
 * Rt = Ra * Vcc / Vt - Ra
 *
 * Using 64-bit arithmetic as 32-bit would overflow.
 * On WeMOS D1 Mini the A0 reads 3.2V as 1023; our Vcc is 3.31V
 * The correct value of the reference volume obtained by measuring
 * resistances with a multimeter, taking the ADC reading and applying
 * Ohm's law.
 * We shift the range by one to avoid division by zero.
 */

struct temptuple {
	short res;	/* Resistance in ohms. */
	short temp;	/* Temperatures in 0.1°K. */
};

int get_resistance(int64_t vt, int64_t ra)
{
	++vt;
	return ra * 1081 / vt - ra;
}

int get_temperature(int res)
{
	int ret;
	size_t i;
	static const struct temptuple lt[] = {
		{1495, 2630}, {1630, 2730}, {1772, 2830}, {1922, 2930},
		{2080, 3030}, {2245, 3130}, {2417, 3230}, {2597, 3330},
		{2785, 3430}, {2980, 3530}, {3182, 3630}, {3392, 3730},
		{3607, 3830}};

	ret = -1;

	for (i = 0; i < 12; ++i) {
		/* If we have a matching resistance, nothing to calculate. */
		if (res == lt[i].res) {
			ret = lt[i].temp;
			break;
		} else if (res == lt[i + 1].res) {
			ret = lt[i + 1].temp;
			break;
		/* If no matching resistance is found, calculate temp from subrange. */
		} else if (res > lt[i].res && res < lt[i + 1].res) {
			ret = lt[i].temp + get_temp_subrange(lt[i].res, lt[i + 1].res, res);
			break;
		}
	}

	return ret;

}

/* Returns the last 0-10 part of the temperature, in 0.1°K. */
int get_temp_subrange(short a, short b, int res)
{
	return (res - a) * 100 / (b - a);
}