This commit is contained in:
Jason2866 2020-08-23 19:53:15 +02:00
parent 6e111477a0
commit e5baabc41c
13 changed files with 2681 additions and 3 deletions

View File

@ -73,4 +73,5 @@ Index | Define | Driver | Device | Address(es) | Description
49 | USE_VEML6075 | xsns_70 | VEML6075 | 0x10 | UVA/UVB/UVINDEX Sensor
50 | USE_VEML7700 | xsns_71 | VEML7700 | 0x10 | Ambient light intensity sensor
51 | USE_MCP9808 | xsns_72 | MCP9808 | 0x18 - 0x1F | Temperature sensor
52 | USE_HP303B | xsns_73 | HP303B | 0x76 - 0x77 | Pressure and temperature sensor
52 | USE_HP303B | xsns_73 | HP303B | 0x76 - 0x77 | Pressure and temperature sensor
53 | USE_VL53L1X | xsns_77 | VL53L1X | 0x52 | Time-of-flight (ToF) distance sensor

View File

@ -0,0 +1,24 @@
language: python
cache:
directories:
- "~/.platformio"
install:
- pip install -U platformio
env:
- BOARD=uno
- BOARD=leonardo
- BOARD=micro
- BOARD=megaatmega2560
- BOARD=due
- BOARD=yun
- BOARD=genuino101
- BOARD=zero
script:
- set -eo pipefail;
for e in examples/*; do
platformio ci --board=$BOARD --lib=. $e/*;
done

View File

@ -0,0 +1,42 @@
Most of the functionality of this library is based on the VL53L1X API provided
provided by ST (STSW-IMG007), and some of the explanatory comments are quoted
or paraphrased from the API source code, API user manual (UM2356), and VL53L1X
datasheet. Therefore, the license terms for the API source code (BSD 3-clause
"New" or "Revised" License) also apply to this derivative work, as specified
below.
For more information, see
https://www.pololu.com/
https://forum.pololu.com/
--------------------------------------------------------------------------------
Copyright (c) 2017, STMicroelectronics
Copyright (c) 2018, Pololu Corporation
All Rights Reserved
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

166
lib/vl53l1x-1.0.0/README.md Normal file
View File

@ -0,0 +1,166 @@
# VL53L1X library for Arduino
Version: 1.0.0<br>
Release date: 2018-05-31<br>
[![Build Status](https://travis-ci.org/pololu/vl53l1x-arduino.svg?branch=master)](https://travis-ci.org/pololu/vl53l1x-arduino)<br>
[www.pololu.com](https://www.pololu.com/)
## Summary
This is a library for the Arduino IDE that helps interface with ST's [VL53L1X time-of-flight distance sensor](https://www.pololu.com/product/3415). The library makes it simple to configure the sensor and read range data from it via I&sup2;C.
## Supported platforms
This library is designed to work with the Arduino IDE versions 1.6.x or later; we have not tested it with earlier versions. This library should support any Arduino-compatible board, including the [Pololu A-Star controllers](https://www.pololu.com/category/149/a-star-programmable-controllers).
## Getting started
### Hardware
A [VL53L1X carrier](https://www.pololu.com/product/3415) can be purchased from Pololu's website. Before continuing, careful reading of the [product page](https://www.pololu.com/product/3415) as well as the VL53L1X datasheet is recommended.
Make the following connections between the Arduino and the VL53L1X board:
#### 5V Arduino boards
(including Arduino Uno, Leonardo, Mega; Pololu A-Star 32U4)
Arduino VL53L1X board
------- -------------
5V - VIN
GND - GND
SDA - SDA
SCL - SCL
#### 3.3V Arduino boards
(including Arduino Due)
Arduino VL53L1X board
------- -------------
3V3 - VIN
GND - GND
SDA - SDA
SCL - SCL
### Software
If you are using version 1.6.2 or later of the [Arduino software (IDE)](http://www.arduino.cc/en/Main/Software), you can use the Library Manager to install this library:
1. In the Arduino IDE, open the "Sketch" menu, select "Include Library", then "Manage Libraries...".
2. Search for "VL53L1X".
3. Click the VL53L1X entry in the list.
4. Click "Install".
If this does not work, you can manually install the library:
1. Download the [latest release archive from GitHub](https://github.com/pololu/vl53l1x-arduino/releases) and decompress it.
2. Rename the folder "vl53l1x-arduino-master" to "VL53L1X".
3. Move the "VL53L1X" folder into the "libraries" directory inside your Arduino sketchbook directory. You can view your sketchbook location by opening the "File" menu and selecting "Preferences" in the Arduino IDE. If there is not already a "libraries" folder in that location, you should make the folder yourself.
4. After installing the library, restart the Arduino IDE.
## Examples
Several example sketches are available that show how to use the library. You can access them from the Arduino IDE by opening the "File" menu, selecting "Examples", and then selecting "VL53L1X". If you cannot find these examples, the library was probably installed incorrectly and you should retry the installation instructions above.
## ST's VL53L1X API and this library
Most of the functionality of this library is based on the [VL53L1X API](http://www.st.com/content/st_com/en/products/embedded-software/proximity-sensors-software/stsw-img007.html) provided by ST (STSW-IMG007), and some of the explanatory comments in the code are quoted or paraphrased from the API source code, API user manual (UM2356), and the VL53L1X datasheet. For more explanation about the library code and how it was derived from the API, see the comments in VL53L1X.cpp.
This library is intended to provide a quicker and easier way to get started using the VL53L1X with an Arduino-compatible controller, in contrast to using ST's API on the Arduino. The library has a more streamlined interface, as well as smaller storage and memory footprints. However, it does not currently implement some of the more advanced functionality available in the API (for example, calibrating the sensor to work well under a cover glass or selecting a smaller region of interest (ROI)), and it has less robust error checking. For advanced applications, especially when storage and memory are less of an issue, consider using the VL53L1X API directly. We have an [implementation of ST's VL53L1X API for Arduino](https://github.com/pololu/vl53l1x-st-api-arduino) available.
## Library reference
* `RangingData ranging_data`<br>
This struct contains information about the last ranging measurement. Its members are:
* `uint16_t range_mm`<br>
Range reading from the last measurement, in millimeters. (This reading can also be obtained as the return value of `read()`.)
* `RangeStatus range_status`<br>
Status of the last measurement; see the definition of the `RangeStatus` enumeration type in VL53L1X.h (or the API user manual and source code) for descriptions of the possible statuses. A status of `VL53L1X::RangeValid` means there were no problems with the measurement.
* `float peak_signal_count_rate_MCPS`<br>
Peak signal count rate of the last measurement, in units of mega counts per second.
* `float ambient_count_rate_MCPS`<br>
Ambient count rate of the last measurement, in units of mega counts per second.
* `uint8_t last_status`<br>
The status of the last I&sup2;C write transmission. See the [`Wire.endTransmission()` documentation](http://arduino.cc/en/Reference/WireEndTransmission) for return values.
* `VL53L1X()`<br>
Constructor.
* `void setAddress(uint8_t new_addr)`<br>
Changes the I&sup2;C slave device address of the VL53L1X to the given value (7-bit).
* `uint8_t getAddress()`<br>
Returns the current I&sup2;C address.
* `bool init(bool io_2v8 = true)`<br>
Iniitializes and configures the sensor. If the optional argument `io_2v8` is true (the default if not specified), the sensor is configured for 2V8 mode (2.8 V I/O); if false, the sensor is left in 1V8 mode. The return value is a boolean indicating whether the initialization completed successfully.
* `void writeReg(uint16_t reg, uint8_t value)`<br>
Writes an 8-bit sensor register with the given value.
Register address constants are defined by the `regAddr` enumeration type in VL53L1X.h.<br>
Example use: `sensor.writeReg(VL53L1X::SOFT_RESET, 0x00);`
* `void writeReg16Bit(uint16_t reg, uint16_t value)`<br>
Writes a 16-bit sensor register with the given value.
* `void writeReg32Bit(uint16_t reg, uint32_t value)`<br>
Writes a 32-bit sensor register with the given value.
* `uint8_t readReg(uint16_t reg)`<br>
Reads an 8-bit sensor register and returns the value read.
* `uint16_t readReg16Bit(uint16_t reg)`<br>
Reads a 16-bit sensor register and returns the value read.
* `uint32_t readReg32Bit(uint16_t reg)`<br>
Reads a 32-bit sensor register and returns the value read.
* `bool setDistanceMode(DistanceMode mode)`<br>
Sets the distance mode of the sensor (`VL53L1X::Short`, `VL53L1X::Medium`, or `VL53L1X::Long`). Shorter distance modes are less affected by ambient light but have lower maximum ranges. See the datasheet for more information. The return value is a boolean indicating whether the requested mode was valid.
* `DistanceMode getDistanceMode()`<br>
Returns the previously set distance mode.
* `bool setMeasurementTimingBudget(uint32_t budget_us)`<br>
Sets the measurement timing budget to the given value in microseconds. This is the time allowed for one range measurement; a longer timing budget allows for more accurate measurements. The minimum budget is 20 ms (20000 us) in short distance mode and 33 ms for medium and long distance modes. See the VL53L1X datasheet for more information on range and timing limits. The return value is a boolean indicating whether the requested budget was valid.
* `uint32_t getMeasurementTimingBudget()`<br>
Returns the current measurement timing budget in microseconds.
* `void startContinuous(uint32_t period_ms)`<br>
Starts continuous ranging measurements. The specified inter-measurement period in milliseconds determines how often the sensor takes a measurement; if it is shorter than the timing budget, the sensor will start a new measurement as soon as the previous one finishes.
* `void stopContinuous()`<br>
Stops continuous mode.
* `uint16_t read(bool blocking = true)`<br>
After continuous ranging measurements have been started, calling this function returns a range reading in millimeters and updates the `ranging_data` struct with details about the last measurement. If the optional argument `blocking` is true (the default if not specified), this function will wait until data from a new measurement is available before returning.
If you do not want this function to block, you can use the `dataReady()` function to check if new data is available before calling `read(false)`. Calling `read(false)` before new data is available will return a reading of 0, and `ranging_data.range_status` will have the value `VL53L1X::None`, indicating that there has been no update.
* `uint16_t readRangeContinuousMillimeters(bool blocking = true)`<br>
Alias of `read()` for convenience.
* `bool dataReady()`<br>
Returns a boolean indicating whether data from a new measurement is available from the sensor.
* `static const char * rangeStatusToString(RangeStatus status)`<br>
Converts a `RangeStatus` into a readable string describing that status.
Note that on an AVR, the strings in this function are stored in RAM (dynamic memory), which makes working with them easier but uses up 200+ bytes of RAM (many AVR-based Arduinos only have about 2000 bytes of RAM). You can avoid this memory usage if you do not call this function in your sketch.
* `void setTimeout(uint16_t timeout)`<br>
Sets a timeout period in milliseconds after which read operations will abort if the sensor is not ready. A value of 0 disables the timeout.
* `uint16_t getTimeout()`<br>
Returns the current timeout period setting.
* `bool timeoutOccurred()`<br>
Indicates whether a read timeout has occurred since the last call to `timeoutOccurred()`.
## Version history
* 1.0.0 (2018-05-31): Original release.

View File

@ -0,0 +1,782 @@
// Most of the functionality of this library is based on the VL53L1X API
// provided by ST (STSW-IMG007), and some of the explanatory comments are quoted
// or paraphrased from the API source code, API user manual (UM2356), and
// VL53L1X datasheet.
#include <VL53L1X.h>
#include <Wire.h>
// Constructors ////////////////////////////////////////////////////////////////
VL53L1X::VL53L1X()
: address(AddressDefault)
, io_timeout(0) // no timeout
, did_timeout(false)
, calibrated(false)
, saved_vhv_init(0)
, saved_vhv_timeout(0)
, distance_mode(Unknown)
{
}
// Public Methods //////////////////////////////////////////////////////////////
void VL53L1X::setAddress(uint8_t new_addr)
{
writeReg(I2C_SLAVE__DEVICE_ADDRESS, new_addr & 0x7F);
address = new_addr;
}
// Initialize sensor using settings taken mostly from VL53L1_DataInit() and
// VL53L1_StaticInit().
// If io_2v8 (optional) is true or not given, the sensor is configured for 2V8
// mode.
bool VL53L1X::init(bool io_2v8)
{
// check model ID and module type registers (values specified in datasheet)
if (readReg16Bit(IDENTIFICATION__MODEL_ID) != 0xEACC) { return false; }
// VL53L1_software_reset() begin
writeReg(SOFT_RESET, 0x00);
delayMicroseconds(100);
writeReg(SOFT_RESET, 0x01);
// VL53L1_poll_for_boot_completion() begin
startTimeout();
while ((readReg(FIRMWARE__SYSTEM_STATUS) & 0x01) == 0)
{
if (checkTimeoutExpired())
{
did_timeout = true;
return false;
}
}
// VL53L1_poll_for_boot_completion() end
// VL53L1_software_reset() end
// VL53L1_DataInit() begin
// sensor uses 1V8 mode for I/O by default; switch to 2V8 mode if necessary
if (io_2v8)
{
writeReg(PAD_I2C_HV__EXTSUP_CONFIG,
readReg(PAD_I2C_HV__EXTSUP_CONFIG) | 0x01);
}
// store oscillator info for later use
fast_osc_frequency = readReg16Bit(OSC_MEASURED__FAST_OSC__FREQUENCY);
osc_calibrate_val = readReg16Bit(RESULT__OSC_CALIBRATE_VAL);
// VL53L1_DataInit() end
// VL53L1_StaticInit() begin
// Note that the API does not actually apply the configuration settings below
// when VL53L1_StaticInit() is called: it keeps a copy of the sensor's
// register contents in memory and doesn't actually write them until a
// measurement is started. Writing the configuration here means we don't have
// to keep it all in memory and avoids a lot of redundant writes later.
// the API sets the preset mode to LOWPOWER_AUTONOMOUS here:
// VL53L1_set_preset_mode() begin
// VL53L1_preset_mode_standard_ranging() begin
// values labeled "tuning parm default" are from vl53l1_tuning_parm_defaults.h
// (API uses these in VL53L1_init_tuning_parm_storage_struct())
// static config
// API resets PAD_I2C_HV__EXTSUP_CONFIG here, but maybe we don't want to do
// that? (seems like it would disable 2V8 mode)
writeReg16Bit(DSS_CONFIG__TARGET_TOTAL_RATE_MCPS, TargetRate); // should already be this value after reset
writeReg(GPIO__TIO_HV_STATUS, 0x02);
writeReg(SIGMA_ESTIMATOR__EFFECTIVE_PULSE_WIDTH_NS, 8); // tuning parm default
writeReg(SIGMA_ESTIMATOR__EFFECTIVE_AMBIENT_WIDTH_NS, 16); // tuning parm default
writeReg(ALGO__CROSSTALK_COMPENSATION_VALID_HEIGHT_MM, 0x01);
writeReg(ALGO__RANGE_IGNORE_VALID_HEIGHT_MM, 0xFF);
writeReg(ALGO__RANGE_MIN_CLIP, 0); // tuning parm default
writeReg(ALGO__CONSISTENCY_CHECK__TOLERANCE, 2); // tuning parm default
// general config
writeReg16Bit(SYSTEM__THRESH_RATE_HIGH, 0x0000);
writeReg16Bit(SYSTEM__THRESH_RATE_LOW, 0x0000);
writeReg(DSS_CONFIG__APERTURE_ATTENUATION, 0x38);
// timing config
// most of these settings will be determined later by distance and timing
// budget configuration
writeReg16Bit(RANGE_CONFIG__SIGMA_THRESH, 360); // tuning parm default
writeReg16Bit(RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS, 192); // tuning parm default
// dynamic config
writeReg(SYSTEM__GROUPED_PARAMETER_HOLD_0, 0x01);
writeReg(SYSTEM__GROUPED_PARAMETER_HOLD_1, 0x01);
writeReg(SD_CONFIG__QUANTIFIER, 2); // tuning parm default
// VL53L1_preset_mode_standard_ranging() end
// from VL53L1_preset_mode_timed_ranging_*
// GPH is 0 after reset, but writing GPH0 and GPH1 above seem to set GPH to 1,
// and things don't seem to work if we don't set GPH back to 0 (which the API
// does here).
writeReg(SYSTEM__GROUPED_PARAMETER_HOLD, 0x00);
writeReg(SYSTEM__SEED_CONFIG, 1); // tuning parm default
// from VL53L1_config_low_power_auto_mode
writeReg(SYSTEM__SEQUENCE_CONFIG, 0x8B); // VHV, PHASECAL, DSS1, RANGE
writeReg16Bit(DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT, 200 << 8);
writeReg(DSS_CONFIG__ROI_MODE_CONTROL, 2); // REQUESTED_EFFFECTIVE_SPADS
// VL53L1_set_preset_mode() end
// default to long range, 50 ms timing budget
// note that this is different than what the API defaults to
setDistanceMode(Long);
setMeasurementTimingBudget(50000);
// VL53L1_StaticInit() end
// the API triggers this change in VL53L1_init_and_start_range() once a
// measurement is started; assumes MM1 and MM2 are disabled
writeReg16Bit(ALGO__PART_TO_PART_RANGE_OFFSET_MM,
readReg16Bit(MM_CONFIG__OUTER_OFFSET_MM) * 4);
return true;
}
// Write an 8-bit register
void VL53L1X::writeReg(uint16_t reg, uint8_t value)
{
Wire.beginTransmission(address);
Wire.write((reg >> 8) & 0xFF); // reg high byte
Wire.write( reg & 0xFF); // reg low byte
Wire.write(value);
last_status = Wire.endTransmission();
}
// Write a 16-bit register
void VL53L1X::writeReg16Bit(uint16_t reg, uint16_t value)
{
Wire.beginTransmission(address);
Wire.write((reg >> 8) & 0xFF); // reg high byte
Wire.write( reg & 0xFF); // reg low byte
Wire.write((value >> 8) & 0xFF); // value high byte
Wire.write( value & 0xFF); // value low byte
last_status = Wire.endTransmission();
}
// Write a 32-bit register
void VL53L1X::writeReg32Bit(uint16_t reg, uint32_t value)
{
Wire.beginTransmission(address);
Wire.write((reg >> 8) & 0xFF); // reg high byte
Wire.write( reg & 0xFF); // reg low byte
Wire.write((value >> 24) & 0xFF); // value highest byte
Wire.write((value >> 16) & 0xFF);
Wire.write((value >> 8) & 0xFF);
Wire.write( value & 0xFF); // value lowest byte
last_status = Wire.endTransmission();
}
// Read an 8-bit register
uint8_t VL53L1X::readReg(regAddr reg)
{
uint8_t value;
Wire.beginTransmission(address);
Wire.write((reg >> 8) & 0xFF); // reg high byte
Wire.write( reg & 0xFF); // reg low byte
last_status = Wire.endTransmission();
Wire.requestFrom(address, (uint8_t)1);
value = Wire.read();
return value;
}
// Read a 16-bit register
uint16_t VL53L1X::readReg16Bit(uint16_t reg)
{
uint16_t value;
Wire.beginTransmission(address);
Wire.write((reg >> 8) & 0xFF); // reg high byte
Wire.write( reg & 0xFF); // reg low byte
last_status = Wire.endTransmission();
Wire.requestFrom(address, (uint8_t)2);
value = (uint16_t)Wire.read() << 8; // value high byte
value |= Wire.read(); // value low byte
return value;
}
// Read a 32-bit register
uint32_t VL53L1X::readReg32Bit(uint16_t reg)
{
uint32_t value;
Wire.beginTransmission(address);
Wire.write((reg >> 8) & 0xFF); // reg high byte
Wire.write( reg & 0xFF); // reg low byte
last_status = Wire.endTransmission();
Wire.requestFrom(address, (uint8_t)4);
value = (uint32_t)Wire.read() << 24; // value highest byte
value |= (uint32_t)Wire.read() << 16;
value |= (uint16_t)Wire.read() << 8;
value |= Wire.read(); // value lowest byte
return value;
}
// set distance mode to Short, Medium, or Long
// based on VL53L1_SetDistanceMode()
bool VL53L1X::setDistanceMode(DistanceMode mode)
{
// save existing timing budget
uint32_t budget_us = getMeasurementTimingBudget();
switch (mode)
{
case Short:
// from VL53L1_preset_mode_standard_ranging_short_range()
// timing config
writeReg(RANGE_CONFIG__VCSEL_PERIOD_A, 0x07);
writeReg(RANGE_CONFIG__VCSEL_PERIOD_B, 0x05);
writeReg(RANGE_CONFIG__VALID_PHASE_HIGH, 0x38);
// dynamic config
writeReg(SD_CONFIG__WOI_SD0, 0x07);
writeReg(SD_CONFIG__WOI_SD1, 0x05);
writeReg(SD_CONFIG__INITIAL_PHASE_SD0, 6); // tuning parm default
writeReg(SD_CONFIG__INITIAL_PHASE_SD1, 6); // tuning parm default
break;
case Medium:
// from VL53L1_preset_mode_standard_ranging()
// timing config
writeReg(RANGE_CONFIG__VCSEL_PERIOD_A, 0x0B);
writeReg(RANGE_CONFIG__VCSEL_PERIOD_B, 0x09);
writeReg(RANGE_CONFIG__VALID_PHASE_HIGH, 0x78);
// dynamic config
writeReg(SD_CONFIG__WOI_SD0, 0x0B);
writeReg(SD_CONFIG__WOI_SD1, 0x09);
writeReg(SD_CONFIG__INITIAL_PHASE_SD0, 10); // tuning parm default
writeReg(SD_CONFIG__INITIAL_PHASE_SD1, 10); // tuning parm default
break;
case Long: // long
// from VL53L1_preset_mode_standard_ranging_long_range()
// timing config
writeReg(RANGE_CONFIG__VCSEL_PERIOD_A, 0x0F);
writeReg(RANGE_CONFIG__VCSEL_PERIOD_B, 0x0D);
writeReg(RANGE_CONFIG__VALID_PHASE_HIGH, 0xB8);
// dynamic config
writeReg(SD_CONFIG__WOI_SD0, 0x0F);
writeReg(SD_CONFIG__WOI_SD1, 0x0D);
writeReg(SD_CONFIG__INITIAL_PHASE_SD0, 14); // tuning parm default
writeReg(SD_CONFIG__INITIAL_PHASE_SD1, 14); // tuning parm default
break;
default:
// unrecognized mode - do nothing
return false;
}
// reapply timing budget
setMeasurementTimingBudget(budget_us);
// save mode so it can be returned by getDistanceMode()
distance_mode = mode;
return true;
}
// Set the measurement timing budget in microseconds, which is the time allowed
// for one measurement. A longer timing budget allows for more accurate
// measurements.
// based on VL53L1_SetMeasurementTimingBudgetMicroSeconds()
bool VL53L1X::setMeasurementTimingBudget(uint32_t budget_us)
{
// assumes PresetMode is LOWPOWER_AUTONOMOUS
if (budget_us <= TimingGuard) { return false; }
uint32_t range_config_timeout_us = budget_us -= TimingGuard;
if (range_config_timeout_us > 1100000) { return false; } // FDA_MAX_TIMING_BUDGET_US * 2
range_config_timeout_us /= 2;
// VL53L1_calc_timeout_register_values() begin
uint32_t macro_period_us;
// "Update Macro Period for Range A VCSEL Period"
macro_period_us = calcMacroPeriod(readReg(RANGE_CONFIG__VCSEL_PERIOD_A));
// "Update Phase timeout - uses Timing A"
// Timeout of 1000 is tuning parm default (TIMED_PHASECAL_CONFIG_TIMEOUT_US_DEFAULT)
// via VL53L1_get_preset_mode_timing_cfg().
uint32_t phasecal_timeout_mclks = timeoutMicrosecondsToMclks(1000, macro_period_us);
if (phasecal_timeout_mclks > 0xFF) { phasecal_timeout_mclks = 0xFF; }
writeReg(PHASECAL_CONFIG__TIMEOUT_MACROP, phasecal_timeout_mclks);
// "Update MM Timing A timeout"
// Timeout of 1 is tuning parm default (LOWPOWERAUTO_MM_CONFIG_TIMEOUT_US_DEFAULT)
// via VL53L1_get_preset_mode_timing_cfg(). With the API, the register
// actually ends up with a slightly different value because it gets assigned,
// retrieved, recalculated with a different macro period, and reassigned,
// but it probably doesn't matter because it seems like the MM ("mode
// mitigation"?) sequence steps are disabled in low power auto mode anyway.
writeReg16Bit(MM_CONFIG__TIMEOUT_MACROP_A, encodeTimeout(
timeoutMicrosecondsToMclks(1, macro_period_us)));
// "Update Range Timing A timeout"
writeReg16Bit(RANGE_CONFIG__TIMEOUT_MACROP_A, encodeTimeout(
timeoutMicrosecondsToMclks(range_config_timeout_us, macro_period_us)));
// "Update Macro Period for Range B VCSEL Period"
macro_period_us = calcMacroPeriod(readReg(RANGE_CONFIG__VCSEL_PERIOD_B));
// "Update MM Timing B timeout"
// (See earlier comment about MM Timing A timeout.)
writeReg16Bit(MM_CONFIG__TIMEOUT_MACROP_B, encodeTimeout(
timeoutMicrosecondsToMclks(1, macro_period_us)));
// "Update Range Timing B timeout"
writeReg16Bit(RANGE_CONFIG__TIMEOUT_MACROP_B, encodeTimeout(
timeoutMicrosecondsToMclks(range_config_timeout_us, macro_period_us)));
// VL53L1_calc_timeout_register_values() end
return true;
}
// Get the measurement timing budget in microseconds
// based on VL53L1_SetMeasurementTimingBudgetMicroSeconds()
uint32_t VL53L1X::getMeasurementTimingBudget()
{
// assumes PresetMode is LOWPOWER_AUTONOMOUS and these sequence steps are
// enabled: VHV, PHASECAL, DSS1, RANGE
// VL53L1_get_timeouts_us() begin
// "Update Macro Period for Range A VCSEL Period"
uint32_t macro_period_us = calcMacroPeriod(readReg(RANGE_CONFIG__VCSEL_PERIOD_A));
// "Get Range Timing A timeout"
uint32_t range_config_timeout_us = timeoutMclksToMicroseconds(decodeTimeout(
readReg16Bit(RANGE_CONFIG__TIMEOUT_MACROP_A)), macro_period_us);
// VL53L1_get_timeouts_us() end
return 2 * range_config_timeout_us + TimingGuard;
}
// Start continuous ranging measurements, with the given inter-measurement
// period in milliseconds determining how often the sensor takes a measurement.
void VL53L1X::startContinuous(uint32_t period_ms)
{
// from VL53L1_set_inter_measurement_period_ms()
writeReg32Bit(SYSTEM__INTERMEASUREMENT_PERIOD, period_ms * osc_calibrate_val);
writeReg(SYSTEM__INTERRUPT_CLEAR, 0x01); // sys_interrupt_clear_range
writeReg(SYSTEM__MODE_START, 0x40); // mode_range__timed
}
// Stop continuous measurements
// based on VL53L1_stop_range()
void VL53L1X::stopContinuous()
{
writeReg(SYSTEM__MODE_START, 0x80); // mode_range__abort
// VL53L1_low_power_auto_data_stop_range() begin
calibrated = false;
// "restore vhv configs"
if (saved_vhv_init != 0)
{
writeReg(VHV_CONFIG__INIT, saved_vhv_init);
}
if (saved_vhv_timeout != 0)
{
writeReg(VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND, saved_vhv_timeout);
}
// "remove phasecal override"
writeReg(PHASECAL_CONFIG__OVERRIDE, 0x00);
// VL53L1_low_power_auto_data_stop_range() end
}
// Returns a range reading in millimeters when continuous mode is active
// (readRangeSingleMillimeters() also calls this function after starting a
// single-shot range measurement)
uint16_t VL53L1X::read(bool blocking)
{
if (blocking)
{
startTimeout();
while (!dataReady())
{
if (checkTimeoutExpired())
{
did_timeout = true;
ranging_data.range_status = None;
ranging_data.range_mm = 0;
ranging_data.peak_signal_count_rate_MCPS = 0;
ranging_data.ambient_count_rate_MCPS = 0;
return ranging_data.range_mm;
}
}
}
readResults();
if (!calibrated)
{
setupManualCalibration();
calibrated = true;
}
updateDSS();
getRangingData();
writeReg(SYSTEM__INTERRUPT_CLEAR, 0x01); // sys_interrupt_clear_range
return ranging_data.range_mm;
}
// convert a RangeStatus to a readable string
// Note that on an AVR, these strings are stored in RAM (dynamic memory), which
// makes working with them easier but uses up 200+ bytes of RAM (many AVR-based
// Arduinos only have about 2000 bytes of RAM). You can avoid this memory usage
// if you do not call this function in your sketch.
const char * VL53L1X::rangeStatusToString(RangeStatus status)
{
switch (status)
{
case RangeValid:
return "range valid";
case SigmaFail:
return "sigma fail";
case SignalFail:
return "signal fail";
case RangeValidMinRangeClipped:
return "range valid, min range clipped";
case OutOfBoundsFail:
return "out of bounds fail";
case HardwareFail:
return "hardware fail";
case RangeValidNoWrapCheckFail:
return "range valid, no wrap check fail";
case WrapTargetFail:
return "wrap target fail";
case XtalkSignalFail:
return "xtalk signal fail";
case SynchronizationInt:
return "synchronization int";
case MinRangeFail:
return "min range fail";
case None:
return "no update";
default:
return "unknown status";
}
}
// Did a timeout occur in one of the read functions since the last call to
// timeoutOccurred()?
bool VL53L1X::timeoutOccurred()
{
bool tmp = did_timeout;
did_timeout = false;
return tmp;
}
// Private Methods /////////////////////////////////////////////////////////////
// "Setup ranges after the first one in low power auto mode by turning off
// FW calibration steps and programming static values"
// based on VL53L1_low_power_auto_setup_manual_calibration()
void VL53L1X::setupManualCalibration()
{
// "save original vhv configs"
saved_vhv_init = readReg(VHV_CONFIG__INIT);
saved_vhv_timeout = readReg(VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND);
// "disable VHV init"
writeReg(VHV_CONFIG__INIT, saved_vhv_init & 0x7F);
// "set loop bound to tuning param"
writeReg(VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND,
(saved_vhv_timeout & 0x03) + (3 << 2)); // tuning parm default (LOWPOWERAUTO_VHV_LOOP_BOUND_DEFAULT)
// "override phasecal"
writeReg(PHASECAL_CONFIG__OVERRIDE, 0x01);
writeReg(CAL_CONFIG__VCSEL_START, readReg(PHASECAL_RESULT__VCSEL_START));
}
// read measurement results into buffer
void VL53L1X::readResults()
{
Wire.beginTransmission(address);
Wire.write((RESULT__RANGE_STATUS >> 8) & 0xFF); // reg high byte
Wire.write( RESULT__RANGE_STATUS & 0xFF); // reg low byte
last_status = Wire.endTransmission();
Wire.requestFrom(address, (uint8_t)17);
results.range_status = Wire.read();
Wire.read(); // report_status: not used
results.stream_count = Wire.read();
results.dss_actual_effective_spads_sd0 = (uint16_t)Wire.read() << 8; // high byte
results.dss_actual_effective_spads_sd0 |= Wire.read(); // low byte
Wire.read(); // peak_signal_count_rate_mcps_sd0: not used
Wire.read();
results.ambient_count_rate_mcps_sd0 = (uint16_t)Wire.read() << 8; // high byte
results.ambient_count_rate_mcps_sd0 |= Wire.read(); // low byte
Wire.read(); // sigma_sd0: not used
Wire.read();
Wire.read(); // phase_sd0: not used
Wire.read();
results.final_crosstalk_corrected_range_mm_sd0 = (uint16_t)Wire.read() << 8; // high byte
results.final_crosstalk_corrected_range_mm_sd0 |= Wire.read(); // low byte
results.peak_signal_count_rate_crosstalk_corrected_mcps_sd0 = (uint16_t)Wire.read() << 8; // high byte
results.peak_signal_count_rate_crosstalk_corrected_mcps_sd0 |= Wire.read(); // low byte
}
// perform Dynamic SPAD Selection calculation/update
// based on VL53L1_low_power_auto_update_DSS()
void VL53L1X::updateDSS()
{
uint16_t spadCount = results.dss_actual_effective_spads_sd0;
if (spadCount != 0)
{
// "Calc total rate per spad"
uint32_t totalRatePerSpad =
(uint32_t)results.peak_signal_count_rate_crosstalk_corrected_mcps_sd0 +
results.ambient_count_rate_mcps_sd0;
// "clip to 16 bits"
if (totalRatePerSpad > 0xFFFF) { totalRatePerSpad = 0xFFFF; }
// "shift up to take advantage of 32 bits"
totalRatePerSpad <<= 16;
totalRatePerSpad /= spadCount;
if (totalRatePerSpad != 0)
{
// "get the target rate and shift up by 16"
uint32_t requiredSpads = ((uint32_t)TargetRate << 16) / totalRatePerSpad;
// "clip to 16 bit"
if (requiredSpads > 0xFFFF) { requiredSpads = 0xFFFF; }
// "override DSS config"
writeReg16Bit(DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT, requiredSpads);
// DSS_CONFIG__ROI_MODE_CONTROL should already be set to REQUESTED_EFFFECTIVE_SPADS
return;
}
}
// If we reached this point, it means something above would have resulted in a
// divide by zero.
// "We want to gracefully set a spad target, not just exit with an error"
// "set target to mid point"
writeReg16Bit(DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT, 0x8000);
}
// get range, status, rates from results buffer
// based on VL53L1_GetRangingMeasurementData()
void VL53L1X::getRangingData()
{
// VL53L1_copy_sys_and_core_results_to_range_results() begin
uint16_t range = results.final_crosstalk_corrected_range_mm_sd0;
// "apply correction gain"
// gain factor of 2011 is tuning parm default (VL53L1_TUNINGPARM_LITE_RANGING_GAIN_FACTOR_DEFAULT)
// Basically, this appears to scale the result by 2011/2048, or about 98%
// (with the 1024 added for proper rounding).
ranging_data.range_mm = ((uint32_t)range * 2011 + 0x0400) / 0x0800;
// VL53L1_copy_sys_and_core_results_to_range_results() end
// set range_status in ranging_data based on value of RESULT__RANGE_STATUS register
// mostly based on ConvertStatusLite()
switch(results.range_status)
{
case 17: // MULTCLIPFAIL
case 2: // VCSELWATCHDOGTESTFAILURE
case 1: // VCSELCONTINUITYTESTFAILURE
case 3: // NOVHVVALUEFOUND
// from SetSimpleData()
ranging_data.range_status = HardwareFail;
break;
case 13: // USERROICLIP
// from SetSimpleData()
ranging_data.range_status = MinRangeFail;
break;
case 18: // GPHSTREAMCOUNT0READY
ranging_data.range_status = SynchronizationInt;
break;
case 5: // RANGEPHASECHECK
ranging_data.range_status = OutOfBoundsFail;
break;
case 4: // MSRCNOTARGET
ranging_data.range_status = SignalFail;
break;
case 6: // SIGMATHRESHOLDCHECK
ranging_data.range_status = SignalFail;
break;
case 7: // PHASECONSISTENCY
ranging_data.range_status = WrapTargetFail;
break;
case 12: // RANGEIGNORETHRESHOLD
ranging_data.range_status = XtalkSignalFail;
break;
case 8: // MINCLIP
ranging_data.range_status = RangeValidMinRangeClipped;
break;
case 9: // RANGECOMPLETE
// from VL53L1_copy_sys_and_core_results_to_range_results()
if (results.stream_count == 0)
{
ranging_data.range_status = RangeValidNoWrapCheckFail;
}
else
{
ranging_data.range_status = RangeValid;
}
break;
default:
ranging_data.range_status = None;
}
// from SetSimpleData()
ranging_data.peak_signal_count_rate_MCPS =
countRateFixedToFloat(results.peak_signal_count_rate_crosstalk_corrected_mcps_sd0);
ranging_data.ambient_count_rate_MCPS =
countRateFixedToFloat(results.ambient_count_rate_mcps_sd0);
}
// Decode sequence step timeout in MCLKs from register value
// based on VL53L1_decode_timeout()
uint32_t VL53L1X::decodeTimeout(uint16_t reg_val)
{
return ((uint32_t)(reg_val & 0xFF) << (reg_val >> 8)) + 1;
}
// Encode sequence step timeout register value from timeout in MCLKs
// based on VL53L1_encode_timeout()
uint16_t VL53L1X::encodeTimeout(uint32_t timeout_mclks)
{
// encoded format: "(LSByte * 2^MSByte) + 1"
uint32_t ls_byte = 0;
uint16_t ms_byte = 0;
if (timeout_mclks > 0)
{
ls_byte = timeout_mclks - 1;
while ((ls_byte & 0xFFFFFF00) > 0)
{
ls_byte >>= 1;
ms_byte++;
}
return (ms_byte << 8) | (ls_byte & 0xFF);
}
else { return 0; }
}
// Convert sequence step timeout from macro periods to microseconds with given
// macro period in microseconds (12.12 format)
// based on VL53L1_calc_timeout_us()
uint32_t VL53L1X::timeoutMclksToMicroseconds(uint32_t timeout_mclks, uint32_t macro_period_us)
{
return ((uint64_t)timeout_mclks * macro_period_us + 0x800) >> 12;
}
// Convert sequence step timeout from microseconds to macro periods with given
// macro period in microseconds (12.12 format)
// based on VL53L1_calc_timeout_mclks()
uint32_t VL53L1X::timeoutMicrosecondsToMclks(uint32_t timeout_us, uint32_t macro_period_us)
{
return (((uint32_t)timeout_us << 12) + (macro_period_us >> 1)) / macro_period_us;
}
// Calculate macro period in microseconds (12.12 format) with given VCSEL period
// assumes fast_osc_frequency has been read and stored
// based on VL53L1_calc_macro_period_us()
uint32_t VL53L1X::calcMacroPeriod(uint8_t vcsel_period)
{
// from VL53L1_calc_pll_period_us()
// fast osc frequency in 4.12 format; PLL period in 0.24 format
uint32_t pll_period_us = ((uint32_t)0x01 << 30) / fast_osc_frequency;
// from VL53L1_decode_vcsel_period()
uint8_t vcsel_period_pclks = (vcsel_period + 1) << 1;
// VL53L1_MACRO_PERIOD_VCSEL_PERIODS = 2304
uint32_t macro_period_us = (uint32_t)2304 * pll_period_us;
macro_period_us >>= 6;
macro_period_us *= vcsel_period_pclks;
macro_period_us >>= 6;
return macro_period_us;
}

1384
lib/vl53l1x-1.0.0/VL53L1X.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
/*
This example shows how to take simple range measurements with the VL53L1X. The
range readings are in units of mm.
*/
#include <Wire.h>
#include <VL53L1X.h>
VL53L1X sensor;
void setup()
{
Serial.begin(115200);
Wire.begin();
Wire.setClock(400000); // use 400 kHz I2C
sensor.setTimeout(500);
if (!sensor.init())
{
Serial.println("Failed to detect and initialize sensor!");
while (1);
}
// Use long distance mode and allow up to 50000 us (50 ms) for a measurement.
// You can change these settings to adjust the performance of the sensor, but
// the minimum timing budget is 20 ms for short distance mode and 33 ms for
// medium and long distance modes. See the VL53L1X datasheet for more
// information on range and timing limits.
sensor.setDistanceMode(VL53L1X::Long);
sensor.setMeasurementTimingBudget(50000);
// Start continuous readings at a rate of one measurement every 50 ms (the
// inter-measurement period). This period should be at least as long as the
// timing budget.
sensor.startContinuous(50);
}
void loop()
{
Serial.print(sensor.read());
if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }
Serial.println();
}

