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
use hal::blocking::i2c;
use {BitFlagsLow, Error, Register, SensorData, Tmp006};
impl<I2C, E> Tmp006<I2C>
where
I2C: i2c::WriteRead<Error = E>,
{
pub fn read_object_temperature(
&mut self,
calibration_factor: f64,
) -> nb::Result<f64, Error<E>> {
let data = self.read_sensor_data()?;
let temp = self.calculate_object_temperature(data, calibration_factor);
Ok(temp)
}
pub fn calculate_object_temperature(&self, data: SensorData, calibration_factor: f64) -> f64 {
const A1: f64 = 1.75e-3;
const A2: f64 = -1.678e-5;
const B0: f64 = -2.94e-5;
const B1: f64 = -5.7e-7;
const B2: f64 = 4.63e-9;
const C2: f64 = 13.4;
const T_REF: f64 = 298.15;
const V_LSB_SIZE: f64 = 156.25e-9;
let v_obj = f64::from(data.object_voltage) * V_LSB_SIZE;
let t_die_k = f64::from(data.ambient_temperature) / 128.0 + 273.15;
let t_diff = t_die_k - T_REF;
let t_diff_sq = t_diff * t_diff;
let v_os = B0 + B1 * t_diff + B2 * t_diff_sq;
let v_diff = v_obj - v_os;
let fv_obj = v_diff + C2 * v_diff * v_diff;
let s0 = calibration_factor;
let s = s0 * (1.0 + A1 * t_diff + A2 * t_diff_sq);
libm::pow(libm::pow(t_die_k, 4.0) + fv_obj / s, 0.25)
}
pub fn read_sensor_data(&mut self) -> nb::Result<SensorData, Error<E>> {
let ready = self.is_data_ready().map_err(nb::Error::Other)?;
if !ready {
return Err(nb::Error::WouldBlock);
}
let v = self
.read_register(Register::V_OBJECT)
.map_err(nb::Error::Other)?;
let temp = self
.read_register(Register::TEMP_AMBIENT)
.map_err(nb::Error::Other)?;
let data = SensorData {
object_voltage: v as i16,
ambient_temperature: temp as i16 / 4,
};
Ok(data)
}
#[allow(clippy::wrong_self_convention)]
pub fn is_data_ready(&mut self) -> Result<bool, Error<E>> {
let config = self.read_register(Register::CONFIG)?;
Ok((config & u16::from(BitFlagsLow::DRDY)) != 0)
}
pub fn read_manufacturer_id(&mut self) -> Result<u16, Error<E>> {
self.read_register(Register::MANUFAC_ID)
}
pub fn read_device_id(&mut self) -> Result<u16, Error<E>> {
self.read_register(Register::DEVICE_ID)
}
fn read_register(&mut self, register: u8) -> Result<u16, Error<E>> {
let mut data = [0; 2];
self.i2c
.write_read(self.address, &[register], &mut data)
.map_err(Error::I2C)?;
Ok((u16::from(data[0]) << 8) | u16::from(data[1]))
}
}