VL53LXX ToF Distance Sensor

The Vl53L0X is a Time-of-Flight (ToF) distance sensor. It is a sensor that can measure distance from a target object without touching it. The sensor uses a laser to send a pulse of light and measures the time it takes for the light to reflect back to the sensor. The sensor can measure distance up to 2 meters with a resolution of 1mm. Because of the way the sensor works, it is able to measure multiple distances at the same time.

The sensor can struggle with outdoor use, as sunlight can interfere with the sensor’s ability to measure distance. The sensor is also not able to measure distance through glass or other transparent materials.

API Reference

Header File

Classes

class Vl53l : public espp::BasePeripheral<vl53l_register_t, true>

VL53LXXX Time-of-Flight Distance Sensor.

The VL53LXX is a new generation Time-of-Flight (ToF) laser-ranging module housed in the smallest package on the market today, providing accurate distance measurement whatever the target reflectances unlike conventional technologies. It can measure absolute distances up to 2m, setting a new benchmark in ranging performance levels, opening the door to various new applications.

Example

    // make the i2c we'll use to communicate
    static constexpr auto i2c_port = I2C_NUM_0;
    static constexpr auto i2c_clock_speed = CONFIG_EXAMPLE_I2C_CLOCK_SPEED_HZ;
    static constexpr gpio_num_t i2c_sda = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO;
    static constexpr gpio_num_t i2c_scl = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO;
    logger.info("Creating I2C on port {} with SDA {} and SCL {}", i2c_port, i2c_sda, i2c_scl);
    logger.info("I2C clock speed: {} Hz", i2c_clock_speed);
    espp::I2c i2c({.port = i2c_port,
                   .sda_io_num = i2c_sda,
                   .scl_io_num = i2c_scl,
                   .sda_pullup_en = GPIO_PULLUP_ENABLE,
                   .scl_pullup_en = GPIO_PULLUP_ENABLE,
                   .clk_speed = i2c_clock_speed});

    // make the actual test object
    espp::Vl53l vl53l(
        espp::Vl53l::Config{.device_address = espp::Vl53l::DEFAULT_ADDRESS,
                            .write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1,
                                               std::placeholders::_2, std::placeholders::_3),
                            .read = std::bind(&espp::I2c::read, &i2c, std::placeholders::_1,
                                              std::placeholders::_2, std::placeholders::_3),
                            .log_level = espp::Logger::Verbosity::WARN});

    std::error_code ec;
    // set the timing budget to 10ms, which must be shorter than the
    // inter-measurement period. We'll log every 20ms so this guarantees we get
    // new data every time
    if (!vl53l.set_timing_budget_ms(10, ec)) {
      logger.error("Failed to set inter measurement period: {}", ec.message());
      return;
    }
    // set the inter-measurement period to 10ms, so we should be sure to get new
    // data each measurement
    if (!vl53l.set_inter_measurement_period_ms(10, ec)) {
      logger.error("Failed to set inter measurement period: {}", ec.message());
      return;
    }
    // tell it to start ranging
    if (!vl53l.start_ranging(ec)) {
      logger.error("Failed to start ranging: {}", ec.message());
      return;
    }

    // make the task which will read the vl53l
    fmt::print("%time (s), distance (m)\n");
    auto read_task_fn = [&vl53l]() {
      auto now = esp_timer_get_time();
      static auto start = now;
      float elapsed = (float)(now - start) / 1e6;
      std::error_code ec;
      // wait for the data to be ready
      while (!vl53l.is_data_ready(ec)) {
        std::this_thread::sleep_for(1ms);
      }
      // clear the interrupt so we can get another reading
      if (!vl53l.clear_interrupt(ec)) {
        logger.error("Failed to clear interrupt: {}", ec.message());
        return false;
      }
      auto meters = vl53l.get_distance_meters(ec);
      if (ec) {
        logger.error("Failed to get distance: {}", ec.message());
        return false;
      }
      fmt::print("{:.3f}, {:.3f}\n", elapsed, meters);
      // we don't want to stop, so return false
      return false;
    };

    espp::Timer timer({.period = 20ms,
                       .callback = read_task_fn,
                       .task_config =
                           {
                               .name = "VL53L4CX",
                               .stack_size_bytes{4 * 1024},
                           },
                       .log_level = espp::Logger::Verbosity::INFO});

Note

For an official Arduino library, see https://github.com/stm32duino/VL53L4CX

Public Types

enum class DistanceMode

Distance mode.

Values:

enumerator SHORT

Short distance mode.

enumerator MEDIUM

Medium distance mode.

enumerator LONG

Long distance mode.

enum class RangeStatus

Range status.

Values:

enumerator VALID

Range valid.

enumerator SIGMA_FAIL

Sigma fail.

enumerator SIGNAL_FAIL

Signal fail.

enumerator BELOW_RANGE

Below range.

enumerator OUT_OF_BOUNDS_FAIL

Out of bounds fail.

enumerator HARDWARE_FAIL

Hardware fail.