View File

@ -0,0 +1,55 @@
/*
This example takes range measurements with the VL53L1X and displays additional
details (status and signal/ambient rates) for each measurement, which can help
you determine whether the sensor is operating normally and the reported range is
valid. The range is in units of mm, and the rates are in units of MCPS (mega
counts per second).
*/
#include <Wire.h>
#include <VL53L1X.h>
VL53L1X sensor;
void setup()
{
Serial.begin(115200);
Wire.begin();
Wire.setClock(400000); // use 400 kHz I2C
sensor.setTimeout(500);
if (!sensor.init())
{
Serial.println("Failed to detect and initialize sensor!");
while (1);
}
// Use long distance mode and allow up to 50000 us (50 ms) for a measurement.
// You can change these settings to adjust the performance of the sensor, but
// the minimum timing budget is 20 ms for short distance mode and 33 ms for
// medium and long distance modes. See the VL53L1X datasheet for more
// information on range and timing limits.
sensor.setDistanceMode(VL53L1X::Long);
sensor.setMeasurementTimingBudget(50000);
// Start continuous readings at a rate of one measurement every 50 ms (the
// inter-measurement period). This period should be at least as long as the
// timing budget.
sensor.startContinuous(50);
}
void loop()
{
sensor.read();
Serial.print("range: ");
Serial.print(sensor.ranging_data.range_mm);
Serial.print("\tstatus: ");
Serial.print(VL53L1X::rangeStatusToString(sensor.ranging_data.range_status));
Serial.print("\tpeak signal: ");
Serial.print(sensor.ranging_data.peak_signal_count_rate_MCPS);
Serial.print("\tambient: ");
Serial.print(sensor.ranging_data.ambient_count_rate_MCPS);
Serial.println();
}

