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
extern crate byteorder;
extern crate i2cdev;
extern crate i2csensors;
use byteorder::{BigEndian, ByteOrder};
use i2cdev::core::I2CDevice;
use i2csensors::{Hygrometer, Thermometer};
pub const SI7021_I2C_ADDRESS: u16 = 0x40;
const MEASURE_RELATIVE_HUMIDITY: u8 = 0xE5;
const MEASURE_TEMPERATURE: u8 = 0xE3;
const READ_TEMPERATURE: u8 = 0xE0;
#[derive(Clone, Debug)]
pub struct Si7021<T> {
device: T,
}
impl<T> Si7021<T>
where T: I2CDevice
{
pub fn new(device: T) -> Si7021<T> {
Si7021 {
device,
}
}
pub fn last_temperature(&mut self) -> Result<f32, T::Error> {
let raw_temperature = self.read_word(READ_TEMPERATURE)?;
Ok(calculate_temperature(raw_temperature))
}
fn read_word(&mut self, command: u8) -> Result<u16, T::Error> {
let mut buf = [0u8; 2];
self.device.write(&[command])?;
self.device.read(&mut buf)?;
Ok(BigEndian::read_u16(&buf))
}
}
impl<T> Hygrometer for Si7021<T>
where T: I2CDevice
{
type Error = T::Error;
fn relative_humidity(&mut self) -> Result<f32, Self::Error> {
let raw_humidity = self.read_word(MEASURE_RELATIVE_HUMIDITY)?;
Ok(calculate_relative_humidity(raw_humidity))
}
}
impl<T> Thermometer for Si7021<T>
where T: I2CDevice
{
type Error = T::Error;
fn temperature_celsius(&mut self) -> Result<f32, Self::Error> {
let raw_temperature = self.read_word(MEASURE_TEMPERATURE)?;
Ok(calculate_temperature(raw_temperature))
}
}
fn calculate_relative_humidity(raw_humidity: u16) -> f32 {
let relative_humidity = 125.0 * raw_humidity as f32 / 65536.0 - 6.0;
relative_humidity.max(0.0).min(100.0)
}
fn calculate_temperature(raw_temperature: u16) -> f32 {
175.72 * raw_temperature as f32 / 65536.0 - 46.85
}