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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#![deny(missing_docs)]
#![no_std]
extern crate embedded_hal as hal;
use hal::blocking::delay::DelayMs;
use hal::blocking::i2c::{Write, WriteRead};
const I2C_ADDRESS: u8 = 0x38;
#[allow(dead_code)]
#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
#[repr(u8)]
enum Command {
Calibrate = 0b1110_0001,
GetRaw = 0b1010_1000,
GetCT = 0b1010_1100,
Reset = 0b1011_1010,
}
#[macro_use]
extern crate bitflags;
bitflags! {
struct StatusFlags: u8 {
const BUSY = (1 << 7);
const MODE = ((1 << 6) | (1 << 5));
const CRC = (1 << 4);
const CALIBRATION_ENABLE = (1 << 3);
const FIFO_ENABLE = (1 << 2);
const FIFO_FULL = (1 << 1);
const FIFO_EMPTY = (1 << 0);
}
}
#[derive(Debug, Copy, Clone)]
pub enum Error<E> {
Uncalibrated(),
BusError(E),
}
impl<E> core::convert::From<E> for Error<E> {
fn from(e: E) -> Self {
Error::BusError(e)
}
}
pub struct AHT10<I2C, D> {
i2c: I2C,
delay: D,
}
pub struct Humidity {
h: u32,
}
impl Humidity {
pub fn rh(&self) -> f32 {
100.0 * (self.h as f32) / ((1 << 20) as f32)
}
pub fn raw(&self) -> u32 {
self.h
}
}
pub struct Temperature {
t: u32,
}
impl Temperature {
pub fn celsius(&self) -> f32 {
(200.0 * (self.t as f32) / ((1 << 20) as f32)) - 50.0
}
pub fn raw(&self) -> u32 {
self.t
}
}
impl<I2C, D, E> AHT10<I2C, D>
where
I2C: WriteRead<Error = E> + Write<Error = E>,
D: DelayMs<u16>,
{
pub fn new(i2c: I2C, delay: D) -> Result<Self, E> {
let mut dev = AHT10 {
i2c: i2c,
delay: delay,
};
dev.write_cmd(Command::GetRaw, 0)?;
dev.delay.delay_ms(300);
dev.write_cmd(Command::Calibrate, 0x0800)?;
dev.delay.delay_ms(300);
Ok(dev)
}
pub fn reset(&mut self) -> Result<(), E> {
self.write_cmd(Command::Reset, 0)?;
self.delay.delay_ms(20);
Ok(())
}
pub fn read(&mut self) -> Result<(Humidity, Temperature), Error<E>> {
let buf: &mut [u8; 7] = &mut [0; 7];
self.i2c
.write_read(I2C_ADDRESS, &[Command::GetCT as u8, 0b11111111, 0], buf)?;
let status = StatusFlags { bits: buf[0] };
if !status.contains(StatusFlags::CALIBRATION_ENABLE) {
return Err(Error::Uncalibrated());
}
let hum = ((buf[1] as u32) << 12) | ((buf[2] as u32) << 4) | ((buf[3] as u32) >> 4);
let temp = (((buf[3] as u32) & 0x0f) << 16) | ((buf[4] as u32) << 8) | (buf[5] as u32);
Ok((Humidity { h: hum }, Temperature { t: temp }))
}
fn write_cmd(&mut self, cmd: Command, dat: u16) -> Result<(), E> {
self.i2c.write(
I2C_ADDRESS,
&[cmd as u8, (dat >> 8) as u8, (dat & 0xff) as u8],
)
}
}