embedded_sensors/bh1750/
mod.rs1use 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}