#![no_std]
use core::fmt;
use embedded_hal::blocking::delay::DelayMs;
use embedded_hal::blocking::i2c::{Read, Write, WriteRead};
use log::info;
pub struct Dht20<I2C, D> {
i2c: I2C,
address: u8,
delay: D,
}
#[derive(Debug, Clone)]
pub struct Reading {
pub temp: f32,
pub hum: f32,
}
#[derive(Debug)]
pub enum Error<E: fmt::Debug> {
I2cError(E),
ReadToFast,
}
impl<I2C, E, D> Dht20<I2C, D>
where
I2C: Read<Error = E> + Write<Error = E> + WriteRead<Error = E>,
E: fmt::Debug,
D: DelayMs<u16>,
{
pub fn new(i2c: I2C, address: u8, delay: D) -> Self {
Self {
i2c,
address,
delay,
}
}
pub fn read(&mut self) -> Result<Reading, E> {
self.reset()?;
self.write_data(&[0xAC, 0x33, 0])?;
self.delay.delay_ms(80);
let data = self.read_data()?;
let mut raw = (data[1] as u32) << 8;
raw += data[2] as u32;
raw <<= 4;
raw += (data[3] >> 4) as u32;
let hum = raw as f32 * 9.5367431640625e-5;
let mut raw = (data[3] & 0x0F) as u32;
raw <<= 8;
raw += data[4] as u32;
raw <<= 8;
raw += data[5] as u32;
let temp = raw as f32 * 1.9073486328125e-4 - 50.0; Ok(Reading { temp, hum })
}
fn reset(&mut self) -> Result<(), E> {
let status = self.read_status()?;
if status & 0x18 != 0x18 {
info!("resetting");
self.write_data(&[0x1B, 0, 0])?;
self.write_data(&[0x1C, 0, 0])?;
self.write_data(&[0x1E, 0, 0])?;
}
Ok(())
}
fn read_data(&mut self) -> Result<[u8; 8], E> {
let mut buffer = [0; 8];
self.i2c.read(self.address, &mut buffer)?;
Ok(buffer)
}
fn read_status(&mut self) -> Result<u8, E> {
let mut buffer = [0; 1];
self.i2c.read(self.address, &mut buffer)?;
Ok(buffer[0])
}
fn write_data(&mut self, data: &[u8]) -> Result<(), E> {
self.i2c.write(self.address, data)
}
}