View File

@ -0,0 +1,41 @@
VL53L1X KEYWORD1
setAddress KEYWORD2
getAddress KEYWORD2
init KEYWORD2
writeReg KEYWORD2
writeReg16Bit KEYWORD2
writeReg32Bit KEYWORD2
readReg KEYWORD2
readReg16Bit KEYWORD2
readReg32Bit KEYWORD2
setDistanceMode KEYWORD2
getDistanceMode KEYWORD2
setMeasurementTimingBudget KEYWORD2
getMeasurementTimingBudget KEYWORD2
startContinuous KEYWORD2
stopContinuous KEYWORD2
read KEYWORD2
readRangeContinuousMillimeters KEYWORD2
rangeStatusToString KEYWORD2
setTimeout KEYWORD2
getTimeout KEYWORD2
timeoutOccurred KEYWORD2
Short LITERAL1
Medium LITERAL1
Long LITERAL1
Unknown LITERAL1
RangeValid LITERAL1
SigmaFail LITERAL1
SignalFail LITERAL1
RangeValidMinRangeClipped LITERAL1
OutOfBoundsFail LITERAL1
HardwareFail LITERAL1
RangeValidNoWrapCheckFail LITERAL1
WrapTargetFail LITERAL1
XtalkSignalFail LITERAL1
SyncronisationInt LITERAL1
MinRangeFail LITERAL1
None LITERAL1

