vl53l1x_simple/lib.rs
1#![doc = include_str!("../README.md")]
2#![no_std]
3
4mod imp;
5mod reg;
6
7/// The default I2C address for the VL53L1X.
8pub const DEFAULT_ADDRESS: u8 = 0b010_1001;
9
10/// Possible errors that can occur during initialisation.
11#[derive(Debug)]
12pub enum InitialisationError<EI2C, EX> {
13 /// An error occurred on the I2C bus.
14 I2C(EI2C),
15 /// An error occurred setting the xshut pin.
16 XShut(EX),
17
18 /// The model ID read from the device was invalid.
19 InvalidModelId(u16),
20 /// The device timed out.
21 Timeout,
22 /// The timing budget was invalid.
23 InvalidTimingBudget,
24}
25
26/// A VL53L1X driver. Use the `new` function to create a new instance, then
27/// call `range` to get the current range, if available.
28pub struct Vl53l1x<I2C, X> {
29 i2c: I2C,
30 _x_shut: X,
31 address: u8,
32
33 fast_osc_frequency: u16,
34 osc_calibrate_val: u16,
35 distance_mode: imp::DistanceMode,
36 calibrated: bool,
37 saved_vhv_init: u8,
38 saved_vhv_timeout: u8,
39}
40
41impl<I2C, X, EI2C, EX> Vl53l1x<I2C, X>
42where
43 I2C: embedded_hal::i2c::I2c<Error = EI2C>,
44 X: embedded_hal::digital::OutputPin<Error = EX>,
45{
46 /// Create a new instance of the VL53L1X driver. This performs a reset of
47 /// the device and may fail if the device is not present. This will use the
48 /// `x_shut` pin to select the device to be reset, then it will change that
49 /// devices' address to the provided address.
50 ///
51 /// If these sensors are being used in an array, set all the xshut pins low
52 /// prior to calling this function which will allow this to only initialize
53 /// a single sensor.
54 ///
55 /// # Errors
56 /// Forwards any errors from the I2C bus and xshut pin, as well as any
57 /// initialisation errors from the device itself.
58 pub fn new(
59 i2c: I2C,
60 mut x_shut: X,
61 address: u8,
62 delay: &mut impl embedded_hal::delay::DelayNs,
63 ) -> Result<Self, InitialisationError<EI2C, EX>> {
64 // Reset the device by driving XSHUT low for 10ms.
65 x_shut.set_low().map_err(InitialisationError::XShut)?;
66 delay.delay_ms(10);
67 x_shut.set_high().map_err(InitialisationError::XShut)?;
68 delay.delay_ms(10);
69
70 let mut this = Self {
71 i2c,
72 _x_shut: x_shut,
73 address: DEFAULT_ADDRESS,
74
75 fast_osc_frequency: 0,
76 osc_calibrate_val: 0,
77 distance_mode: imp::DistanceMode::Long,
78 calibrated: false,
79 saved_vhv_init: 0,
80 saved_vhv_timeout: 0,
81 };
82
83 this.init(delay)?;
84
85 this.set_address(address)
86 .map_err(InitialisationError::I2C)?;
87
88 this.start_continuous(50)
89 .map_err(InitialisationError::I2C)?;
90
91 Ok(this)
92 }
93
94 /// Poll the device for a new range value. Returns `None` if the device is
95 /// still measuring.
96 ///
97 /// The range is returned in millimeters.
98 ///
99 /// # Errors
100 /// Forwards any errors from the I2C bus.
101 pub fn try_read(&mut self) -> Result<Option<u16>, EI2C> {
102 self.try_read_inner()
103 }
104}