enumerator VALID_NO_WRAP_CHECK_FAIL

Valid, but wraparound check has not been done.

enumerator NO_MATCHING_PHASE

No matching phase.

enumerator PROCESSING_FAIL

Processing fail.

enumerator XTALK_SIGNAL_FAIL

Crosstalk signal fail.

enumerator SYNCRONISATION_INT

Synchronisation interrupt (ignore data)

enumerator RANGE_IGNORE_THRESHOLD_FAIL

Range ignore threshold fail.

typedef std::function<bool(uint8_t)> probe_fn

Function to probe the peripheral

Param address

The address to probe

Return

True if the peripheral is found at the given address

Public Functions

inline explicit Vl53l(const Config &config)

Constructor.

See also

Config

Parameters

config – Configuration

inline ModelInfo get_model_info(std::error_code &ec)

Get the ModelInfo.

See also

VL53L0X_GetModelID

Parameters

ec – Error code if unsuccessful

Returns

ModelInfo

inline uint16_t get_distance_mm(std::error_code &ec)

Get the current distance in millimeters.

Parameters

ec – Error code if unsuccessful

Returns

Distance in millimeters

inline float get_distance_cm(std::error_code &ec)

Get the current distance in centimeters.

Parameters

ec – Error code if unsuccessful

Returns

Distance in centimeters

inline float get_distance_meters(std::error_code &ec)

Get the current distance in meters.

Parameters

ec – Error code if unsuccessful

Returns

Distance in meters

inline int get_inter_measurement_period_ms() const

Get the inter-measurement period in milliseconds.

Returns

Inter-measurement period in milliseconds

inline int read_inter_measurement_period_ms(std::error_code &ec)

Read the current inter-measurement time in milliseconds.

The inter-measurement period determines how often the sensor takes a measurement. Valid range is timing_budget to 5000 ms. Set to 0 to disable continuous mode.

Parameters

ec – Error code if unsuccessful

Returns

Inter-measurement time in milliseconds

inline bool set_inter_measurement_period_ms(int period_ms, std::error_code &ec)

Set the inter-measurement time in milliseconds.

The inter-measurement period determines how often the sensor takes a measurement. Valid range is timing_budget to 5000 ms. Set to 0 to disable continuous mode.

Parameters

period_ms – Inter-measurement time in milliseconds

inline bool start_ranging(std::error_code &ec)

Start ranging.

Ranging depends on the inter-measurement setting (continuous mode vs autonomous mode). In continuous mode, the sensor will take measurements continuously. In autonomous mode, the sensor will take a single measurement each time start_ranging() is called.

See also

stop_ranging()

Parameters

ec – Error code if unsuccessful

Returns

True if successful

inline bool stop_ranging(std::error_code &ec)

Stop ranging.

Stop ranging. This will put the sensor in standby mode.

See also

start_ranging()

Parameters

ec – Error code if unsuccessful

Returns

True if successful

inline bool is_data_ready(std::error_code &ec)

Is data ready.

Check if data is ready to be read. This is used to determine if a measurement is available to be read.

Parameters

ec – Error code if unsuccessful

Returns

True if data is ready

inline bool clear_interrupt(std::error_code &ec)

Clear the interrupt.

Clear the interrupt. This is called automatically by start_ranging().

See also

start_ranging()

Parameters

ec – Error code if unsuccessful

Returns

True if successful

inline int get_timing_budget_ms() const

Get the current timing budget in milliseconds.

Returns

Timing budget in milliseconds

inline uint32_t get_timing_budget_us() const

Get the current timing budget in microseconds.

Returns

Timing budget in microseconds

inline uint32_t read_timing_budget_ms(std::error_code &ec)

Read the current timing budget in microseconds.

The timing budget is the time allowed for one measurement. Valid range is 10ms to 200ms. It cannot be greater than the inter-measurement period.

Parameters

ec – Error code if unsuccessful

Returns

Timing budget in microseconds

inline float get_timing_budget_seconds()

Get the current timing budget in seconds.

The timing budget is the time allowed for one measurement. Valid range is 10ms to 200ms. It cannot be greater than the inter-measurement period.

Returns

Timing budget in seconds

inline float read_timing_budget_seconds(std::error_code &ec)

Read the current timing budget in seconds.

The timing budget is the time allowed for one measurement. Valid range is 10ms to 200ms. It cannot be greater than the inter-measurement period.

Parameters

ec – Error code if unsuccessful

Returns

Timing budget in seconds

inline bool set_timing_budget_us(uint32_t budget_us, std::error_code &ec)

Set the timing budget in microseconds.

The timing budget is the time allowed for one measurement. Valid range is 10ms to 200ms. It cannot be greater than the inter-measurement period.

Parameters

budget_us – Timing budget in microseconds

inline bool set_timing_budget_ms(uint32_t budget_ms, std::error_code &ec)

Set the timing budget in milliseconds.

The timing budget is the time allowed for one measurement. Valid range is 10ms to 200ms.

Parameters
  • budget_ms – Timing budget in milliseconds

  • ec – Error code if unsuccessful