View File

@ -0,0 +1,9 @@
name=VL53L1X
version=1.0.0
author=Pololu
maintainer=Pololu <inbox@pololu.com>
sentence=VL53L1X distance sensor library
paragraph=This is a library for the Arduino IDE that helps interface with ST's VL53L1X distance sensor.
category=Sensors
url=https://github.com/pololu/vl53l1x-arduino
architectures=*

View File

@ -531,6 +531,7 @@
// #define USE_SPS30 // [I2cDriver30] Enable Sensiron SPS30 particle sensor (I2C address 0x69) (+1.7 code)
#define USE_ADE7953 // [I2cDriver7] Enable ADE7953 Energy monitor as used on Shelly 2.5 (I2C address 0x38) (+1k5)
// #define USE_VL53L0X // [I2cDriver31] Enable VL53L0x time of flight sensor (I2C address 0x29) (+4k code)
// #define USE_VL53L1X // Enable support for VL53L1X sensor (I2C addres 0x52) using Pololu VL53L1X library (+2k9 code)
// #define USE_MLX90614 // [I2cDriver32] Enable MLX90614 ir temp sensor (I2C address 0x5a) (+0.6k code)
// #define USE_CHIRP // [I2cDriver33] Enable CHIRP soil moisture sensor (variable I2C address, default 0x20)
// #define USE_PAJ7620 // [I2cDriver34] Enable PAJ7620 gesture sensor (I2C address 0x73) (+2.5k code)

