embedded_sensors/bh1750/
mod.rs

1use core::marker::PhantomData;
2
3use embedded_hal::blocking::i2c;
4
5use self::{
6    config::{Config, MeasurementMode},
7    result::Error,
8};
9
10pub mod config;
11mod register;
12pub mod result;
13
14pub struct Bh1750<I2C> {
15    addr: u8,
16    cfg: Config,
17    light_level: f32,
18    _i2c: PhantomData<I2C>,
19}
20
21impl<I2C, I2cError> Bh1750<I2C>
22where
23    I2C: i2c::Read<Error = I2cError> + i2c::Write<Error = I2cError>,
24{
25    pub fn new(addr: u8, i2c: &mut I2C) -> Result<Self, Error<I2cError>> {
26        Self::with_configuration(addr, i2c, Config::default())
27    }
28
29    pub fn with_configuration(
30        addr: u8,
31        i2c: &mut I2C,
32        cfg: Config,
33    ) -> Result<Self, Error<I2cError>> {
34        let mut bh = Self {
35            addr,
36            cfg,
37            light_level: 0.0,
38            _i2c: PhantomData::default(),
39        };
40
41        bh.init(i2c)?;
42
43        Ok(bh)
44    }
45
46    fn init(&mut self, i2c: &mut I2C) -> Result<(), Error<I2cError>> {
47        self.set_measurement_mode(i2c, self.cfg.measurement_mode)?;
48        self.set_measurement_time(i2c, self.cfg.measurement_time)?;
49        Ok(())
50    }
51
52    pub fn measurement_mode(&self) -> MeasurementMode {
53        self.cfg.measurement_mode
54    }
55
56    pub fn set_measurement_mode(
57        &mut self,
58        i2c: &mut I2C,
59        measurement_mode: MeasurementMode,
60    ) -> Result<(), Error<I2cError>> {
61        Self::write_register(self.addr, i2c, measurement_mode as u8)?;
62        self.cfg.measurement_mode = measurement_mode;
63        Ok(())
64    }
65
66    pub fn measurement_time(&self) -> MeasurementMode {
67        self.cfg.measurement_mode
68    }
69
70    pub fn set_measurement_time(
71        &mut self,
72        i2c: &mut I2C,
73        measurement_time: u8,
74    ) -> Result<(), Error<I2cError>> {
75        if measurement_time < 31 || measurement_time > 254 {
76            return Err(Error::InvalidMeasurementTime(measurement_time));
77        }
78
79        Self::write_register(
80            self.addr,
81            i2c,
82            (0b01000 << 3) | (measurement_time as u8 >> 5),
83        )?;
84        Self::write_register(self.addr, i2c, (0b011 << 5) | (measurement_time & 0b11111))?;
85        self.cfg.measurement_time = measurement_time;
86        Ok(())
87    }
88
89    pub fn light_level(&self) -> f32 {
90        self.light_level
91    }
92
93    pub fn read(&mut self, i2c: &mut I2C) -> Result<(), Error<I2cError>> {
94        let mut buf = [0; 2];
95
96        Self::read_register(self.addr, i2c, self.cfg.measurement_mode as u8, &mut buf)?;
97
98        let light_level = u16::from_be_bytes(buf);
99        self.light_level = match self.cfg.measurement_mode {
100            MeasurementMode::ContinuouslyHighResolution
101            | MeasurementMode::OneTimeHighResolution => {
102                light_level as f32 / 1.2 * (69.0 / self.cfg.measurement_time as f32)
103            }
104            MeasurementMode::ContinuouslyHighResolution2
105            | MeasurementMode::OneTimeHighResolution2 => {
106                light_level as f32 / 1.2 * (69.0 / self.cfg.measurement_time as f32) / 2.0
107            }
108            MeasurementMode::ContinuouslyLowResolution | MeasurementMode::OneTimeLowResolution => {
109                light_level as f32 / 1.2
110            }
111        };
112
113        Ok(())
114    }
115
116    fn read_register(
117        addr: u8,
118        i2c: &mut I2C,
119        reg: u8,
120        buf: &mut [u8],
121    ) -> Result<(), Error<I2cError>> {
122        match i2c.write(addr, &[reg as u8]) {
123            Ok(()) => {}
124            Err(e) => return Err(Error::I2cError(e)),
125        }
126
127        match i2c.read(addr, buf) {
128            Ok(()) => Ok(()),
129            Err(e) => Err(Error::I2cError(e)),
130        }
131    }
132
133    fn write_register(addr: u8, i2c: &mut I2C, reg: u8) -> Result<(), Error<I2cError>> {
134        match i2c.write(addr, &[reg]) {
135            Ok(()) => Ok(()),
136            Err(e) => Err(Error::I2cError(e)),
137        }
138    }
139}