Returns

True if successful

inline bool probe(std::error_code &ec)

Probe the peripheral

Note

This function is thread safe

Note

If the probe function is not set, this function will return false and set the error code to operation_not_supported

Note

This function is only available if UseAddress is true

Parameters

ec – The error code to set if there is an error

Returns

True if the peripheral is found

inline void set_address(uint8_t address)

Set the address of the peripheral

Note

This function is thread safe

Note

This function is only available if UseAddress is true

Parameters

address – The address of the peripheral

inline void set_probe(const probe_fn &probe)

Set the probe function

Note

This function is thread safe

Note

This should rarely be used, as the probe function is usually set in the constructor. If you need to change the probe function, consider using the set_config function instead.

Note

This function is only available if UseAddress is true

Parameters

probe – The probe function

inline void set_write(const write_fn &write)

Set the write function

Note

This function is thread safe

Note

This should rarely be used, as the write function is usually set in the constructor. If you need to change the write function, consider using the set_config function instead.

Parameters

write – The write function

inline void set_read(const read_fn &read)

Set the read function

Note

This function is thread safe

Note

This should rarely be used, as the read function is usually set in the constructor. If you need to change the read function, consider using the set_config function instead.

Parameters

read – The read function

inline void set_read_register(const read_register_fn &read_register)

Set the read register function

Note

This function is thread safe

Note

This should rarely be used, as the read register function is usually set in the constructor. If you need to change the read register function, consider using the set_config function instead.

Parameters

read_register – The read register function

inline void set_write_then_read(const write_then_read_fn &write_then_read)

Set the write then read function

Note

This function is thread safe

Note

This should rarely be used, as the write then read function is usually set in the constructor. If you need to change the write then

Parameters

write_then_read – The write then read function

inline void set_separate_write_then_read_delay(const std::chrono::milliseconds &delay)

Set the delay between the write and read operations in write_then_read

Note

This function is thread safe

Note

This should rarely be used, as the delay is usually set in the constructor. If you need to change the delay, consider using the set_config function instead.

Note

This delay is only used if the write_then_read function is not set to a custom function and the write and read functions are separate functions.

Parameters

delay – The delay between the write and read operations in write_then_read

inline void set_config(const Config &config)

Set the configuration for the peripheral

Note

This function is thread safe

Note

The configuration should normally be set in the constructor, but this function can be used to change the configuration after the peripheral has been created - for instance if the peripheral could be found on different communications buses.

Parameters

config – The configuration for the peripheral

inline void set_config(Config &&config)

Set the configuration for the peripheral

Note

This function is thread safe

Note

The configuration should normally be set in the constructor, but this function can be used to change the configuration after the peripheral has been created - for instance if the peripheral could be found on different communications buses.

Parameters

config – The configuration for the peripheral

inline const std::string &get_name() const

Get the name of the component

Note

This is the tag of the logger

Returns

A const reference to the name of the component

inline void set_log_tag(const std::string_view &tag)

Set the tag for the logger

Parameters

tag – The tag to use for the logger

inline espp::Logger::Verbosity get_log_level() const

Get the log level for the logger

Returns

The verbosity level of the logger

inline void set_log_level(espp::Logger::Verbosity level)

Set the log level for the logger

Parameters

level – The verbosity level to use for the logger

inline void set_log_verbosity(espp::Logger::Verbosity level)

Set the log verbosity for the logger

See also

set_log_level

Note

This is a convenience method that calls set_log_level

Parameters

level – The verbosity level to use for the logger

inline espp::Logger::Verbosity get_log_verbosity() const

Get the log verbosity for the logger

See also

get_log_level

Note

This is a convenience method that calls get_log_level

Returns

The verbosity level of the logger

inline void set_log_rate_limit(std::chrono::duration<float> rate_limit)

Set the rate limit for the logger

Note

Only calls to the logger that have _rate_limit suffix will be rate limited

Parameters

rate_limit – The rate limit to use for the logger

struct Config

Configuration for the VL53LXX.

Public Members

uint8_t device_address = DEFAULT_ADDRESS

I2C address of the VL53LXX.

BasePeripheral<vl53l_register_t, true>::write_fn write = nullptr

Write function.

BasePeripheral<vl53l_register_t, true>::read_fn read = nullptr

Read function.

bool auto_init = true

Automatically initialize the sensor.

Logger::Verbosity log_level = Logger::Verbosity::WARN

Log level for this class.

struct ModelInfo

Model ID and module type.

Public Members

uint8_t model_id = {0}

Model ID.

uint8_t module_type = {0}

Module type.

struct RangeData

Range data.

Public Members

int16_t max_mm

Maximum distance in millimeters.

int16_t min_mm

Minimum distance in millimeters.

float return_rate_mcps

Return rate in MCPS (mega counts per second)

float ambient_rate_mcps

Ambient rate in MCPS (mega counts per second)

float sigma_mm

Sigma in millimeters.

int16_t range_mm

Range in millimeters.