View File

@ -598,8 +598,9 @@ void GetFeatures(void)
#ifdef USE_DYP
feature6 |= 0x00400000; // xsns_76_dyp.ino
#endif
// feature6 |= 0x00800000;
#if defined(USE_I2C) && defined(USE_VL53L1X)
feature6 |= 0x00400000; // xsns_77_vl53l1x.ino
#endif
// feature6 |= 0x01000000;
// feature6 |= 0x02000000;
// feature6 |= 0x04000000;

128
tasmota/xsns_77_vl53l1x.ino Normal file
View File

@ -0,0 +1,128 @@
/*
xsns_77_vl53l1x.ino - VL53L1X
Copyright (C) 2018 Theo Arends and Rui Marinho
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_I2C
#ifdef USE_VL53L1X
/*********************************************************************************************\
* VL53L1X
*
* Source:
*
* I2C Address: 0x52
\*********************************************************************************************/
#define XSNS_77 77
#define XI2C_53 53 // See I2CDEVICES.md
#include <Wire.h>
#include "VL53L1X.h"
VL53L1X sensor;
uint8_t vl53l1x_ready = 0;
uint16_t vl53l1x_distance = 0;
/********************************************************************************************/
void Vl53l1Detect(void) {
if (!I2cSetDevice(0x52)) { return; }
if (!sensor.init()) { return; }
I2cSetActiveFound(sensor.getAddress(), "VL53L1X");
sensor.setTimeout(500);
sensor.setDistanceMode(VL53L1X::Long);
sensor.setMeasurementTimingBudget(140000);
sensor.startContinuous(50);
vl53l1x_ready = 1;
}
#ifdef USE_WEBSERVER
const char HTTP_SNS_VL53L1X[] PROGMEM =
"{s}VL53L1X " D_DISTANCE "{m}%d" D_UNIT_MILLIMETER "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
#endif // USE_WEBSERVER
void Vl53l1Every_250MSecond(void) {
// every 200 ms
uint16_t dist = sensor.read();
if ((0 == dist) || (dist > 4000)) {
dist = 9999;
}
vl53l1x_distance = dist;
}
#ifdef USE_DOMOTICZ
void Vl53l1Every_Second(void) {
DomoticzSensor(DZ_ILLUMINANCE, vl53l1x_distance);
}
#endif // USE_DOMOTICZ
void Vl53l1Show(boolean json) {
if (json) {
ResponseAppend_P(PSTR(",\"VL53L1X\":{\"" D_JSON_DISTANCE "\":%d}"), vl53l1x_distance);
#ifdef USE_DOMOTICZ
if (0 == tele_period) {
DomoticzSensor(DZ_ILLUMINANCE, vl53l1x_distance);
}
#endif // USE_DOMOTICZ
#ifdef USE_WEBSERVER
} else {
WSContentSend_PD(HTTP_SNS_VL53L1X, vl53l1x_distance);
#endif
}
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xsns77(byte function)
{
if (!I2cEnabled(XI2C_53)) { return false; }
bool result = false;
if (FUNC_INIT == function) {
Vl53l1Detect();
}
else if (vl53l1x_ready) {
switch (function) {
case FUNC_EVERY_250_MSECOND:
Vl53l1Every_250MSecond();
break;
#ifdef USE_DOMOTICZ
case FUNC_EVERY_SECOND:
Vl53l1Every_Second();
break;
#endif // USE_DOMOTICZ
case FUNC_JSON_APPEND:
Vl53l1Show(1);
break;
#ifdef USE_WEBSERVER
case FUNC_WEB_SENSOR:
Vl53l1Show(0);
break;
#endif // USE_WEBSERVER
}
}
return result;
}
#endif // USE_VL53L1X
#endif // USE_I2C