1#![no_std]
2
3use libm::{
16 powf,
17 sqrtf,
18 floorf,
19};
20
21#[allow(dead_code)]
22#[non_exhaustive]
23#[derive(Clone, Copy)]
24pub enum ADCRes {
25 B8 = 255,
26 B10 = 1_023,
27 B12 = 4_095,
28 B14 = 16_383,
29 B16 = 65_535,
30 B18 = 262_143,
31 B20 = 1_048_575,
32 B22 = 4_194_303,
33 B24 = 16_777_215,
34}
35
36#[allow(dead_code)]
37#[non_exhaustive]
38#[derive(Clone, Copy)]
39pub enum RTDType {
40 PT100 = 100,
41 PT200 = 200,
42 PT500 = 500,
43 PT1000 = 1000,
44}
45
46#[allow(dead_code)]
47#[non_exhaustive]
48struct RTDCorrection;
49
50impl RTDCorrection {
51 pub const PT100: Polynomial = [1.51892983e-10, -2.85842067e-08, -5.34227299e-06,
52 1.80282972e-03, -1.61875985e-01, 4.84112370e+00];
53 pub const PT200: Polynomial = [0_f32; 6]; pub const PT500: Polynomial = [0_f32; 6]; pub const PT1000: Polynomial = [1.51892983e-15, -2.85842067e-12, -5.34227299e-09,
56 1.80282972e-05, -1.61875985e-02, 4.84112370e+00];
57}
58type Polynomial = [f32; 6];
59
60const A: f32 = 3.9083e-3;
61const B: f32 = -5.7750e-7;
62const C: f32 = -4.1830e-12;
63
64#[allow(dead_code)]
68pub fn calc_t(r: f32, r_0: RTDType) -> Result<f32, Error> {
69 let r_min = floorf(calc_r(-200_f32, r_0).unwrap()) as i32;
70 let r_max = floorf(calc_r(850_f32, r_0).unwrap()) as i32;
71
72 let corr_poly: Result<[f32; 6], Error> = match r_0 {
74 RTDType::PT100 => Ok(RTDCorrection::PT100),
75 RTDType::PT200 => Ok(RTDCorrection::PT200),
76 RTDType::PT500 => Ok(RTDCorrection::PT500),
77 RTDType::PT1000 => Ok(RTDCorrection::PT1000),
78 };
79
80 let r_0 = r_0 as i32 as f32;
82 let mut t = ( -r_0 * A + sqrtf( powf(r_0, 2_f32) * powf(A, 2_f32) - 4_f32 * r_0 * B * ( r_0 - r as f32 ) ) ) / ( 2_f32 * r_0 as f32 * B );
83
84 match corr_poly {
85 Ok(poly) => {
86 match (floorf(r) as i32, r_0 as i32) {
87 (r, r_0) if r_0 <= r && r <= r_max => {
88 Ok(t)
90 },
91 (r, r_0) if r_min <= r && r < r_0 => {
92 t += poly_correction(r as f32, poly);
95 Ok(t)
96 },
97 _ => Err(Error::OutOfBounds),
98 }
99 },
100 Err(_) => Err(Error::NonexistentType),
101 }
102}
103
104#[allow(dead_code)]
109pub fn calc_r(t: f32, r_0: RTDType) -> Result<f32, Error> {
110 let r_0 = r_0 as i32;
111 match floorf(t) as i32 {
112 0..=850 => Ok(r_0 as f32 * ( 1_f32 + A * t + B * powf(t, 2_f32) )),
113 -200..=-1 => Ok(r_0 as f32 * ( 1_f32 + A * t + B * powf(t, 2_f32) + C * ( t - 100_f32 ) * powf(t, 3_f32) )),
114 _ => Err(Error::OutOfBounds),
115 }
116}
117
118#[allow(dead_code)]
120pub fn conv_d_val_to_r(d_val: u32, r_ref: u32, res: ADCRes, pga_gain: u32) -> Result<f32, Error> {
121 let res = res as u32;
122 match d_val {
123 d if d <= res => Ok(d_val as f32 * r_ref as f32 / ( res as f32 * pga_gain as f32)),
124 _ => Err(Error::OutOfBounds),
125 }
126}
127
128#[allow(dead_code)]
130fn poly_correction(r: f32, poly: Polynomial) -> f32 {
131 let mut res = 0_f32;
132 for (i, factor) in poly.iter().enumerate() {
133 res += factor * powf(r, i as f32);
134 };
135 res
136}
137
138#[derive(Debug)]
139pub enum Error {
140 OutOfBounds,
141 NonexistentType,
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn resistance_calculation() {
150 let t = 0.0;
151
152 let r = calc_r(t, RTDType::PT100).unwrap();
153 assert_eq!(r, 100_f32);
154 }
155
156 #[test]
157 fn temperature_calculation() {
158 let r = 100.0;
159
160 let t = calc_t(r, RTDType::PT100).unwrap();
161 assert_eq!(t, 0_f32);
162 }
163}