1#![no_std]
2
3use data::Aht10Data;
4use embedded_hal as hal;
7use hal::blocking::{
8 delay::DelayMs,
9 i2c::{Read, Write},
10};
11
12pub mod data;
13
14const AHT10_ADDRESS: u8 = 0x38;
15
16const AHT10_INIT_MODE_NORMAL: u8 = 0x00;
17
18const AHT10_INIT_MODE_CYCLE: u8 = 0x20;
19const AHT10_INIT_MODE_CMD: u8 = 0x40; const AHT10_INIT_CALIBRATION_ON: u8 = 0x08;
22const AHT10_INIT_CALIBRATION_OFF: u8 = 0x00;
23
24enum Aht10Commands {
25 Initialization = 0b1110_0001,
26 TriggerMeasure = 0b1010_1100,
27 SoftReset = 0b1011_1010,
28}
29
30#[derive(Debug, Copy, Clone)]
31pub enum AhtError<E> {
32 ReadTimeout,
33 BusError(E),
34}
35
36#[derive(Debug, Copy, Clone)]
37pub struct Aht10Status {
38 pub is_busy: bool,
39 pub working_mode: u8,
40 pub calibration_enable: bool,
41}
42
43pub struct AHT10<I2C> {
44 i2c_dev: I2C,
45}
46
47impl<I2C, E> AHT10<I2C>
48where
49 I2C: Write<Error = E> + Read<Error = E>,
50{
51 pub fn new(i2c: I2C) -> Self {
52 Self { i2c_dev: i2c }
53 }
54
55 pub fn initialize(&mut self) -> Result<(), AhtError<E>> {
57 self.write_command(
58 Aht10Commands::Initialization,
59 AHT10_INIT_MODE_NORMAL | AHT10_INIT_CALIBRATION_ON,
60 0x00,
61 )
62 }
63
64 pub fn read_status(&mut self) -> Result<Aht10Status, AhtError<E>> {
66 let mut buffer: [u8; 6] = [0; 6];
67 self.i2c_dev
68 .read(AHT10_ADDRESS, &mut buffer)
69 .map_err(|e| AhtError::BusError(e))?;
70
71 let is_busy = (buffer[0] & 0x80) > 0;
72 let working_mode = (buffer[0] & 0x60) >> 4;
73 let calibration_enable = (buffer[0] & 0x08) > 0;
74
75 Ok(Aht10Status {
76 is_busy,
77 working_mode,
78 calibration_enable,
79 })
80 }
81
82 pub fn read_data<Delay: DelayMs<u16>>(
84 &mut self,
85 delay: &mut Delay,
86 ) -> Result<Aht10Data, AhtError<E>> {
87 self.write_command(Aht10Commands::TriggerMeasure, 0x33, 0x00)?; let mut status = self.read_status()?;
90 for _ in 0..3 {
91 if !status.is_busy {
92 break;
93 }
94
95 delay.delay_ms(75);
96 status = self.read_status()?;
97 }
98
99 if status.is_busy {
100 return Err(AhtError::ReadTimeout);
101 }
102
103 let raw = self.read_raw_data()?;
104 Ok(Aht10Data::new(raw))
105 }
106
107 pub fn soft_reset<Delay: DelayMs<u16>>(
109 &mut self,
110 delay: &mut Delay,
111 ) -> Result<(), AhtError<E>> {
112 self.write_command(Aht10Commands::SoftReset, 0, 0)?;
113 delay.delay_ms(20);
114 Ok(())
115 }
116
117 fn write_command(
118 &mut self,
119 cmd: Aht10Commands,
120 data0: u8,
121 data1: u8,
122 ) -> Result<(), AhtError<E>> {
123 self.i2c_dev
124 .write(AHT10_ADDRESS, &[cmd as u8, data0, data1])
125 .map_err(|e| AhtError::BusError(e))
126 }
127
128 fn read_raw_data(&mut self) -> Result<[u8; 5], AhtError<E>> {
129 let mut buffer: [u8; 6] = [0; 6];
130 self.i2c_dev
131 .read(AHT10_ADDRESS, &mut buffer)
132 .map_err(|e| AhtError::BusError(e))?;
133
134 Ok(buffer[1..6].try_into().unwrap())
135 }
136}