Skip to main content

vl53l0x_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 VL53L0X.
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(u8),
20    /// The signal rate limit was invalid.
21    InvalidSignalRateLimit(f32),
22    /// The measurement timing budget was too short.
23    TimingBudgetTooShort,
24    /// The device timed out.
25    Timeout,
26}
27
28/// A VL53L0X driver. Use the `new` function to create a new instance, then
29/// call `range` to get the current range, if available.
30pub struct Vl53l0x<I2C, X> {
31    i2c: I2C,
32    _x_shut: X,
33    address: u8,
34
35    stop_variable: u8,
36    measurement_timing_budget_us: u32,
37}
38
39impl<I2C, X, EI2C, EX> Vl53l0x<I2C, X>
40where
41    I2C: embedded_hal::i2c::I2c<Error = EI2C>,
42    X: embedded_hal::digital::OutputPin<Error = EX>,
43{
44    /// Create a new instance of the VL53L0X driver. This performs a reset of
45    /// the device and may fail if the device is not present. This will use the
46    /// `x_shut` pin to select the device to be reset, then it will change that
47    /// devices' address to the provided address.
48    ///
49    /// If these sensors are being used in an array, set all the xshut pins low
50    /// prior to calling this function which will allow this to only initialize
51    /// a single sensor.
52    ///
53    /// # Errors
54    /// Forwards any errors from the I2C bus and xshut pin, as well as any
55    /// initialisation errors from the device itself.
56    pub fn new(
57        i2c: I2C,
58        mut x_shut: X,
59        address: u8,
60        delay: &mut impl embedded_hal::delay::DelayNs,
61    ) -> Result<Self, InitialisationError<EI2C, EX>> {
62        // Reset the device by driving XSHUT low for 10ms.
63        x_shut.set_low().map_err(InitialisationError::XShut)?;
64        delay.delay_ms(10);
65        x_shut.set_high().map_err(InitialisationError::XShut)?;
66        delay.delay_ms(10);
67
68        let mut this = Self {
69            i2c,
70            _x_shut: x_shut,
71            address: DEFAULT_ADDRESS,
72
73            stop_variable: 0,
74            measurement_timing_budget_us: 0,
75        };
76
77        this.init(delay)?;
78
79        this.set_address(address)
80            .map_err(InitialisationError::I2C)?;
81
82        this.start_continuous(50)
83            .map_err(InitialisationError::I2C)?;
84
85        Ok(this)
86    }
87
88    /// Poll the device for a new range value. Returns `None` if the device is
89    /// still measuring.
90    ///
91    /// The range is returned in millimeters.
92    ///
93    /// # Errors
94    /// Forwards any errors from the I2C bus.
95    pub fn try_read(&mut self) -> Result<Option<u16>, EI2C> {
96        self.try_read_range_continuous_millimeters()
97    }
98}