1 /*
2  * Copyright (c) 2019 Vestas Wind Systems A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr.h>
8 #include <device.h>
9 #include <drivers/adc.h>
10 #include <stdio.h>
11 #include <math.h>
12 
13 #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
14 #include <logging/log.h>
15 LOG_MODULE_REGISTER(main);
16 
17 /* Nominal RTD (PT100) resistance in ohms */
18 #define RTD_NOMINAL_RESISTANCE 100
19 
20 /* ADC resolution in bits */
21 #define ADC_RESOLUTION 24U
22 
23 /* ADC maximum value (taking sign bit into consideration) */
24 #define ADC_MAX BIT_MASK(ADC_RESOLUTION - 1)
25 
26 /* Bottom resistor value in ohms */
27 #define BOTTOM_RESISTANCE 2000
28 
29 #ifndef CONFIG_NEWLIB_LIBC
sqrt(double value)30 static double sqrt(double value)
31 {
32 	double sqrt = value / 3;
33 	int i;
34 
35 	if (value <= 0) {
36 		return 0;
37 	}
38 
39 	for (i = 0; i < 6; i++) {
40 		sqrt = (sqrt + value / sqrt) / 2;
41 	}
42 
43 	return sqrt;
44 }
45 #endif /* CONFIG_NEWLIB_LIBC */
46 
rtd_temperature(int nom,double resistance)47 static double rtd_temperature(int nom, double resistance)
48 {
49 	const double a0 =  3.90802E-3;
50 	const double b0 = -0.58020E-6;
51 	double temp;
52 
53 	temp = -nom * a0;
54 	temp += sqrt((nom * nom) * (a0 * a0) - 4.0 * nom * b0 *
55 		     (nom - resistance));
56 	temp /= 2.0 * nom * b0;
57 
58 	return temp;
59 }
60 
main(void)61 void main(void)
62 {
63 	const struct device *lmp90100 = DEVICE_DT_GET_ONE(ti_lmp90100);
64 	double resistance;
65 	int32_t buffer;
66 	int err;
67 	const struct adc_channel_cfg ch_cfg = {
68 		.channel_id = 0,
69 		.differential = 1,
70 		.input_positive = 0,
71 		.input_negative = 1,
72 		.reference = ADC_REF_EXTERNAL1,
73 		.gain = ADC_GAIN_1,
74 		.acquisition_time = ADC_ACQ_TIME(ADC_ACQ_TIME_TICKS, 0)
75 	};
76 	const struct adc_sequence seq = {
77 		.options = NULL,
78 		.channels = BIT(0),
79 		.buffer = &buffer,
80 		.buffer_size = sizeof(buffer),
81 		.resolution = ADC_RESOLUTION,
82 		.oversampling = 0,
83 		.calibrate = 0
84 	};
85 
86 	if (!device_is_ready(lmp90100)) {
87 		LOG_ERR("LMP90100 device not ready");
88 		return;
89 	}
90 
91 	err = adc_channel_setup(lmp90100, &ch_cfg);
92 	if (err) {
93 		LOG_ERR("failed to setup ADC channel (err %d)", err);
94 		return;
95 	}
96 
97 	while (true) {
98 		err = adc_read(lmp90100, &seq);
99 		if (err) {
100 			LOG_ERR("failed to read ADC (err %d)", err);
101 		} else {
102 			resistance = (buffer / (double)ADC_MAX) * BOTTOM_RESISTANCE;
103 			printf("R: %.02f ohm\n", resistance);
104 			printf("T: %.02f degC\n",
105 				rtd_temperature(RTD_NOMINAL_RESISTANCE,
106 						resistance));
107 		}
108 
109 		k_sleep(K_MSEC(1000));
110 	}
111 }
112