├── LICENSE.md ├── README.md ├── keywords.txt ├── library.properties └── src ├── ComponentObject.h ├── RangeSensor.h ├── vl53l1x_class.cpp ├── vl53l1x_class.h └── vl53l1x_error_codes.h /LICENSE.md: -------------------------------------------------------------------------------- 1 | COPYRIGHT(c) 2018 STMicroelectronics 2 | 3 | Redistribution and use in source and binary forms, with or without modification, 4 | are permitted provided that the following conditions are met: 5 | 1. Redistributions of source code must retain the above copyright notice, 6 | this list of conditions and the following disclaimer. 7 | 2. Redistributions in binary form must reproduce the above copyright notice, 8 | this list of conditions and the following disclaimer in the documentation 9 | and/or other materials provided with the distribution. 10 | 3. Neither the name of STMicroelectronics nor the names of its contributors 11 | may be used to endorse or promote products derived from this software 12 | without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VL53L1X 2 | Arduino library to support the VL53L1X Time-of-Flight and gesture-detection sensor 3 | 4 | ## API 5 | 6 | This sensor uses I2C to communicate. And I2C instance is required to access to the sensor. 7 | 8 | The API provides simple distance measure, single swipe gesture detection, 9 | directional (left/right) swipe gesture detection and single tap gesture detection. 10 | 11 | 12 | ## Note 13 | 14 | The maximum detection distance is influenced by the color of the target and 15 | the indoor or outdoor situation due to absence or presence of external 16 | infrared. 17 | The detection range can be comprise between ~40cm and ~400cm. (see chapter 5 of 18 | the VL53L1X datasheet). 19 | The library should work also with standard Arduino boards. In this case you just 20 | need to adjust the code in the sketch in order to use the correct Wire instance and 21 | the correct pin number for XSHUT and GPIO1 pins. 22 | 23 | ## Documentation 24 | 25 | You can find the source files at 26 | https://github.com/stm32duino/VL53L1X 27 | 28 | The VL53L1X datasheet is available at 29 | https://www.st.com/content/st_com/en/products/imaging-and-photonics-solutions/proximity-sensors/vl53l1x.html 30 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For VL53L1X 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | ComponentObject KEYWORD1 10 | RangeSensor KEYWORD1 11 | VL53L1X KEYWORD1 12 | 13 | ####################################### 14 | # Methods and Functions (KEYWORD2) 15 | ####################################### 16 | 17 | begin KEYWORD2 18 | end KEYWORD2 19 | VL53L1X_On KEYWORD2 20 | VL53L1X_Off KEYWORD2 21 | InitSensor KEYWORD2 22 | Init KEYWORD2 23 | ReadID KEYWORD2 24 | GetDistance KEYWORD2 25 | VL53L1X_GetSWVersion KEYWORD2 26 | VL53L1X_SetI2CAddress KEYWORD2 27 | VL53L1X_SensorInit KEYWORD2 28 | VL53L1X_ClearInterrupt KEYWORD2 29 | VL53L1X_SetInterruptPolarity KEYWORD2 30 | VL53L1X_GetInterruptPolarity KEYWORD2 31 | VL53L1X_StartRanging KEYWORD2 32 | VL53L1X_StopRanging KEYWORD2 33 | VL53L1X_CheckForDataReady KEYWORD2 34 | VL53L1X_SetTimingBudgetInMs KEYWORD2 35 | VL53L1X_GetTimingBudgetInMs KEYWORD2 36 | VL53L1X_SetDistanceMode KEYWORD2 37 | VL53L1X_GetDistanceMode KEYWORD2 38 | VL53L1X_SetInterMeasurementInMs KEYWORD2 39 | VL53L1X_GetInterMeasurementInMs KEYWORD2 40 | VL53L1X_BootState KEYWORD2 41 | VL53L1X_GetSensorId KEYWORD2 42 | VL53L1X_GetDistance KEYWORD2 43 | VL53L1X_GetSignalPerSpad KEYWORD2 44 | VL53L1X_GetAmbientPerSpad KEYWORD2 45 | VL53L1X_GetSignalRate KEYWORD2 46 | VL53L1X_GetSpadNb KEYWORD2 47 | VL53L1X_GetAmbientRate KEYWORD2 48 | VL53L1X_GetRangeStatus KEYWORD2 49 | VL53L1X_SetOffset KEYWORD2 50 | VL53L1X_GetOffset KEYWORD2 51 | VL53L1X_SetXtalk KEYWORD2 52 | VL53L1X_GetXtalk KEYWORD2 53 | VL53L1X_SetDistanceThreshold KEYWORD2 54 | VL53L1X_GetDistanceThresholdWindow KEYWORD2 55 | VL53L1X_GetDistanceThresholdLow KEYWORD2 56 | VL53L1X_GetDistanceThresholdHigh KEYWORD2 57 | VL53L1X_SetROI KEYWORD2 58 | VL53L1X_GetROI_XY KEYWORD2 59 | VL53L1X_SetROICenter KEYWORD2 60 | VL53L1X_GetROICenter KEYWORD2 61 | VL53L1X_SetSignalThreshold KEYWORD2 62 | VL53L1X_GetSignalThreshold KEYWORD2 63 | VL53L1X_SetSigmaThreshold KEYWORD2 64 | VL53L1X_GetSigmaThreshold KEYWORD2 65 | VL53L1X_StartTemperatureUpdate KEYWORD2 66 | VL53L1X_CalibrateOffset KEYWORD2 67 | VL53L1X_CalibrateXtalk KEYWORD2 68 | 69 | ####################################### 70 | # Constants (LITERAL1) 71 | ####################################### 72 | 73 | VL53L1X_IMPLEMENTATION_VER_MAJOR LITERAL1 74 | VL53L1X_IMPLEMENTATION_VER_MINOR LITERAL1 75 | VL53L1X_IMPLEMENTATION_VER_SUB LITERAL1 76 | VL53L1X_IMPLEMENTATION_VER_REVISION LITERAL1 77 | SOFT_RESET LITERAL1 78 | VL53L1X_I2C_SLAVE__DEVICE_ADDRESS LITERAL1 79 | VL53L1X_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND LITERAL1 80 | ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS LITERAL1 81 | ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS LITERAL1 82 | ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS LITERAL1 83 | ALGO__PART_TO_PART_RANGE_OFFSET_MM LITERAL1 84 | MM_CONFIG__INNER_OFFSET_MM LITERAL1 85 | MM_CONFIG__OUTER_OFFSET_MM LITERAL1 86 | GPIO_HV_MUX__CTRL LITERAL1 87 | GPIO__TIO_HV_STATUS LITERAL1 88 | SYSTEM__INTERRUPT_CONFIG_GPIO LITERAL1 89 | PHASECAL_CONFIG__TIMEOUT_MACROP LITERAL1 90 | RANGE_CONFIG__TIMEOUT_MACROP_A_HI LITERAL1 91 | RANGE_CONFIG__VCSEL_PERIOD_A LITERAL1 92 | RANGE_CONFIG__VCSEL_PERIOD_B LITERAL1 93 | RANGE_CONFIG__TIMEOUT_MACROP_B_HI LITERAL1 94 | RANGE_CONFIG__TIMEOUT_MACROP_B_LO LITERAL1 95 | RANGE_CONFIG__SIGMA_THRESH LITERAL1 96 | RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS LITERAL1 97 | RANGE_CONFIG__VALID_PHASE_HIGH LITERAL1 98 | VL53L1X_SYSTEM__INTERMEASUREMENT_PERIOD LITERAL1 99 | SYSTEM__THRESH_HIGH LITERAL1 100 | SYSTEM__THRESH_LOW LITERAL1 101 | SD_CONFIG__WOI_SD0 LITERAL1 102 | SD_CONFIG__INITIAL_PHASE_SD0 LITERAL1 103 | ROI_CONFIG__USER_ROI_CENTRE_SPAD LITERAL1 104 | ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE LITERAL1 105 | SYSTEM__SEQUENCE_CONFIG LITERAL1 106 | VL53L1X_SYSTEM__GROUPED_PARAMETER_HOLD LITERAL1 107 | SYSTEM__INTERRUPT_CLEAR LITERAL1 108 | SYSTEM__MODE_START LITERAL1 109 | VL53L1X_RESULT__RANGE_STATUS LITERAL1 110 | VL53L1X_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0 LITERAL1 111 | RESULT__AMBIENT_COUNT_RATE_MCPS_SD LITERAL1 112 | VL53L1X_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 LITERAL1 113 | VL53L1X_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0 LITERAL1 114 | VL53L1X_RESULT__OSC_CALIBRATE_VAL LITERAL1 115 | VL53L1X_FIRMWARE__SYSTEM_STATUS LITERAL1 116 | VL53L1X_IDENTIFICATION__MODEL_ID LITERAL1 117 | VL53L1X_ROI_CONFIG__MODE_ROI_CENTRE_SPAD LITERAL1 118 | VL53L1X_DEFAULT_DEVICE_ADDRESS LITERAL1 119 | ALGO__PART_TO_PART_RANGE_OFFSET_MM LITERAL1 120 | MM_CONFIG__INNER_OFFSET_MM LITERAL1 121 | MM_CONFIG__OUTER_OFFSET_MM LITERAL1 122 | VL53L1X_ERROR_NONE LITERAL1 123 | VL53L1X_ERROR_CALIBRATION_WARNING LITERAL1 124 | VL53L1X_ERROR_MIN_CLIPPED LITERAL1 125 | VL53L1X_ERROR_UNDEFINED LITERAL1 126 | VL53L1X_ERROR_INVALID_PARAMS LITERAL1 127 | VL53L1X_ERROR_NOT_SUPPORTED LITERAL1 128 | VL53L1X_ERROR_RANGE_ERROR LITERAL1 129 | VL53L1X_ERROR_TIME_OUT LITERAL1 130 | VL53L1X_ERROR_MODE_NOT_SUPPORTED LITERAL1 131 | VL53L1X_ERROR_BUFFER_TOO_SMALL LITERAL1 132 | VL53L1X_ERROR_COMMS_BUFFER_TOO_SMALL LITERAL1 133 | VL53L1X_ERROR_GPIO_NOT_EXISTING LITERAL1 134 | VL53L1X_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED LITERAL1 135 | VL53L1X_ERROR_CONTROL_INTERFACE LITERAL1 136 | VL53L1X_ERROR_INVALID_COMMAND LITERAL1 137 | VL53L1X_ERROR_DIVISION_BY_ZERO LITERAL1 138 | VL53L1X_ERROR_REF_SPAD_INIT LITERAL1 139 | VL53L1X_ERROR_GPH_SYNC_CHECK_FAIL LITERAL1 140 | VL53L1X_ERROR_STREAM_COUNT_CHECK_FAIL LITERAL1 141 | VL53L1X_ERROR_GPH_ID_CHECK_FAIL LITERAL1 142 | VL53L1X_ERROR_ZONE_STREAM_COUNT_CHECK_FAIL LITERAL1 143 | VL53L1X_ERROR_ZONE_GPH_ID_CHECK_FAIL LITERAL1 144 | VL53L1X_ERROR_XTALK_EXTRACTION_NO_SAMPLE_FAIL LITERAL1 145 | VL53L1X_ERROR_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL LITERAL1 146 | VL53L1X_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL LITERAL1 147 | VL53L1X_ERROR_OFFSET_CAL_NO_SPADS_ENABLED_FAIL LITERAL1 148 | VL53L1X_ERROR_ZONE_CAL_NO_SAMPLE_FAIL LITERAL1 149 | VL53L1X_ERROR_TUNING_PARM_KEY_MISMATCH LITERAL1 150 | VL53L1X_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS LITERAL1 151 | VL53L1X_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH LITERAL1 152 | VL53L1X_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW LITERAL1 153 | VL53L1X_WARNING_OFFSET_CAL_MISSING_SAMPLES LITERAL1 154 | VL53L1X_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH LITERAL1 155 | VL53L1X_WARNING_OFFSET_CAL_RATE_TOO_HIGH LITERAL1 156 | VL53L1X_WARNING_OFFSET_CAL_SPAD_COUNT_TOO_LOW LITERAL1 157 | VL53L1X_WARNING_ZONE_CAL_MISSING_SAMPLES LITERAL1 158 | VL53L1X_WARNING_ZONE_CAL_SIGMA_TOO_HIGH LITERAL1 159 | VL53L1X_WARNING_ZONE_CAL_RATE_TOO_HIGH LITERAL1 160 | VL53L1X_WARNING_XTALK_MISSING_SAMPLES LITERAL1 161 | VL53L1X_WARNING_XTALK_NO_SAMPLES_FOR_GRADIENT LITERAL1 162 | VL53L1X_WARNING_XTALK_SIGMA_LIMIT_FOR_GRADIENT LITERAL1 163 | VL53L1X_ERROR_NOT_IMPLEMENTED LITERAL1 164 | VL53L1X_ERROR_PLATFORM_SPECIFIC_START LITERAL1 165 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=STM32duino VL53L1X 2 | version=2.0.1 3 | author=AST 4 | maintainer=stm32duino 5 | sentence=Allows controlling the VL53L1X (Time-of-Flight and gesture detection sensor) 6 | paragraph=This library provides simple measure distance in mm, single swipe gesture detection, directional (left/right) swipe gesture detection and single tap gesture detection. 7 | category=Device Control 8 | url=https://github.com/stm32duino/VL53L1X 9 | architectures=stm32, avr, sam 10 | -------------------------------------------------------------------------------- /src/ComponentObject.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file ComponentObject.h 4 | * @author AST 5 | * @version V1.0.0 6 | * @date April 13th, 2015 7 | * @brief This file contains the abstract class describing the interface of a 8 | * generic component. 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

© COPYRIGHT(c) 2015 STMicroelectronics

13 | * 14 | * Redistribution and use in source and binary forms, with or without modification, 15 | * are permitted provided that the following conditions are met: 16 | * 1. Redistributions of source code must retain the above copyright notice, 17 | * this list of conditions and the following disclaimer. 18 | * 2. Redistributions in binary form must reproduce the above copyright notice, 19 | * this list of conditions and the following disclaimer in the documentation 20 | * and/or other materials provided with the distribution. 21 | * 3. Neither the name of STMicroelectronics nor the names of its contributors 22 | * may be used to endorse or promote products derived from this software 23 | * without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 28 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | ****************************************************************************** 37 | */ 38 | 39 | 40 | /* Define to prevent recursive inclusion -------------------------------------*/ 41 | 42 | #ifndef __COMPONENT_OBJECT_CLASS_H 43 | #define __COMPONENT_OBJECT_CLASS_H 44 | 45 | 46 | /* Includes ------------------------------------------------------------------*/ 47 | 48 | #include 49 | 50 | 51 | /* Classes ------------------------------------------------------------------*/ 52 | 53 | /** An abstract class for Generic components. 54 | */ 55 | class ComponentObject 56 | { 57 | public: 58 | /** 59 | * @brief Initializing the component. 60 | * @param[in] init pointer to device specific initalization structure. 61 | * @retval "0" in case of success, an error code otherwise. 62 | */ 63 | virtual int Init() = 0; 64 | 65 | /** 66 | * @brief Getting the ID of the component. 67 | * @param[out] id pointer to an allocated variable to store the ID into. 68 | * @retval "0" in case of success, an error code otherwise. 69 | */ 70 | virtual int ReadID() = 0; 71 | }; 72 | 73 | #endif /* __COMPONENT_OBJECT_CLASS_H */ 74 | 75 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 76 | -------------------------------------------------------------------------------- /src/RangeSensor.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file RangeSensor.h 4 | * @author AST / EST 5 | * @version V0.0.1 6 | * @date 13-April-2015 7 | * @brief This file contains the abstract class describing in general 8 | * the interfaces of a range sensor 9 | ****************************************************************************** 10 | * @attention 11 | * 12 | *

© COPYRIGHT(c) 2015 STMicroelectronics

13 | * 14 | * Redistribution and use in source and binary forms, with or without modification, 15 | * are permitted provided that the following conditions are met: 16 | * 1. Redistributions of source code must retain the above copyright notice, 17 | * this list of conditions and the following disclaimer. 18 | * 2. Redistributions in binary form must reproduce the above copyright notice, 19 | * this list of conditions and the following disclaimer in the documentation 20 | * and/or other materials provided with the distribution. 21 | * 3. Neither the name of STMicroelectronics nor the names of its contributors 22 | * may be used to endorse or promote products derived from this software 23 | * without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 28 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | ****************************************************************************** 37 | */ 38 | 39 | /* Define to prevent from recursive inclusion --------------------------------*/ 40 | #ifndef __RANGE_SENSOR_CLASS_H 41 | #define __RANGE_SENSOR_CLASS_H 42 | 43 | /* Includes ------------------------------------------------------------------*/ 44 | #include 45 | 46 | /* Classes ------------------------------------------------------------------*/ 47 | /** An abstract class for range sensors 48 | */ 49 | class RangeSensor : public ComponentObject 50 | { 51 | public: 52 | /** 53 | * @brief Get current range [mm] 54 | * @param[out] piData Pointer to where to store range to 55 | * @return 0 in case of success, an error code otherwise 56 | */ 57 | virtual int GetDistance(uint32_t *piData) = 0; 58 | }; 59 | 60 | #endif /* __RANGE_SENSOR_CLASS_H */ 61 | -------------------------------------------------------------------------------- /src/vl53l1x_class.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file vl53l0x_class.cpp 4 | * @author IMG 5 | * @version V0.0.1 6 | * @date 14-December-2018 7 | * @brief Implementation file for the VL53L1X driver class 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | *

© COPYRIGHT(c) 2018 STMicroelectronics

12 | * 13 | * Redistribution and use in source and binary forms, with or without modification, 14 | * are permitted provided that the following conditions are met: 15 | * 1. Redistributions of source code must retain the above copyright notice, 16 | * this list of conditions and the following disclaimer. 17 | * 2. Redistributions in binary form must reproduce the above copyright notice, 18 | * this list of conditions and the following disclaimer in the documentation 19 | * and/or other materials provided with the distribution. 20 | * 3. Neither the name of STMicroelectronics nor the names of its contributors 21 | * may be used to endorse or promote products derived from this software 22 | * without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | * 35 | ****************************************************************************** 36 | */ 37 | 38 | /* Includes */ 39 | #include 40 | #include "Arduino.h" 41 | #include "vl53l1x_class.h" 42 | 43 | 44 | #define ALGO__PART_TO_PART_RANGE_OFFSET_MM 0x001E 45 | #define MM_CONFIG__INNER_OFFSET_MM 0x0020 46 | #define MM_CONFIG__OUTER_OFFSET_MM 0x0022 47 | 48 | 49 | //#define DEBUG_MODE 50 | 51 | 52 | const uint8_t VL51L1X_DEFAULT_CONFIGURATION[] = 53 | { 54 | 0x00, /* 0x2d : set bit 2 and 5 to 1 for fast plus mode (1MHz I2C), else don't touch */ 55 | 0x00, /* 0x2e : bit 0 if I2C pulled up at 1.8V, else set bit 0 to 1 (pull up at AVDD) */ 56 | 0x00, /* 0x2f : bit 0 if GPIO pulled up at 1.8V, else set bit 0 to 1 (pull up at AVDD) */ 57 | 0x01, /* 0x30 : set bit 4 to 0 for active high interrupt and 1 for active low (bits 3:0 must be 0x1), use SetInterruptPolarity() */ 58 | 0x02, /* 0x31 : bit 1 = interrupt depending on the polarity, use CheckForDataReady() */ 59 | 0x00, /* 0x32 : not user-modifiable */ 60 | 0x02, /* 0x33 : not user-modifiable */ 61 | 0x08, /* 0x34 : not user-modifiable */ 62 | 0x00, /* 0x35 : not user-modifiable */ 63 | 0x08, /* 0x36 : not user-modifiable */ 64 | 0x10, /* 0x37 : not user-modifiable */ 65 | 0x01, /* 0x38 : not user-modifiable */ 66 | 0x01, /* 0x39 : not user-modifiable */ 67 | 0x00, /* 0x3a : not user-modifiable */ 68 | 0x00, /* 0x3b : not user-modifiable */ 69 | 0x00, /* 0x3c : not user-modifiable */ 70 | 0x00, /* 0x3d : not user-modifiable */ 71 | 0xff, /* 0x3e : not user-modifiable */ 72 | 0x00, /* 0x3f : not user-modifiable */ 73 | 0x0F, /* 0x40 : not user-modifiable */ 74 | 0x00, /* 0x41 : not user-modifiable */ 75 | 0x00, /* 0x42 : not user-modifiable */ 76 | 0x00, /* 0x43 : not user-modifiable */ 77 | 0x00, /* 0x44 : not user-modifiable */ 78 | 0x00, /* 0x45 : not user-modifiable */ 79 | 0x20, /* 0x46 : interrupt configuration 0->level low detection, 1-> level high, 2-> Out of window, 3->In window, 0x20-> New sample ready , TBC */ 80 | 0x0b, /* 0x47 : not user-modifiable */ 81 | 0x00, /* 0x48 : not user-modifiable */ 82 | 0x00, /* 0x49 : not user-modifiable */ 83 | 0x02, /* 0x4a : not user-modifiable */ 84 | 0x0a, /* 0x4b : not user-modifiable */ 85 | 0x21, /* 0x4c : not user-modifiable */ 86 | 0x00, /* 0x4d : not user-modifiable */ 87 | 0x00, /* 0x4e : not user-modifiable */ 88 | 0x05, /* 0x4f : not user-modifiable */ 89 | 0x00, /* 0x50 : not user-modifiable */ 90 | 0x00, /* 0x51 : not user-modifiable */ 91 | 0x00, /* 0x52 : not user-modifiable */ 92 | 0x00, /* 0x53 : not user-modifiable */ 93 | 0xc8, /* 0x54 : not user-modifiable */ 94 | 0x00, /* 0x55 : not user-modifiable */ 95 | 0x00, /* 0x56 : not user-modifiable */ 96 | 0x38, /* 0x57 : not user-modifiable */ 97 | 0xff, /* 0x58 : not user-modifiable */ 98 | 0x01, /* 0x59 : not user-modifiable */ 99 | 0x00, /* 0x5a : not user-modifiable */ 100 | 0x08, /* 0x5b : not user-modifiable */ 101 | 0x00, /* 0x5c : not user-modifiable */ 102 | 0x00, /* 0x5d : not user-modifiable */ 103 | 0x01, /* 0x5e : not user-modifiable */ 104 | 0xcc, /* 0x5f : not user-modifiable */ 105 | 0x0f, /* 0x60 : not user-modifiable */ 106 | 0x01, /* 0x61 : not user-modifiable */ 107 | 0xf1, /* 0x62 : not user-modifiable */ 108 | 0x0d, /* 0x63 : not user-modifiable */ 109 | 0x01, /* 0x64 : Sigma threshold MSB (mm in 14.2 format for MSB+LSB), use SetSigmaThreshold(), default value 90 mm */ 110 | 0x68, /* 0x65 : Sigma threshold LSB */ 111 | 0x00, /* 0x66 : Min count Rate MSB (MCPS in 9.7 format for MSB+LSB), use SetSignalThreshold() */ 112 | 0x80, /* 0x67 : Min count Rate LSB */ 113 | 0x08, /* 0x68 : not user-modifiable */ 114 | 0xb8, /* 0x69 : not user-modifiable */ 115 | 0x00, /* 0x6a : not user-modifiable */ 116 | 0x00, /* 0x6b : not user-modifiable */ 117 | 0x00, /* 0x6c : Intermeasurement period MSB, 32 bits register, use SetIntermeasurementInMs() */ 118 | 0x00, /* 0x6d : Intermeasurement period */ 119 | 0x0f, /* 0x6e : Intermeasurement period */ 120 | 0x89, /* 0x6f : Intermeasurement period LSB */ 121 | 0x00, /* 0x70 : not user-modifiable */ 122 | 0x00, /* 0x71 : not user-modifiable */ 123 | 0x00, /* 0x72 : distance threshold high MSB (in mm, MSB+LSB), use SetD:tanceThreshold() */ 124 | 0x00, /* 0x73 : distance threshold high LSB */ 125 | 0x00, /* 0x74 : distance threshold low MSB ( in mm, MSB+LSB), use SetD:tanceThreshold() */ 126 | 0x00, /* 0x75 : distance threshold low LSB */ 127 | 0x00, /* 0x76 : not user-modifiable */ 128 | 0x01, /* 0x77 : not user-modifiable */ 129 | 0x0f, /* 0x78 : not user-modifiable */ 130 | 0x0d, /* 0x79 : not user-modifiable */ 131 | 0x0e, /* 0x7a : not user-modifiable */ 132 | 0x0e, /* 0x7b : not user-modifiable */ 133 | 0x00, /* 0x7c : not user-modifiable */ 134 | 0x00, /* 0x7d : not user-modifiable */ 135 | 0x02, /* 0x7e : not user-modifiable */ 136 | 0xc7, /* 0x7f : ROI center, use SetROI() */ 137 | 0xff, /* 0x80 : XY ROI (X=Width, Y=Height), use SetROI() */ 138 | 0x9B, /* 0x81 : not user-modifiable */ 139 | 0x00, /* 0x82 : not user-modifiable */ 140 | 0x00, /* 0x83 : not user-modifiable */ 141 | 0x00, /* 0x84 : not user-modifiable */ 142 | 0x01, /* 0x85 : not user-modifiable */ 143 | 0x00, /* 0x86 : clear interrupt, use ClearInterrupt() */ 144 | 0x00 /* 0x87 : start ranging, use StartRanging() or StopRanging(), If you want an automatic start after VL53L1X_init() call, put 0x40 in location 0x87 */ 145 | }; 146 | 147 | 148 | 149 | /* VL53L1X_api.h functions */ 150 | 151 | 152 | VL53L1X_ERROR VL53L1X::VL53L1X_GetSWVersion(VL53L1X_Version_t *pVersion) 153 | { 154 | VL53L1X_ERROR Status = 0; 155 | 156 | pVersion->major = VL53L1X_IMPLEMENTATION_VER_MAJOR; 157 | pVersion->minor = VL53L1X_IMPLEMENTATION_VER_MINOR; 158 | pVersion->build = VL53L1X_IMPLEMENTATION_VER_SUB; 159 | pVersion->revision = VL53L1X_IMPLEMENTATION_VER_REVISION; 160 | return Status; 161 | } 162 | 163 | VL53L1X_ERROR VL53L1X::VL53L1X_SetI2CAddress(uint8_t new_address) 164 | { 165 | VL53L1X_ERROR status = 0; 166 | 167 | status = VL53L1X_WrByte(Device, VL53L1X_I2C_SLAVE__DEVICE_ADDRESS, new_address >> 1); 168 | Device->I2cDevAddr = new_address; 169 | 170 | 171 | return status; 172 | } 173 | 174 | VL53L1X_ERROR VL53L1X::VL53L1X_SensorInit() 175 | { 176 | VL53L1X_ERROR status = 0; 177 | uint8_t Addr = 0x00, tmp=0; 178 | 179 | for (Addr = 0x2D; Addr <= 0x87; Addr++) 180 | { 181 | status = VL53L1X_WrByte(Device, Addr, VL51L1X_DEFAULT_CONFIGURATION[Addr - 0x2D]); 182 | } 183 | status = VL53L1X_StartRanging(); 184 | while(tmp==0) 185 | { 186 | status = VL53L1X_CheckForDataReady(&tmp); 187 | } 188 | tmp = 0; 189 | status = VL53L1X_ClearInterrupt(); 190 | status = VL53L1X_StopRanging(); 191 | status = VL53L1X_WrByte(Device, VL53L1X_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND, 0x09); /* two bounds VHV */ 192 | status = VL53L1X_WrByte(Device, 0x0B, 0); /* start VHV from the previous temperature */ 193 | return status; 194 | } 195 | 196 | 197 | VL53L1X_ERROR VL53L1X::VL53L1X_ClearInterrupt() 198 | { 199 | VL53L1X_ERROR status = 0; 200 | 201 | status = VL53L1X_WrByte(Device, SYSTEM__INTERRUPT_CLEAR, 0x01); 202 | return status; 203 | } 204 | 205 | 206 | VL53L1X_ERROR VL53L1X::VL53L1X_SetInterruptPolarity(uint8_t NewPolarity) 207 | { 208 | uint8_t Temp; 209 | VL53L1X_ERROR status = 0; 210 | 211 | status = VL53L1X_RdByte(Device, GPIO_HV_MUX__CTRL, &Temp); 212 | Temp = Temp & 0xEF; 213 | status = VL53L1X_WrByte(Device, GPIO_HV_MUX__CTRL, Temp | (!(NewPolarity & 1)) << 4); 214 | return status; 215 | } 216 | 217 | 218 | 219 | VL53L1X_ERROR VL53L1X::VL53L1X_GetInterruptPolarity(uint8_t *pInterruptPolarity) 220 | { 221 | uint8_t Temp; 222 | VL53L1X_ERROR status = 0; 223 | 224 | status = VL53L1X_RdByte(Device, GPIO_HV_MUX__CTRL, &Temp); 225 | Temp = Temp & 0x10; 226 | *pInterruptPolarity = !(Temp>>4); 227 | return status; 228 | } 229 | 230 | 231 | 232 | VL53L1X_ERROR VL53L1X::VL53L1X_StartRanging() 233 | { 234 | VL53L1X_ERROR status = 0; 235 | 236 | status = VL53L1X_WrByte(Device, SYSTEM__MODE_START, 0x40); /* Enable VL53L1X */ 237 | return status; 238 | } 239 | 240 | VL53L1X_ERROR VL53L1X::VL53L1X_StopRanging() 241 | { 242 | VL53L1X_ERROR status = 0; 243 | 244 | status = VL53L1X_WrByte(Device, SYSTEM__MODE_START, 0x00); /* Disable VL53L1X */ 245 | return status; 246 | } 247 | 248 | 249 | 250 | VL53L1X_ERROR VL53L1X::VL53L1X_CheckForDataReady(uint8_t *isDataReady) 251 | { 252 | uint8_t Temp; 253 | uint8_t IntPol; 254 | VL53L1X_ERROR status = 0; 255 | 256 | status = VL53L1X_GetInterruptPolarity(&IntPol); 257 | status = VL53L1X_RdByte(Device, GPIO__TIO_HV_STATUS, &Temp); 258 | /* Read in the register to check if a new value is available */ 259 | if (status == 0) 260 | { 261 | if ((Temp & 1) == IntPol) 262 | *isDataReady = 1; 263 | else 264 | *isDataReady = 0; 265 | } 266 | return status; 267 | } 268 | 269 | 270 | VL53L1X_ERROR VL53L1X::VL53L1X_SetTimingBudgetInMs(uint16_t TimingBudgetInMs) 271 | { 272 | uint16_t DM; 273 | VL53L1X_ERROR status=0; 274 | 275 | status = VL53L1X_GetDistanceMode(&DM); 276 | if (DM == 0) 277 | return 1; 278 | else if (DM == 1) /* Short DistanceMode */ 279 | { 280 | switch (TimingBudgetInMs) 281 | { 282 | case 15: /* only available in short distance mode */ 283 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 284 | 0x01D); 285 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 286 | 0x0027); 287 | break; 288 | case 20: 289 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 290 | 0x0051); 291 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 292 | 0x006E); 293 | break; 294 | case 33: 295 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 296 | 0x00D6); 297 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 298 | 0x006E); 299 | break; 300 | case 50: 301 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 302 | 0x1AE); 303 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 304 | 0x01E8); 305 | break; 306 | case 100: 307 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 308 | 0x02E1); 309 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 310 | 0x0388); 311 | break; 312 | case 200: 313 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 314 | 0x03E1); 315 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 316 | 0x0496); 317 | break; 318 | case 500: 319 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 320 | 0x0591); 321 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 322 | 0x05C1); 323 | break; 324 | default: 325 | status = 1; 326 | break; 327 | } 328 | } 329 | else 330 | { 331 | switch (TimingBudgetInMs) 332 | { 333 | case 20: 334 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 335 | 0x001E); 336 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 337 | 0x0022); 338 | break; 339 | case 33: 340 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 341 | 0x0060); 342 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 343 | 0x006E); 344 | break; 345 | case 50: 346 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 347 | 0x00AD); 348 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 349 | 0x00C6); 350 | break; 351 | case 100: 352 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 353 | 0x01CC); 354 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 355 | 0x01EA); 356 | break; 357 | case 200: 358 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 359 | 0x02D9); 360 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 361 | 0x02F8); 362 | break; 363 | case 500: 364 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 365 | 0x048F); 366 | VL53L1X_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 367 | 0x04A4); 368 | break; 369 | default: 370 | status = 1; 371 | break; 372 | } 373 | } 374 | return status; 375 | } 376 | 377 | VL53L1X_ERROR VL53L1X::VL53L1X_GetTimingBudgetInMs(uint16_t *pTimingBudget) 378 | { 379 | uint16_t Temp; 380 | VL53L1X_ERROR status = 0; 381 | 382 | status = VL53L1X_RdWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, &Temp); 383 | switch (Temp) 384 | { 385 | case 0x001D : 386 | *pTimingBudget = 15; 387 | break; 388 | case 0x0051 : 389 | case 0x001E : 390 | *pTimingBudget = 20; 391 | break; 392 | case 0x00D6 : 393 | case 0x0060 : 394 | *pTimingBudget = 33; 395 | break; 396 | case 0x1AE : 397 | case 0x00AD : 398 | *pTimingBudget = 50; 399 | break; 400 | case 0x02E1 : 401 | case 0x01CC : 402 | *pTimingBudget = 100; 403 | break; 404 | case 0x03E1 : 405 | case 0x02D9 : 406 | *pTimingBudget = 200; 407 | break; 408 | case 0x0591 : 409 | case 0x048F : 410 | *pTimingBudget = 500; 411 | break; 412 | default: 413 | *pTimingBudget = 0; 414 | break; 415 | } 416 | return status; 417 | } 418 | 419 | 420 | VL53L1X_ERROR VL53L1X::VL53L1X_SetDistanceMode(uint16_t DM) 421 | { 422 | uint16_t TB; 423 | VL53L1X_ERROR status = 0; 424 | 425 | status = VL53L1X_GetTimingBudgetInMs(&TB); 426 | 427 | 428 | switch (DM) 429 | { 430 | case 1: 431 | status = VL53L1X_WrByte(Device, PHASECAL_CONFIG__TIMEOUT_MACROP, 0x14); 432 | status = VL53L1X_WrByte(Device, RANGE_CONFIG__VCSEL_PERIOD_A, 0x07); 433 | status = VL53L1X_WrByte(Device, RANGE_CONFIG__VCSEL_PERIOD_B, 0x05); 434 | status = VL53L1X_WrByte(Device, RANGE_CONFIG__VALID_PHASE_HIGH, 0x38); 435 | status = VL53L1X_WrWord(Device, SD_CONFIG__WOI_SD0, 0x0705); 436 | status = VL53L1X_WrWord(Device, SD_CONFIG__INITIAL_PHASE_SD0, 0x0606); 437 | break; 438 | case 2: 439 | status = VL53L1X_WrByte(Device, PHASECAL_CONFIG__TIMEOUT_MACROP, 0x0A); 440 | status = VL53L1X_WrByte(Device, RANGE_CONFIG__VCSEL_PERIOD_A, 0x0F); 441 | status = VL53L1X_WrByte(Device, RANGE_CONFIG__VCSEL_PERIOD_B, 0x0D); 442 | status = VL53L1X_WrByte(Device, RANGE_CONFIG__VALID_PHASE_HIGH, 0xB8); 443 | status = VL53L1X_WrWord(Device, SD_CONFIG__WOI_SD0, 0x0F0D); 444 | status = VL53L1X_WrWord(Device, SD_CONFIG__INITIAL_PHASE_SD0, 0x0E0E); 445 | break; 446 | default: 447 | break; 448 | } 449 | status = VL53L1X_SetTimingBudgetInMs(TB); 450 | return status; 451 | } 452 | 453 | 454 | 455 | 456 | VL53L1X_ERROR VL53L1X::VL53L1X_GetDistanceMode(uint16_t *DM) 457 | { 458 | uint8_t TempDM, status=0; 459 | 460 | status = VL53L1X_RdByte(Device,PHASECAL_CONFIG__TIMEOUT_MACROP, &TempDM); 461 | if (TempDM == 0x14) 462 | *DM=1; 463 | if(TempDM == 0x0A) 464 | *DM=2; 465 | return status; 466 | } 467 | 468 | 469 | 470 | VL53L1X_ERROR VL53L1X::VL53L1X_SetInterMeasurementInMs(uint16_t InterMeasMs) 471 | { 472 | uint16_t ClockPLL; 473 | VL53L1X_ERROR status = 0; 474 | 475 | status = VL53L1X_RdWord(Device, VL53L1X_RESULT__OSC_CALIBRATE_VAL, &ClockPLL); 476 | ClockPLL = ClockPLL&0x3FF; 477 | VL53L1X_WrDWord(Device, VL53L1X_SYSTEM__INTERMEASUREMENT_PERIOD, 478 | (uint32_t)(ClockPLL * InterMeasMs * 1.075)); 479 | return status; 480 | 481 | } 482 | 483 | 484 | VL53L1X_ERROR VL53L1X::VL53L1X_GetInterMeasurementInMs(uint16_t *pIM) 485 | { 486 | uint16_t ClockPLL; 487 | VL53L1X_ERROR status = 0; 488 | uint32_t tmp; 489 | 490 | status = VL53L1X_RdDWord(Device,VL53L1X_SYSTEM__INTERMEASUREMENT_PERIOD, &tmp); 491 | *pIM = (uint16_t)tmp; 492 | status = VL53L1X_RdWord(Device, VL53L1X_RESULT__OSC_CALIBRATE_VAL, &ClockPLL); 493 | ClockPLL = ClockPLL&0x3FF; 494 | *pIM= (uint16_t)(*pIM/(ClockPLL*1.065)); 495 | return status; 496 | } 497 | 498 | 499 | VL53L1X_ERROR VL53L1X::VL53L1X_BootState(uint8_t *state) 500 | { 501 | VL53L1X_ERROR status = 0; 502 | uint8_t tmp = 0; 503 | 504 | status = VL53L1X_RdByte(Device,VL53L1X_FIRMWARE__SYSTEM_STATUS, &tmp); 505 | *state = tmp; 506 | return status; 507 | } 508 | 509 | 510 | VL53L1X_ERROR VL53L1X::VL53L1X_GetSensorId(uint16_t *sensorId) 511 | { 512 | VL53L1X_ERROR status = 0; 513 | uint16_t tmp = 0; 514 | 515 | status = VL53L1X_RdWord(Device, VL53L1X_IDENTIFICATION__MODEL_ID, &tmp); 516 | *sensorId = tmp; 517 | return status; 518 | } 519 | 520 | 521 | VL53L1X_ERROR VL53L1X::VL53L1X_GetDistance(uint16_t *distance) 522 | { 523 | VL53L1X_ERROR status = 0; 524 | uint16_t tmp = 0; 525 | 526 | status = (VL53L1X_RdWord(Device, 527 | VL53L1X_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0, &tmp)); 528 | *distance = tmp; 529 | return status; 530 | } 531 | 532 | VL53L1X_ERROR VL53L1X::VL53L1X_GetSignalPerSpad(uint16_t *signalRate) 533 | { 534 | VL53L1X_ERROR status = 0; 535 | uint16_t SpNb=1, signal; 536 | 537 | status = VL53L1X_RdWord(Device, 538 | VL53L1X_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0, &signal); 539 | status = VL53L1X_RdWord(Device, 540 | VL53L1X_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0, &SpNb); 541 | *signalRate = (uint16_t) (2000.0*signal/SpNb); 542 | return status; 543 | } 544 | 545 | 546 | VL53L1X_ERROR VL53L1X::VL53L1X_GetAmbientPerSpad(uint16_t *ambPerSp) 547 | { 548 | VL53L1X_ERROR status=0; 549 | uint16_t AmbientRate, SpNb=1; 550 | 551 | status = VL53L1X_RdWord(Device, RESULT__AMBIENT_COUNT_RATE_MCPS_SD, &AmbientRate); 552 | status = VL53L1X_RdWord(Device, VL53L1X_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0, &SpNb); 553 | *ambPerSp=(uint16_t) (2000.0 * AmbientRate / SpNb); 554 | return status; 555 | } 556 | 557 | 558 | VL53L1X_ERROR VL53L1X::VL53L1X_GetSignalRate(uint16_t *signal) 559 | { 560 | VL53L1X_ERROR status = 0; 561 | uint16_t tmp; 562 | 563 | status = VL53L1X_RdWord(Device, 564 | VL53L1X_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0, &tmp); 565 | *signal = tmp*8; 566 | return status; 567 | } 568 | 569 | 570 | VL53L1X_ERROR VL53L1X::VL53L1X_GetSpadNb(uint16_t *spNb) 571 | { 572 | VL53L1X_ERROR status = 0; 573 | uint16_t tmp; 574 | 575 | status = VL53L1X_RdWord(Device, 576 | VL53L1X_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0, &tmp); 577 | *spNb = tmp >> 8; 578 | return status; 579 | } 580 | 581 | 582 | VL53L1X_ERROR VL53L1X::VL53L1X_GetAmbientRate(uint16_t *ambRate) 583 | { 584 | VL53L1X_ERROR status = 0; 585 | uint16_t tmp; 586 | 587 | status = VL53L1X_RdWord(Device, RESULT__AMBIENT_COUNT_RATE_MCPS_SD, &tmp); 588 | *ambRate = tmp*8; 589 | return status; 590 | } 591 | 592 | 593 | VL53L1X_ERROR VL53L1X::VL53L1X_GetRangeStatus(uint8_t *rangeStatus) 594 | { 595 | VL53L1X_ERROR status = 0; 596 | uint8_t RgSt; 597 | 598 | status = VL53L1X_RdByte(Device, VL53L1X_RESULT__RANGE_STATUS, &RgSt); 599 | RgSt = RgSt&0x1F; 600 | switch (RgSt) 601 | { 602 | case 9: 603 | RgSt = 0; 604 | break; 605 | case 6: 606 | RgSt = 1; 607 | break; 608 | case 4: 609 | RgSt = 2; 610 | break; 611 | case 8: 612 | RgSt = 3; 613 | break; 614 | case 5: 615 | RgSt = 4; 616 | break; 617 | case 3: 618 | RgSt = 5; 619 | break; 620 | case 19: 621 | RgSt = 6; 622 | break; 623 | case 7: 624 | RgSt = 7; 625 | break; 626 | case 12: 627 | RgSt = 9; 628 | break; 629 | case 18: 630 | RgSt = 10; 631 | break; 632 | case 22: 633 | RgSt = 11; 634 | break; 635 | case 23: 636 | RgSt = 12; 637 | break; 638 | case 13: 639 | RgSt = 13; 640 | break; 641 | default: 642 | RgSt = 255; 643 | break; 644 | } 645 | *rangeStatus = RgSt; 646 | return status; 647 | } 648 | 649 | 650 | VL53L1X_ERROR VL53L1X::VL53L1X_SetOffset(int16_t OffsetValue) 651 | { 652 | VL53L1X_ERROR status = 0; 653 | int16_t Temp; 654 | 655 | Temp = (OffsetValue*4); 656 | VL53L1X_WrWord(Device, ALGO__PART_TO_PART_RANGE_OFFSET_MM, 657 | (uint16_t)Temp); 658 | VL53L1X_WrWord(Device, MM_CONFIG__INNER_OFFSET_MM, 0x0); 659 | VL53L1X_WrWord(Device, MM_CONFIG__OUTER_OFFSET_MM, 0x0); 660 | return status; 661 | } 662 | 663 | 664 | VL53L1X_ERROR VL53L1X::VL53L1X_GetOffset(int16_t *offset) 665 | { 666 | VL53L1X_ERROR status = 0; 667 | uint16_t Temp; 668 | 669 | status = VL53L1X_RdWord(Device,ALGO__PART_TO_PART_RANGE_OFFSET_MM, &Temp); 670 | Temp = Temp<<3; 671 | *offset = (int16_t)(Temp); 672 | *offset = *offset / 32; 673 | return status; 674 | } 675 | 676 | VL53L1X_ERROR VL53L1X::VL53L1X_SetXtalk(uint16_t XtalkValue) 677 | { 678 | /* XTalkValue in count per second to avoid float type */ 679 | VL53L1X_ERROR status = 0; 680 | 681 | status = VL53L1X_WrWord(Device, 682 | ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS, 683 | 0x0000); 684 | status = VL53L1X_WrWord(Device, ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS, 685 | 0x0000); 686 | status = VL53L1X_WrWord(Device, ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS, 687 | (XtalkValue<<9)/1000); /* * << 9 (7.9 format) and /1000 to convert cps to kpcs */ 688 | return status; 689 | } 690 | 691 | 692 | VL53L1X_ERROR VL53L1X::VL53L1X_GetXtalk(uint16_t *xtalk ) 693 | { 694 | VL53L1X_ERROR status = 0; 695 | uint16_t tmp; 696 | 697 | status = VL53L1X_RdWord(Device,ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS, &tmp); 698 | *xtalk = (tmp*1000)>>9; /* * 1000 to convert kcps to cps and >> 9 (7.9 format) */ 699 | return status; 700 | } 701 | 702 | 703 | VL53L1X_ERROR VL53L1X::VL53L1X_SetDistanceThreshold(uint16_t ThreshLow, 704 | uint16_t ThreshHigh, uint8_t Window, 705 | uint8_t IntOnNoTarget) 706 | { 707 | VL53L1X_ERROR status = 0; 708 | uint8_t Temp = 0; 709 | 710 | status = VL53L1X_RdByte(Device, SYSTEM__INTERRUPT_CONFIG_GPIO, &Temp); 711 | Temp = Temp & 0x47; 712 | if (IntOnNoTarget == 0) 713 | { 714 | status = VL53L1X_WrByte(Device, SYSTEM__INTERRUPT_CONFIG_GPIO, 715 | (Temp | (Window & 0x07))); 716 | } 717 | else 718 | { 719 | status = VL53L1X_WrByte(Device, SYSTEM__INTERRUPT_CONFIG_GPIO, 720 | ((Temp | (Window & 0x07)) | 0x40)); 721 | } 722 | status = VL53L1X_WrWord(Device, SYSTEM__THRESH_HIGH, ThreshHigh); 723 | status = VL53L1X_WrWord(Device, SYSTEM__THRESH_LOW, ThreshLow); 724 | return status; 725 | } 726 | 727 | 728 | VL53L1X_ERROR VL53L1X::VL53L1X_GetDistanceThresholdWindow(uint16_t *window) 729 | { 730 | VL53L1X_ERROR status = 0; 731 | uint8_t tmp; 732 | status = VL53L1X_RdByte(Device,SYSTEM__INTERRUPT_CONFIG_GPIO, &tmp); 733 | *window = (uint16_t)(tmp & 0x7); 734 | return status; 735 | } 736 | 737 | 738 | VL53L1X_ERROR VL53L1X::VL53L1X_GetDistanceThresholdLow(uint16_t *low) 739 | { 740 | VL53L1X_ERROR status = 0; 741 | uint16_t tmp; 742 | 743 | status = VL53L1X_RdWord(Device,SYSTEM__THRESH_LOW, &tmp); 744 | *low = tmp; 745 | return status; 746 | } 747 | 748 | VL53L1X_ERROR VL53L1X::VL53L1X_GetDistanceThresholdHigh(uint16_t *high) 749 | { 750 | VL53L1X_ERROR status = 0; 751 | uint16_t tmp; 752 | 753 | status = VL53L1X_RdWord(Device,SYSTEM__THRESH_HIGH, &tmp); 754 | *high = tmp; 755 | return status; 756 | } 757 | 758 | VL53L1X_ERROR VL53L1X::VL53L1X_SetROI(uint16_t X, uint16_t Y) 759 | { 760 | uint8_t OpticalCenter; 761 | VL53L1X_ERROR status = 0; 762 | 763 | status =VL53L1X_RdByte(Device, VL53L1X_ROI_CONFIG__MODE_ROI_CENTRE_SPAD, &OpticalCenter); 764 | if (X > 16) 765 | X = 16; 766 | if (Y > 16) 767 | Y = 16; 768 | if (X > 10 || Y > 10) 769 | { 770 | OpticalCenter = 199; 771 | } 772 | status = VL53L1X_WrByte(Device, ROI_CONFIG__USER_ROI_CENTRE_SPAD, OpticalCenter); 773 | status = VL53L1X_WrByte(Device, ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE, 774 | (Y - 1) << 4 | (X - 1)); 775 | return status; 776 | } 777 | 778 | VL53L1X_ERROR VL53L1X::VL53L1X_GetROI_XY(uint16_t *ROI_X, uint16_t *ROI_Y) 779 | { 780 | VL53L1X_ERROR status = 0; 781 | uint8_t tmp; 782 | 783 | status = VL53L1X_RdByte(Device,ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE, &tmp); 784 | *ROI_X = ((uint16_t)tmp & 0x0F) + 1; 785 | *ROI_Y = (((uint16_t)tmp & 0xF0) >> 4) + 1; 786 | return status; 787 | } 788 | 789 | VL53L1X_ERROR VL53L1X::VL53L1X_SetROICenter(uint8_t ROICenter) 790 | { 791 | VL53L1X_ERROR status = 0; 792 | status = VL53L1X_WrByte(Device,ROI_CONFIG__USER_ROI_CENTRE_SPAD,ROICenter); 793 | return status; 794 | } 795 | 796 | VL53L1X_ERROR VL53L1X::VL53L1X_GetROICenter(uint8_t *ROICenter) 797 | { 798 | VL53L1X_ERROR status = 0; 799 | uint8_t tmp; 800 | status = VL53L1X_RdByte(Device,ROI_CONFIG__USER_ROI_CENTRE_SPAD,&tmp); 801 | *ROICenter = tmp; 802 | return status; 803 | } 804 | 805 | VL53L1X_ERROR VL53L1X::VL53L1X_SetSignalThreshold(uint16_t Signal) 806 | { 807 | VL53L1X_ERROR status = 0; 808 | 809 | VL53L1X_WrWord(Device,RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS,Signal>>3); 810 | return status; 811 | } 812 | 813 | VL53L1X_ERROR VL53L1X::VL53L1X_GetSignalThreshold(uint16_t *signal) 814 | { 815 | VL53L1X_ERROR status = 0; 816 | uint16_t tmp; 817 | 818 | status = VL53L1X_RdWord(Device, 819 | RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS, &tmp); 820 | *signal = tmp <<3; 821 | return status; 822 | } 823 | 824 | 825 | VL53L1X_ERROR VL53L1X::VL53L1X_SetSigmaThreshold(uint16_t Sigma) 826 | { 827 | VL53L1X_ERROR status = 0; 828 | 829 | if(Sigma>(0xFFFF>>2)) 830 | { 831 | return 1; 832 | } 833 | /* 16 bits register 14.2 format */ 834 | status = VL53L1X_WrWord(Device,RANGE_CONFIG__SIGMA_THRESH,Sigma<<2); 835 | return status; 836 | } 837 | 838 | VL53L1X_ERROR VL53L1X::VL53L1X_GetSigmaThreshold(uint16_t *sigma) 839 | { 840 | VL53L1X_ERROR status = 0; 841 | uint16_t tmp; 842 | 843 | status = VL53L1X_RdWord(Device,RANGE_CONFIG__SIGMA_THRESH, &tmp); 844 | *sigma = tmp >> 2; 845 | return status; 846 | 847 | } 848 | 849 | VL53L1X_ERROR VL53L1X::VL53L1X_StartTemperatureUpdate() 850 | { 851 | VL53L1X_ERROR status = 0; 852 | uint8_t tmp=0; 853 | 854 | status = VL53L1X_WrByte(Device,VL53L1X_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND,0x81); /* full VHV */ 855 | status = VL53L1X_WrByte(Device,0x0B,0x92); 856 | status = VL53L1X_StartRanging(); 857 | while(tmp==0) 858 | { 859 | status = VL53L1X_CheckForDataReady(&tmp); 860 | } 861 | tmp = 0; 862 | status = VL53L1X_ClearInterrupt(); 863 | status = VL53L1X_StopRanging(); 864 | status = VL53L1X_WrByte(Device, VL53L1X_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND, 0x09); /* two bounds VHV */ 865 | status = VL53L1X_WrByte(Device, 0x0B, 0); /* start VHV from the previous temperature */ 866 | return status; 867 | } 868 | 869 | /* VL53L1X_calibration.h functions */ 870 | 871 | int8_t VL53L1X::VL53L1X_CalibrateOffset(uint16_t TargetDistInMm, int16_t *offset) 872 | { 873 | uint8_t i = 0, tmp; 874 | int16_t AverageDistance = 0; 875 | uint16_t distance; 876 | VL53L1X_ERROR status = 0; 877 | 878 | status = VL53L1X_WrWord(Device, ALGO__PART_TO_PART_RANGE_OFFSET_MM, 0x0); 879 | status = VL53L1X_WrWord(Device, MM_CONFIG__INNER_OFFSET_MM, 0x0); 880 | status = VL53L1X_WrWord(Device, MM_CONFIG__OUTER_OFFSET_MM, 0x0); 881 | status = VL53L1X_StartRanging(); /* Enable VL53L1X sensor */ 882 | for (i = 0; i < 50; i++) 883 | { 884 | while (tmp == 0) 885 | { 886 | status = VL53L1X_CheckForDataReady(&tmp); 887 | } 888 | tmp = 0; 889 | status = VL53L1X_GetDistance(&distance); 890 | status = VL53L1X_ClearInterrupt(); 891 | AverageDistance = AverageDistance + distance; 892 | } 893 | status = VL53L1X_StopRanging(); 894 | AverageDistance = AverageDistance / 50; 895 | *offset = TargetDistInMm - AverageDistance; 896 | status = VL53L1X_WrWord(Device, ALGO__PART_TO_PART_RANGE_OFFSET_MM, *offset*4); 897 | return status; 898 | } 899 | 900 | 901 | int8_t VL53L1X::VL53L1X_CalibrateXtalk(uint16_t TargetDistInMm, uint16_t *xtalk) 902 | { 903 | uint8_t i, tmp= 0; 904 | float AverageSignalRate = 0; 905 | float AverageDistance = 0; 906 | float AverageSpadNb = 0; 907 | uint16_t distance = 0, spadNum; 908 | uint16_t sr; 909 | VL53L1X_ERROR status = 0; 910 | 911 | status = VL53L1X_WrWord(Device, 0x0016,0); 912 | status = VL53L1X_StartRanging(); 913 | for (i = 0; i < 50; i++) 914 | { 915 | while (tmp == 0) 916 | { 917 | status = VL53L1X_CheckForDataReady(&tmp); 918 | } 919 | tmp=0; 920 | status= VL53L1X_GetSignalRate(&sr); 921 | status= VL53L1X_GetDistance(&distance); 922 | status = VL53L1X_ClearInterrupt(); 923 | AverageDistance = AverageDistance + distance; 924 | status = VL53L1X_GetSpadNb(&spadNum); 925 | AverageSpadNb = AverageSpadNb + spadNum; 926 | AverageSignalRate = 927 | AverageSignalRate + sr; 928 | } 929 | status = VL53L1X_StopRanging(); 930 | AverageDistance = AverageDistance / 50; 931 | AverageSpadNb = AverageSpadNb / 50; 932 | AverageSignalRate = AverageSignalRate / 50; 933 | /* Calculate Xtalk value */ 934 | *xtalk = (uint16_t)(512*(AverageSignalRate*(1-(AverageDistance/TargetDistInMm)))/AverageSpadNb); 935 | status = VL53L1X_WrWord(Device, 0x0016, *xtalk); 936 | return status; 937 | } 938 | 939 | 940 | 941 | 942 | /* Write and read functions from I2C */ 943 | 944 | 945 | VL53L1X_ERROR VL53L1X::VL53L1X_WriteMulti(VL53L1X_DEV Dev, uint16_t index, uint8_t *pdata, uint32_t count) 946 | { 947 | int status; 948 | 949 | status = VL53L1X_I2CWrite(Dev->I2cDevAddr, index, pdata, (uint16_t)count); 950 | return status; 951 | } 952 | 953 | VL53L1X_ERROR VL53L1X::VL53L1X_ReadMulti(VL53L1X_DEV Dev, uint16_t index, uint8_t *pdata, uint32_t count) 954 | { 955 | int status; 956 | 957 | status = VL53L1X_I2CRead(Dev->I2cDevAddr, index, pdata, (uint16_t)count); 958 | 959 | return status; 960 | } 961 | 962 | 963 | VL53L1X_ERROR VL53L1X::VL53L1X_WrByte(VL53L1X_DEV Dev, uint16_t index, uint8_t data) 964 | { 965 | int status; 966 | 967 | status=VL53L1X_I2CWrite(Dev->I2cDevAddr, index, &data, 1); 968 | return status; 969 | } 970 | 971 | VL53L1X_ERROR VL53L1X::VL53L1X_WrWord(VL53L1X_DEV Dev, uint16_t index, uint16_t data) 972 | { 973 | int status; 974 | uint8_t buffer[2]; 975 | 976 | buffer[0] = data >> 8; 977 | buffer[1] = data & 0x00FF; 978 | status=VL53L1X_I2CWrite(Dev->I2cDevAddr, index, (uint8_t *)buffer, 2); 979 | return status; 980 | } 981 | 982 | VL53L1X_ERROR VL53L1X::VL53L1X_WrDWord(VL53L1X_DEV Dev, uint16_t index, uint32_t data) 983 | { 984 | int status; 985 | uint8_t buffer[4]; 986 | 987 | buffer[0] = (data >> 24) & 0xFF; 988 | buffer[1] = (data >> 16) & 0xFF; 989 | buffer[2] = (data >> 8) & 0xFF; 990 | buffer[3] = (data >> 0) & 0xFF; 991 | status=VL53L1X_I2CWrite(Dev->I2cDevAddr, index, (uint8_t *)buffer, 4); 992 | return status; 993 | } 994 | 995 | 996 | VL53L1X_ERROR VL53L1X::VL53L1X_RdByte(VL53L1X_DEV Dev, uint16_t index, uint8_t *data) 997 | { 998 | int status; 999 | 1000 | status = VL53L1X_I2CRead(Dev->I2cDevAddr, index, data, 1); 1001 | 1002 | if(status) 1003 | return -1; 1004 | 1005 | return 0; 1006 | } 1007 | 1008 | VL53L1X_ERROR VL53L1X::VL53L1X_RdWord(VL53L1X_DEV Dev, uint16_t index, uint16_t *data) 1009 | { 1010 | int status; 1011 | uint8_t buffer[2] = {0,0}; 1012 | 1013 | status = VL53L1X_I2CRead(Dev->I2cDevAddr, index, buffer, 2); 1014 | if (!status) 1015 | { 1016 | *data = (buffer[0] << 8) + buffer[1]; 1017 | } 1018 | return status; 1019 | 1020 | } 1021 | 1022 | VL53L1X_ERROR VL53L1X::VL53L1X_RdDWord(VL53L1X_DEV Dev, uint16_t index, uint32_t *data) 1023 | { 1024 | int status; 1025 | uint8_t buffer[4] = {0,0,0,0}; 1026 | 1027 | status = VL53L1X_I2CRead(Dev->I2cDevAddr, index, buffer, 4); 1028 | if(!status) 1029 | { 1030 | *data = ((uint32_t)buffer[0] << 24) + ((uint32_t)buffer[1] << 16) + ((uint32_t)buffer[2] << 8) + (uint32_t)buffer[3]; 1031 | } 1032 | return status; 1033 | 1034 | } 1035 | 1036 | VL53L1X_ERROR VL53L1X::VL53L1X_UpdateByte(VL53L1X_DEV Dev, uint16_t index, uint8_t AndData, uint8_t OrData) 1037 | { 1038 | int status; 1039 | uint8_t buffer = 0; 1040 | 1041 | /* read data direct onto buffer */ 1042 | status = VL53L1X_I2CRead(Dev->I2cDevAddr, index, &buffer,1); 1043 | if (!status) 1044 | { 1045 | buffer = (buffer & AndData) | OrData; 1046 | status = VL53L1X_I2CWrite(Dev->I2cDevAddr, index, &buffer, (uint16_t)1); 1047 | } 1048 | return status; 1049 | } 1050 | 1051 | VL53L1X_ERROR VL53L1X::VL53L1X_I2CWrite(uint8_t DeviceAddr, uint16_t RegisterAddr, uint8_t* pBuffer, uint16_t NumByteToWrite) 1052 | { 1053 | #ifdef DEBUG_MODE 1054 | Serial.print("Beginning transmission to "); 1055 | Serial.println(((DeviceAddr) >> 1) & 0x7F); 1056 | #endif 1057 | dev_i2c->beginTransmission(((uint8_t)(((DeviceAddr) >> 1) & 0x7F))); 1058 | #ifdef DEBUG_MODE 1059 | Serial.print("Writing port number "); 1060 | Serial.println(RegisterAddr); 1061 | #endif 1062 | uint8_t buffer[2]; 1063 | buffer[0]=(uint8_t) (RegisterAddr>>8); 1064 | buffer[1]=(uint8_t) (RegisterAddr&0xFF); 1065 | dev_i2c->write(buffer, 2); 1066 | for (uint16_t i = 0 ; i < NumByteToWrite ; i++) 1067 | dev_i2c->write(pBuffer[i]); 1068 | 1069 | dev_i2c->endTransmission(true); 1070 | return 0; 1071 | } 1072 | 1073 | VL53L1X_ERROR VL53L1X::VL53L1X_I2CRead(uint8_t DeviceAddr, uint16_t RegisterAddr, uint8_t* pBuffer, uint16_t NumByteToRead) 1074 | { 1075 | int status = 0; 1076 | //Loop until the port is transmitted correctly 1077 | do 1078 | { 1079 | #ifdef DEBUG_MODE 1080 | Serial.print("Beginning transmission to "); 1081 | Serial.println(((DeviceAddr) >> 1) & 0x7F); 1082 | #endif 1083 | dev_i2c->beginTransmission(((uint8_t)(((DeviceAddr) >> 1) & 0x7F))); 1084 | #ifdef DEBUG_MODE 1085 | Serial.print("Writing port number "); 1086 | Serial.println(RegisterAddr); 1087 | #endif 1088 | uint8_t buffer[2]; 1089 | buffer[0]=(uint8_t) (RegisterAddr>>8); 1090 | buffer[1]=(uint8_t) (RegisterAddr&0xFF); 1091 | dev_i2c->write(buffer, 2); 1092 | status = dev_i2c->endTransmission(false); 1093 | //Fix for some STM32 boards 1094 | //Reinitialize th i2c bus with the default parameters 1095 | #ifdef ARDUINO_ARCH_STM32 1096 | if (status) 1097 | { 1098 | dev_i2c->end(); 1099 | dev_i2c->begin(); 1100 | } 1101 | #endif 1102 | //End of fix 1103 | } 1104 | while(status != 0); 1105 | 1106 | dev_i2c->requestFrom(((uint8_t)(((DeviceAddr) >> 1) & 0x7F)), (byte) NumByteToRead); 1107 | 1108 | int i=0; 1109 | while (dev_i2c->available()) 1110 | { 1111 | pBuffer[i] = dev_i2c->read(); 1112 | i++; 1113 | } 1114 | 1115 | return 0; 1116 | } 1117 | 1118 | 1119 | VL53L1X_ERROR VL53L1X::VL53L1X_GetTickCount( 1120 | uint32_t *ptick_count_ms) 1121 | { 1122 | 1123 | /* Returns current tick count in [ms] */ 1124 | 1125 | VL53L1X_ERROR status = VL53L1X_ERROR_NONE; 1126 | 1127 | //*ptick_count_ms = timeGetTime(); 1128 | *ptick_count_ms = 0; 1129 | 1130 | return status; 1131 | } 1132 | 1133 | 1134 | 1135 | VL53L1X_ERROR VL53L1X::VL53L1X_WaitUs(VL53L1X_Dev_t *pdev, int32_t wait_us) 1136 | { 1137 | (void)pdev; 1138 | delay(wait_us/1000); 1139 | return VL53L1X_ERROR_NONE; 1140 | } 1141 | 1142 | 1143 | VL53L1X_ERROR VL53L1X::VL53L1X_WaitMs(VL53L1X_Dev_t *pdev, int32_t wait_ms) 1144 | { 1145 | (void)pdev; 1146 | delay(wait_ms); 1147 | return VL53L1X_ERROR_NONE; 1148 | } 1149 | 1150 | 1151 | VL53L1X_ERROR VL53L1X::VL53L1X_WaitValueMaskEx( 1152 | VL53L1X_Dev_t *pdev, 1153 | uint32_t timeout_ms, 1154 | uint16_t index, 1155 | uint8_t value, 1156 | uint8_t mask, 1157 | uint32_t poll_delay_ms) 1158 | { 1159 | 1160 | /* 1161 | * Platform implementation of WaitValueMaskEx V2WReg script command 1162 | * 1163 | * WaitValueMaskEx( 1164 | * duration_ms, 1165 | * index, 1166 | * value, 1167 | * mask, 1168 | * poll_delay_ms); 1169 | */ 1170 | 1171 | VL53L1X_Error status = VL53L1X_ERROR_NONE; 1172 | uint32_t start_time_ms = 0; 1173 | uint32_t current_time_ms = 0; 1174 | uint32_t polling_time_ms = 0; 1175 | uint8_t byte_value = 0; 1176 | uint8_t found = 0; 1177 | 1178 | 1179 | 1180 | /* calculate time limit in absolute time */ 1181 | 1182 | VL53L1X_GetTickCount(&start_time_ms); 1183 | 1184 | /* remember current trace functions and temporarily disable 1185 | * function logging 1186 | */ 1187 | 1188 | 1189 | /* wait until value is found, timeout reached on error occurred */ 1190 | 1191 | while ((status == VL53L1X_ERROR_NONE) && 1192 | (polling_time_ms < timeout_ms) && 1193 | (found == 0)) 1194 | { 1195 | 1196 | if (status == VL53L1X_ERROR_NONE) 1197 | status = VL53L1X_RdByte( 1198 | pdev, 1199 | index, 1200 | &byte_value); 1201 | 1202 | if ((byte_value & mask) == value) 1203 | found = 1; 1204 | 1205 | if (status == VL53L1X_ERROR_NONE && 1206 | found == 0 && 1207 | poll_delay_ms > 0) 1208 | status = VL53L1X_WaitMs( 1209 | pdev, 1210 | poll_delay_ms); 1211 | 1212 | /* Update polling time (Compare difference rather than absolute to 1213 | negate 32bit wrap around issue) */ 1214 | VL53L1X_GetTickCount(¤t_time_ms); 1215 | polling_time_ms = current_time_ms - start_time_ms; 1216 | 1217 | } 1218 | 1219 | 1220 | if (found == 0 && status == VL53L1X_ERROR_NONE) 1221 | status = VL53L1X_ERROR_TIME_OUT; 1222 | 1223 | return status; 1224 | } 1225 | 1226 | 1227 | 1228 | 1229 | -------------------------------------------------------------------------------- /src/vl53l1x_class.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright © 2018, STMicroelectronics International N.V. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of STMicroelectronics nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND 19 | NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED. 20 | IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. BE LIABLE FOR ANY 21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | *****************************************************************************/ 28 | 29 | #ifndef __VL53L1X_CLASS_H 30 | #define __VL53L1X_CLASS_H 31 | 32 | 33 | #ifdef _MSC_VER 34 | # ifdef VL53L1X_API_EXPORTS 35 | # define VL53L1X_API __declspec(dllexport) 36 | # else 37 | # define VL53L1X_API 38 | # endif 39 | #else 40 | # define VL53L1X_API 41 | #endif 42 | 43 | 44 | /* Includes ------------------------------------------------------------------*/ 45 | #include "Arduino.h" 46 | #include "Wire.h" 47 | #include "RangeSensor.h" 48 | #include "vl53l1x_error_codes.h" 49 | 50 | 51 | #define VL53L1X_IMPLEMENTATION_VER_MAJOR 1 52 | #define VL53L1X_IMPLEMENTATION_VER_MINOR 0 53 | #define VL53L1X_IMPLEMENTATION_VER_SUB 1 54 | #define VL53L1X_IMPLEMENTATION_VER_REVISION 0000 55 | 56 | typedef int8_t VL53L1X_ERROR; 57 | 58 | #define VL53L1X_I2C_SLAVE__DEVICE_ADDRESS 0x0001 59 | #define VL53L1X_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND 0x0008 60 | #define ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS 0x0016 61 | #define ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS 0x0018 62 | #define ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS 0x001A 63 | #define ALGO__PART_TO_PART_RANGE_OFFSET_MM 0x001E 64 | #define MM_CONFIG__INNER_OFFSET_MM 0x0020 65 | #define MM_CONFIG__OUTER_OFFSET_MM 0x0022 66 | #define GPIO_HV_MUX__CTRL 0x0030 67 | #define GPIO__TIO_HV_STATUS 0x0031 68 | #define SYSTEM__INTERRUPT_CONFIG_GPIO 0x0046 69 | #define PHASECAL_CONFIG__TIMEOUT_MACROP 0x004B 70 | #define RANGE_CONFIG__TIMEOUT_MACROP_A_HI 0x005E 71 | #define RANGE_CONFIG__VCSEL_PERIOD_A 0x0060 72 | #define RANGE_CONFIG__VCSEL_PERIOD_B 0x0063 73 | #define RANGE_CONFIG__TIMEOUT_MACROP_B_HI 0x0061 74 | #define RANGE_CONFIG__TIMEOUT_MACROP_B_LO 0x0062 75 | #define RANGE_CONFIG__SIGMA_THRESH 0x0064 76 | #define RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS 0x0066 77 | #define RANGE_CONFIG__VALID_PHASE_HIGH 0x0069 78 | #define VL53L1X_SYSTEM__INTERMEASUREMENT_PERIOD 0x006C 79 | #define SYSTEM__THRESH_HIGH 0x0072 80 | #define SYSTEM__THRESH_LOW 0x0074 81 | #define SD_CONFIG__WOI_SD0 0x0078 82 | #define SD_CONFIG__INITIAL_PHASE_SD0 0x007A 83 | #define ROI_CONFIG__USER_ROI_CENTRE_SPAD 0x007F 84 | #define ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE 0x0080 85 | #define SYSTEM__SEQUENCE_CONFIG 0x0081 86 | #define VL53L1X_SYSTEM__GROUPED_PARAMETER_HOLD 0x0082 87 | #define SYSTEM__INTERRUPT_CLEAR 0x0086 88 | #define SYSTEM__MODE_START 0x0087 89 | #define VL53L1X_RESULT__RANGE_STATUS 0x0089 90 | #define VL53L1X_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0 0x008C 91 | #define RESULT__AMBIENT_COUNT_RATE_MCPS_SD 0x0090 92 | #define VL53L1X_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 0x0096 93 | #define VL53L1X_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0 0x0098 94 | #define VL53L1X_RESULT__OSC_CALIBRATE_VAL 0x00DE 95 | #define VL53L1X_FIRMWARE__SYSTEM_STATUS 0x00E5 96 | #define VL53L1X_IDENTIFICATION__MODEL_ID 0x010F 97 | #define VL53L1X_ROI_CONFIG__MODE_ROI_CENTRE_SPAD 0x013E 98 | 99 | 100 | #define VL53L1X_DEFAULT_DEVICE_ADDRESS 0x52 101 | 102 | /**************************************** 103 | * PRIVATE define do not edit 104 | ****************************************/ 105 | 106 | /** 107 | * @brief defines SW Version 108 | */ 109 | typedef struct 110 | { 111 | uint8_t major; /*!< major number */ 112 | uint8_t minor; /*!< minor number */ 113 | uint8_t build; /*!< build number */ 114 | uint32_t revision; /*!< revision number */ 115 | } VL53L1X_Version_t; 116 | 117 | 118 | typedef struct 119 | { 120 | 121 | uint8_t I2cDevAddr; 122 | TwoWire *I2cHandle; 123 | 124 | } VL53L1X_Dev_t; 125 | 126 | typedef VL53L1X_Dev_t *VL53L1X_DEV; 127 | 128 | 129 | /* Classes -------------------------------------------------------------------*/ 130 | /** Class representing a VL53L1X sensor component 131 | */ 132 | class VL53L1X : public RangeSensor 133 | { 134 | public: 135 | /** Constructor 136 | * @param[in] i2c device I2C to be used for communication 137 | * @param[in] pin shutdown pin to be used as component GPIO0 138 | */ 139 | VL53L1X(TwoWire *i2c, int pin) : RangeSensor(), dev_i2c(i2c), gpio0(pin) 140 | { 141 | Device = &MyDevice; 142 | memset((void *)Device, 0x0, sizeof(VL53L1X_Dev_t)); 143 | MyDevice.I2cDevAddr=VL53L1X_DEFAULT_DEVICE_ADDRESS; 144 | MyDevice.I2cHandle = i2c; 145 | } 146 | 147 | /** Destructor 148 | */ 149 | virtual ~VL53L1X() {} 150 | /* warning: VL53L1X class inherits from GenericSensor, RangeSensor and LightSensor, that haven`t a destructor. 151 | The warning should request to introduce a virtual destructor to make sure to delete the object */ 152 | 153 | virtual int begin() 154 | { 155 | if(gpio0 >= 0) 156 | { 157 | pinMode(gpio0, OUTPUT); 158 | } 159 | return 0; 160 | } 161 | 162 | virtual int end() 163 | { 164 | if(gpio0 >= 0) 165 | { 166 | pinMode(gpio0, INPUT); 167 | } 168 | return 0; 169 | } 170 | 171 | /*** Interface Methods ***/ 172 | /*** High level API ***/ 173 | /** 174 | * @brief PowerOn the sensor 175 | * @return void 176 | */ 177 | /* turns on the sensor */ 178 | virtual void VL53L1X_On(void) 179 | { 180 | if(gpio0 >= 0) 181 | { 182 | digitalWrite(gpio0, HIGH); 183 | } 184 | delay(10); 185 | } 186 | 187 | /** 188 | * @brief PowerOff the sensor 189 | * @return void 190 | */ 191 | /* turns off the sensor */ 192 | virtual void VL53L1X_Off(void) 193 | { 194 | if(gpio0 >= 0) 195 | { 196 | digitalWrite(gpio0, LOW); 197 | } 198 | delay(10); 199 | } 200 | 201 | /** 202 | * @brief Initialize the sensor with default values 203 | * @return 0 on Success 204 | */ 205 | 206 | VL53L1X_ERROR InitSensor(uint8_t address) 207 | { 208 | VL53L1X_ERROR status = 0; 209 | uint8_t sensorState = 0; 210 | VL53L1X_Off(); 211 | VL53L1X_On(); 212 | status = VL53L1X_SetI2CAddress(address); 213 | 214 | #ifdef DEBUG_MODE 215 | uint8_t byteData; 216 | uint16_t wordData; 217 | status = VL53L1X_RdByte(Device, 0x010F, &byteData); 218 | Serial.println("VL53L1X Model_ID: " + String(byteData)); 219 | status = VL53L1X_RdByte(Device, 0x0110, &byteData); 220 | Serial.println("VL53L1X Module_Type: " + String(byteData)); 221 | status = VL53L1X_RdWord(Device, 0x010F, &wordData); 222 | Serial.println("VL53L1X: " + String(wordData)); 223 | #endif 224 | 225 | 226 | while (!sensorState && !status) 227 | { 228 | status = VL53L1X_BootState(&sensorState); 229 | delay(2); 230 | } 231 | if(!status) 232 | { 233 | status = VL53L1X_SensorInit(); 234 | } 235 | return status; 236 | } 237 | 238 | 239 | 240 | /** 241 | * 242 | * @brief One time device initialization 243 | * @param void 244 | * @return 0 on success, @a #CALIBRATION_WARNING if failed 245 | */ 246 | virtual int Init() 247 | { 248 | return VL53L1X_SensorInit(); 249 | } 250 | 251 | 252 | 253 | /* Read function of the ID device */ 254 | virtual int ReadID() 255 | { 256 | uint16_t sensorId; 257 | VL53L1X_GetSensorId(&sensorId); 258 | if (sensorId == 0xEEAC) 259 | return 0; 260 | return -1; 261 | } 262 | 263 | 264 | 265 | /** 266 | * @brief Get ranging result and only that 267 | * @param pRange_mm Pointer to range distance 268 | * @return 0 on success 269 | */ 270 | int GetDistance(uint32_t *piData) 271 | { 272 | int status; 273 | uint16_t distance; 274 | status = VL53L1X_GetDistance(&distance); 275 | *piData = (uint32_t) distance; 276 | return status; 277 | } 278 | 279 | 280 | /* VL53L1X_api.h functions */ 281 | 282 | 283 | 284 | /** 285 | * @brief This function returns the SW driver version 286 | */ 287 | VL53L1X_ERROR VL53L1X_GetSWVersion(VL53L1X_Version_t *pVersion); 288 | 289 | /** 290 | * @brief This function sets the sensor I2C address used in case multiple devices application, default address 0x52 291 | */ 292 | VL53L1X_ERROR VL53L1X_SetI2CAddress(uint8_t new_address); 293 | 294 | /** 295 | * @brief This function loads the 135 bytes default values to initialize the sensor. 296 | * @param dev Device address 297 | * @return 0:success, != 0:failed 298 | */ 299 | VL53L1X_ERROR VL53L1X_SensorInit(); 300 | 301 | /** 302 | * @brief This function clears the interrupt, to be called after a ranging data reading 303 | * to arm the interrupt for the next data ready event. 304 | */ 305 | VL53L1X_ERROR VL53L1X_ClearInterrupt(); 306 | 307 | /** 308 | * @brief This function programs the interrupt polarity\n 309 | * 1=active high (default), 0=active low 310 | */ 311 | VL53L1X_ERROR VL53L1X_SetInterruptPolarity(uint8_t IntPol); 312 | 313 | /** 314 | * @brief This function returns the current interrupt polarity\n 315 | * 1=active high (default), 0=active low 316 | */ 317 | VL53L1X_ERROR VL53L1X_GetInterruptPolarity(uint8_t *pIntPol); 318 | 319 | /** 320 | * @brief This function starts the ranging distance operation\n 321 | * The ranging operation is continuous. The clear interrupt has to be done after each get data to allow the interrupt to raise when the next data is ready\n 322 | * 1=active high (default), 0=active low, use SetInterruptPolarity() to change the interrupt polarity if required. 323 | */ 324 | VL53L1X_ERROR VL53L1X_StartRanging(); 325 | 326 | /** 327 | * @brief This function stops the ranging. 328 | */ 329 | VL53L1X_ERROR VL53L1X_StopRanging(); 330 | 331 | /** 332 | * @brief This function checks if the new ranging data is available by polling the dedicated register. 333 | * @param : isDataReady==0 -> not ready; isDataReady==1 -> ready 334 | */ 335 | VL53L1X_ERROR VL53L1X_CheckForDataReady(uint8_t *isDataReady); 336 | 337 | /** 338 | * @brief This function programs the timing budget in ms. 339 | * Predefined values = 15, 20, 33, 50, 100(default), 200, 500. 340 | */ 341 | VL53L1X_ERROR VL53L1X_SetTimingBudgetInMs(uint16_t TimingBudgetInMs); 342 | 343 | /** 344 | * @brief This function returns the current timing budget in ms. 345 | */ 346 | VL53L1X_ERROR VL53L1X_GetTimingBudgetInMs(uint16_t *pTimingBudgetInMs); 347 | 348 | /** 349 | * @brief This function programs the distance mode (1=short, 2=long(default)). 350 | * Short mode max distance is limited to 1.3 m but better ambient immunity.\n 351 | * Long mode can range up to 4 m in the dark with 200 ms timing budget. 352 | */ 353 | VL53L1X_ERROR VL53L1X_SetDistanceMode(uint16_t DistanceMode); 354 | 355 | /** 356 | * @brief This function returns the current distance mode (1=short, 2=long). 357 | */ 358 | VL53L1X_ERROR VL53L1X_GetDistanceMode(uint16_t *pDistanceMode); 359 | 360 | /** 361 | * @brief This function programs the Intermeasurement period in ms\n 362 | * Intermeasurement period must be >/= timing budget. This condition is not checked by the API, 363 | * the customer has the duty to check the condition. Default = 100 ms 364 | */ 365 | VL53L1X_ERROR VL53L1X_SetInterMeasurementInMs(uint16_t InterMeasurementInMs); 366 | 367 | /** 368 | * @brief This function returns the Intermeasurement period in ms. 369 | */ 370 | VL53L1X_ERROR VL53L1X_GetInterMeasurementInMs(uint16_t * pIM); 371 | 372 | /** 373 | * @brief This function returns the boot state of the device (1:booted, 0:not booted) 374 | */ 375 | VL53L1X_ERROR VL53L1X_BootState(uint8_t *state); 376 | 377 | /** 378 | * @brief This function returns the sensor id, sensor Id must be 0xEEAC 379 | */ 380 | VL53L1X_ERROR VL53L1X_GetSensorId(uint16_t *id); 381 | 382 | /** 383 | * @brief This function returns the distance measured by the sensor in mm 384 | */ 385 | VL53L1X_ERROR VL53L1X_GetDistance(uint16_t *distance); 386 | 387 | /** 388 | * @brief This function returns the returned signal per SPAD in kcps/SPAD. 389 | * With kcps stands for Kilo Count Per Second 390 | */ 391 | VL53L1X_ERROR VL53L1X_GetSignalPerSpad(uint16_t *signalPerSp); 392 | 393 | /** 394 | * @brief This function returns the ambient per SPAD in kcps/SPAD 395 | */ 396 | VL53L1X_ERROR VL53L1X_GetAmbientPerSpad(uint16_t *amb); 397 | 398 | /** 399 | * @brief This function returns the returned signal in kcps. 400 | */ 401 | VL53L1X_ERROR VL53L1X_GetSignalRate(uint16_t *signalRate); 402 | 403 | /** 404 | * @brief This function returns the current number of enabled SPADs 405 | */ 406 | VL53L1X_ERROR VL53L1X_GetSpadNb(uint16_t *spNb); 407 | 408 | /** 409 | * @brief This function returns the ambient rate in kcps 410 | */ 411 | VL53L1X_ERROR VL53L1X_GetAmbientRate(uint16_t *ambRate); 412 | 413 | /** 414 | * @brief This function returns the ranging status error \n 415 | * (0:no error, 1:sigma failed, 2:signal failed, ..., 7:wrap-around) 416 | */ 417 | VL53L1X_ERROR VL53L1X_GetRangeStatus(uint8_t *rangeStatus); 418 | 419 | /** 420 | * @brief This function programs the offset correction in mm 421 | * @param OffsetValue:the offset correction value to program in mm 422 | */ 423 | VL53L1X_ERROR VL53L1X_SetOffset(int16_t OffsetValue); 424 | 425 | /** 426 | * @brief This function returns the programmed offset correction value in mm 427 | */ 428 | VL53L1X_ERROR VL53L1X_GetOffset(int16_t *Offset); 429 | 430 | /** 431 | * @brief This function programs the xtalk correction value in cps (Count Per Second).\n 432 | * This is the number of photons reflected back from the cover glass in cps. 433 | */ 434 | VL53L1X_ERROR VL53L1X_SetXtalk(uint16_t XtalkValue); 435 | 436 | /** 437 | * @brief This function returns the current programmed xtalk correction value in cps 438 | */ 439 | VL53L1X_ERROR VL53L1X_GetXtalk(uint16_t *Xtalk); 440 | 441 | /** 442 | * @brief This function programs the threshold detection mode\n 443 | * Example:\n 444 | * VL53L1X_SetDistanceThreshold(dev,100,300,0,1): Below 100 \n 445 | * VL53L1X_SetDistanceThreshold(dev,100,300,1,1): Above 300 \n 446 | * VL53L1X_SetDistanceThreshold(dev,100,300,2,1): Out of window \n 447 | * VL53L1X_SetDistanceThreshold(dev,100,300,3,1): In window \n 448 | * @param dev : device address 449 | * @param ThreshLow(in mm) : the threshold under which one the device raises an interrupt if Window = 0 450 | * @param ThreshHigh(in mm) : the threshold above which one the device raises an interrupt if Window = 1 451 | * @param Window detection mode : 0=below, 1=above, 2=out, 3=in 452 | * @param IntOnNoTarget = 1 (No longer used - just use 1) 453 | */ 454 | VL53L1X_ERROR VL53L1X_SetDistanceThreshold(uint16_t ThreshLow, 455 | uint16_t ThreshHigh, uint8_t Window, 456 | uint8_t IntOnNoTarget); 457 | 458 | /** 459 | * @brief This function returns the window detection mode (0=below; 1=above; 2=out; 3=in) 460 | */ 461 | VL53L1X_ERROR VL53L1X_GetDistanceThresholdWindow(uint16_t *window); 462 | 463 | /** 464 | * @brief This function returns the low threshold in mm 465 | */ 466 | VL53L1X_ERROR VL53L1X_GetDistanceThresholdLow(uint16_t *low); 467 | 468 | /** 469 | * @brief This function returns the high threshold in mm 470 | */ 471 | VL53L1X_ERROR VL53L1X_GetDistanceThresholdHigh(uint16_t *high); 472 | 473 | /** 474 | * @brief This function programs the ROI (Region of Interest)\n 475 | * The ROI position is centered, only the ROI size can be reprogrammed.\n 476 | * The smallest acceptable ROI size = 4\n 477 | * @param X:ROI Width; Y=ROI Height 478 | */ 479 | VL53L1X_ERROR VL53L1X_SetROI(uint16_t X, uint16_t Y); 480 | 481 | /** 482 | *@brief This function returns width X and height Y 483 | */ 484 | VL53L1X_ERROR VL53L1X_GetROI_XY(uint16_t *ROI_X, uint16_t *ROI_Y); 485 | 486 | /** 487 | *@brief This function programs the new user ROI center, please to be aware that there is no check in this function. 488 | *if the ROI center vs ROI size is out of border the ranging function return error #13 489 | */ 490 | VL53L1X_ERROR VL53L1X_SetROICenter(uint8_t ROICenter); 491 | 492 | /** 493 | *@brief This function returns the current user ROI center 494 | */ 495 | VL53L1X_ERROR VL53L1X_GetROICenter(uint8_t *ROICenter); 496 | 497 | /** 498 | * @brief This function programs a new signal threshold in kcps (default=1024 kcps\n 499 | */ 500 | VL53L1X_ERROR VL53L1X_SetSignalThreshold(uint16_t signal); 501 | 502 | /** 503 | * @brief This function returns the current signal threshold in kcps 504 | */ 505 | VL53L1X_ERROR VL53L1X_GetSignalThreshold(uint16_t *signal); 506 | 507 | /** 508 | * @brief This function programs a new sigma threshold in mm (default=15 mm) 509 | */ 510 | VL53L1X_ERROR VL53L1X_SetSigmaThreshold(uint16_t sigma); 511 | 512 | /** 513 | * @brief This function returns the current sigma threshold in mm 514 | */ 515 | VL53L1X_ERROR VL53L1X_GetSigmaThreshold(uint16_t *signal); 516 | 517 | /** 518 | * @brief This function performs the temperature calibration. 519 | * It is recommended to call this function any time the temperature might have changed by more than 8 deg C 520 | * without sensor ranging activity for an extended period. 521 | */ 522 | VL53L1X_ERROR VL53L1X_StartTemperatureUpdate(); 523 | 524 | 525 | /* VL53L1X_calibration.h functions */ 526 | 527 | /** 528 | * @brief This function performs the offset calibration.\n 529 | * The function returns the offset value found and programs the offset compensation into the device. 530 | * @param TargetDistInMm target distance in mm, ST recommended 100 mm 531 | * Target reflectance = grey17% 532 | * @return 0:success, !=0: failed 533 | * @return offset pointer contains the offset found in mm 534 | */ 535 | int8_t VL53L1X_CalibrateOffset(uint16_t TargetDistInMm, int16_t *offset); 536 | 537 | /** 538 | * @brief This function performs the xtalk calibration.\n 539 | * The function returns the xtalk value found and programs the xtalk compensation to the device 540 | * @param TargetDistInMm target distance in mm\n 541 | * The target distance : the distance where the sensor start to "under range"\n 542 | * due to the influence of the photons reflected back from the cover glass becoming strong\n 543 | * It's also called inflection point\n 544 | * Target reflectance = grey 17% 545 | * @return 0: success, !=0: failed 546 | * @return xtalk pointer contains the xtalk value found in cps (number of photons in count per second) 547 | */ 548 | int8_t VL53L1X_CalibrateXtalk(uint16_t TargetDistInMm, uint16_t *xtalk); 549 | 550 | 551 | 552 | 553 | 554 | 555 | protected: 556 | 557 | 558 | /* Write and read functions from I2C */ 559 | 560 | VL53L1X_ERROR VL53L1X_WrByte(VL53L1X_DEV dev, uint16_t index, uint8_t data); 561 | VL53L1X_ERROR VL53L1X_WrWord(VL53L1X_DEV dev, uint16_t index, uint16_t data); 562 | VL53L1X_ERROR VL53L1X_WrDWord(VL53L1X_DEV dev, uint16_t index, uint32_t data); 563 | VL53L1X_ERROR VL53L1X_RdByte(VL53L1X_DEV dev, uint16_t index, uint8_t *data); 564 | VL53L1X_ERROR VL53L1X_RdWord(VL53L1X_DEV dev, uint16_t index, uint16_t *data); 565 | VL53L1X_ERROR VL53L1X_RdDWord(VL53L1X_DEV dev, uint16_t index, uint32_t *data); 566 | VL53L1X_ERROR VL53L1X_UpdateByte(VL53L1X_DEV dev, uint16_t index, uint8_t AndData, uint8_t OrData); 567 | 568 | VL53L1X_ERROR VL53L1X_WriteMulti(VL53L1X_DEV Dev, uint16_t index, uint8_t *pdata, uint32_t count); 569 | VL53L1X_ERROR VL53L1X_ReadMulti(VL53L1X_DEV Dev, uint16_t index, uint8_t *pdata, uint32_t count); 570 | 571 | VL53L1X_ERROR VL53L1X_I2CWrite(uint8_t dev, uint16_t index, uint8_t *data, uint16_t number_of_bytes); 572 | VL53L1X_ERROR VL53L1X_I2CRead(uint8_t dev, uint16_t index, uint8_t *data, uint16_t number_of_bytes); 573 | VL53L1X_ERROR VL53L1X_GetTickCount(uint32_t *ptick_count_ms); 574 | VL53L1X_ERROR VL53L1X_WaitUs(VL53L1X_Dev_t *pdev, int32_t wait_us); 575 | VL53L1X_ERROR VL53L1X_WaitMs(VL53L1X_Dev_t *pdev, int32_t wait_ms); 576 | 577 | VL53L1X_ERROR VL53L1X_WaitValueMaskEx(VL53L1X_Dev_t *pdev, uint32_t timeout_ms, uint16_t index, uint8_t value, uint8_t mask, uint32_t poll_delay_ms); 578 | 579 | 580 | 581 | protected: 582 | 583 | /* IO Device */ 584 | TwoWire *dev_i2c; 585 | /* Digital out pin */ 586 | int gpio0; 587 | /* Device data */ 588 | VL53L1X_Dev_t MyDevice; 589 | VL53L1X_DEV Device; 590 | }; 591 | 592 | 593 | #endif /* _VL53L1X_CLASS_H_ */ 594 | -------------------------------------------------------------------------------- /src/vl53l1x_error_codes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, STMicroelectronics - All Rights Reserved 3 | * 4 | * This file is part of VL53L1X Core and is dual licensed, 5 | * either 'STMicroelectronics 6 | * Proprietary license' 7 | * or 'BSD 3-clause "New" or "Revised" License' , at your option. 8 | * 9 | ******************************************************************************** 10 | * 11 | * 'STMicroelectronics Proprietary license' 12 | * 13 | ******************************************************************************** 14 | * 15 | * License terms: STMicroelectronics Proprietary in accordance with licensing 16 | * terms at www.st.com/sla0081 17 | * 18 | * STMicroelectronics confidential 19 | * Reproduction and Communication of this document is strictly prohibited unless 20 | * specifically authorized in writing by STMicroelectronics. 21 | * 22 | * 23 | ******************************************************************************** 24 | * 25 | * Alternatively, VL53L1X Core may be distributed under the terms of 26 | * 'BSD 3-clause "New" or "Revised" License', in which case the following 27 | * provisions apply instead of the ones mentioned above : 28 | * 29 | ******************************************************************************** 30 | * 31 | * License terms: BSD 3-clause "New" or "Revised" License. 32 | * 33 | * Redistribution and use in source and binary forms, with or without 34 | * modification, are permitted provided that the following conditions are met: 35 | * 36 | * 1. Redistributions of source code must retain the above copyright notice, this 37 | * list of conditions and the following disclaimer. 38 | * 39 | * 2. Redistributions in binary form must reproduce the above copyright notice, 40 | * this list of conditions and the following disclaimer in the documentation 41 | * and/or other materials provided with the distribution. 42 | * 43 | * 3. Neither the name of the copyright holder nor the names of its contributors 44 | * may be used to endorse or promote products derived from this software 45 | * without specific prior written permission. 46 | * 47 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 48 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 50 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 51 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 53 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 54 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 55 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 56 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 | * 58 | * 59 | ******************************************************************************** 60 | * 61 | */ 62 | 63 | /** 64 | * @file vl53l1_error_codes.h 65 | * 66 | * @brief Error Code definitions for VL53L1X API. 67 | * 68 | */ 69 | 70 | #ifndef _VL53L1X_ERROR_CODES_H_ 71 | #define _VL53L1X_ERROR_CODES_H_ 72 | 73 | #ifdef __cplusplus 74 | extern "C" { 75 | #endif 76 | 77 | 78 | /**************************************** 79 | * PRIVATE define do not edit 80 | ****************************************/ 81 | 82 | /** @defgroup VL53L1X_define_Error_group Error and Warning code returned by API 83 | * The following DEFINE are used to identify the PAL ERROR 84 | * @{ 85 | */ 86 | 87 | typedef int8_t VL53L1X_Error; 88 | 89 | #define VL53L1X_ERROR_NONE ((VL53L1X_Error) 0) 90 | #define VL53L1X_ERROR_CALIBRATION_WARNING ((VL53L1X_Error) - 1) 91 | /*!< Warning invalid calibration data may be in used 92 | \a VL53L1X_InitData() 93 | \a VL53L1X_GetOffsetCalibrationData 94 | \a VL53L1X_SetOffsetCalibrationData */ 95 | #define VL53L1X_ERROR_MIN_CLIPPED ((VL53L1X_Error) - 2) 96 | /*!< Warning parameter passed was clipped to min before to be applied */ 97 | 98 | #define VL53L1X_ERROR_UNDEFINED ((VL53L1X_Error) - 3) 99 | /*!< Unqualified error */ 100 | #define VL53L1X_ERROR_INVALID_PARAMS ((VL53L1X_Error) - 4) 101 | /*!< Parameter passed is invalid or out of range */ 102 | #define VL53L1X_ERROR_NOT_SUPPORTED ((VL53L1X_Error) - 5) 103 | /*!< Function is not supported in current mode or configuration */ 104 | #define VL53L1X_ERROR_RANGE_ERROR ((VL53L1X_Error) - 6) 105 | /*!< Device report a ranging error interrupt status */ 106 | #define VL53L1X_ERROR_TIME_OUT ((VL53L1X_Error) - 7) 107 | /*!< Aborted due to time out */ 108 | #define VL53L1X_ERROR_MODE_NOT_SUPPORTED ((VL53L1X_Error) - 8) 109 | /*!< Asked mode is not supported by the device */ 110 | #define VL53L1X_ERROR_BUFFER_TOO_SMALL ((VL53L1X_Error) - 9) 111 | /*!< ... */ 112 | #define VL53L1X_ERROR_COMMS_BUFFER_TOO_SMALL ((VL53L1X_Error) - 10) 113 | /*!< Supplied buffer is larger than I2C supports */ 114 | #define VL53L1X_ERROR_GPIO_NOT_EXISTING ((VL53L1X_Error) - 11) 115 | /*!< User tried to setup a non-existing GPIO pin */ 116 | #define VL53L1X_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED ((VL53L1X_Error) - 12) 117 | /*!< unsupported GPIO functionality */ 118 | #define VL53L1X_ERROR_CONTROL_INTERFACE ((VL53L1X_Error) - 13) 119 | /*!< error reported from IO functions */ 120 | #define VL53L1X_ERROR_INVALID_COMMAND ((VL53L1X_Error) - 14) 121 | /*!< The command is not allowed in the current device state 122 | * (power down) */ 123 | #define VL53L1X_ERROR_DIVISION_BY_ZERO ((VL53L1X_Error) - 15) 124 | /*!< In the function a division by zero occurs */ 125 | #define VL53L1X_ERROR_REF_SPAD_INIT ((VL53L1X_Error) - 16) 126 | /*!< Error during reference SPAD initialization */ 127 | #define VL53L1X_ERROR_GPH_SYNC_CHECK_FAIL ((VL53L1X_Error) - 17) 128 | /*!< GPH sync interrupt check fail - API out of sync with device*/ 129 | #define VL53L1X_ERROR_STREAM_COUNT_CHECK_FAIL ((VL53L1X_Error) - 18) 130 | /*!< Stream count check fail - API out of sync with device */ 131 | #define VL53L1X_ERROR_GPH_ID_CHECK_FAIL ((VL53L1X_Error) - 19) 132 | /*!< GPH ID check fail - API out of sync with device */ 133 | #define VL53L1X_ERROR_ZONE_STREAM_COUNT_CHECK_FAIL ((VL53L1X_Error) - 20) 134 | /*!< Zone dynamic config stream count check failed - API out of sync */ 135 | #define VL53L1X_ERROR_ZONE_GPH_ID_CHECK_FAIL ((VL53L1X_Error) - 21) 136 | /*!< Zone dynamic config GPH ID check failed - API out of sync */ 137 | 138 | #define VL53L1X_ERROR_XTALK_EXTRACTION_NO_SAMPLE_FAIL ((VL53L1X_Error) - 22) 139 | /*!< Thrown when run_xtalk_extraction fn has 0 succesful samples 140 | * when using the full array to sample the xtalk. In this case there is 141 | * not enough information to generate new Xtalk parm info. The function 142 | * will exit and leave the current xtalk parameters unaltered */ 143 | #define VL53L1X_ERROR_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL ((VL53L1X_Error) - 23) 144 | /*!< Thrown when run_xtalk_extraction fn has found that the 145 | * avg sigma estimate of the full array xtalk sample is > than the 146 | * maximal limit allowed. In this case the xtalk sample is too noisy for 147 | * measurement. The function will exit and leave the current xtalk parameters 148 | * unaltered. */ 149 | 150 | 151 | #define VL53L1X_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL ((VL53L1X_Error) - 24) 152 | /*!< Thrown if there one of stages has no valid offset calibration 153 | * samples. A fatal error calibration not valid */ 154 | #define VL53L1X_ERROR_OFFSET_CAL_NO_SPADS_ENABLED_FAIL ((VL53L1X_Error) - 25) 155 | /*!< Thrown if there one of stages has zero effective SPADS 156 | * Traps the case when MM1 SPADs is zero. 157 | * A fatal error calibration not valid */ 158 | #define VL53L1X_ERROR_ZONE_CAL_NO_SAMPLE_FAIL ((VL53L1X_Error) - 26) 159 | /*!< Thrown if then some of the zones have no valid samples 160 | * A fatal error calibration not valid */ 161 | 162 | #define VL53L1X_ERROR_TUNING_PARM_KEY_MISMATCH ((VL53L1X_Error) - 27) 163 | /*!< Thrown if the tuning file key table version does not match with 164 | * expected value. The driver expects the key table version to match 165 | * the compiled default version number in the define 166 | * #VL53L1X_TUNINGPARM_KEY_TABLE_VERSION_DEFAULT 167 | * */ 168 | 169 | #define VL53L1X_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS ((VL53L1X_Error) - 28) 170 | /*!< Thrown if there are less than 5 good SPADs are available. */ 171 | #define VL53L1X_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH ((VL53L1X_Error) - 29) 172 | /*!< Thrown if the final reference rate is greater than 173 | the upper reference rate limit - default is 40 Mcps. 174 | Implies a minimum Q3 (x10) SPAD (5) selected */ 175 | #define VL53L1X_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW ((VL53L1X_Error) - 30) 176 | /*!< Thrown if the final reference rate is less than 177 | the lower reference rate limit - default is 10 Mcps. 178 | Implies maximum Q1 (x1) SPADs selected */ 179 | 180 | 181 | #define VL53L1X_WARNING_OFFSET_CAL_MISSING_SAMPLES ((VL53L1X_Error) - 31) 182 | /*!< Thrown if there is less than the requested number of 183 | * valid samples. */ 184 | #define VL53L1X_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH ((VL53L1X_Error) - 32) 185 | /*!< Thrown if the offset calibration range sigma estimate is greater 186 | * than 8.0 mm. This is the recommended min value to yield a stable 187 | * offset measurement */ 188 | #define VL53L1X_WARNING_OFFSET_CAL_RATE_TOO_HIGH ((VL53L1X_Error) - 33) 189 | /*!< Thrown when VL53L1X_run_offset_calibration() peak rate is greater 190 | than that 50.0Mcps. This is the recommended max rate to avoid 191 | pile-up influencing the offset measurement */ 192 | #define VL53L1X_WARNING_OFFSET_CAL_SPAD_COUNT_TOO_LOW ((VL53L1X_Error) - 34) 193 | /*!< Thrown when VL53L1X_run_offset_calibration() when one of stages 194 | range has less that 5.0 effective SPADS. This is the recommended 195 | min value to yield a stable offset */ 196 | 197 | 198 | #define VL53L1X_WARNING_ZONE_CAL_MISSING_SAMPLES ((VL53L1X_Error) - 35) 199 | /*!< Thrown if one of more of the zones have less than 200 | the requested number of valid samples */ 201 | #define VL53L1X_WARNING_ZONE_CAL_SIGMA_TOO_HIGH ((VL53L1X_Error) - 36) 202 | /*!< Thrown if one or more zones have sigma estimate value greater 203 | * than 8.0 mm. This is the recommended min value to yield a stable 204 | * offset measurement */ 205 | #define VL53L1X_WARNING_ZONE_CAL_RATE_TOO_HIGH ((VL53L1X_Error) - 37) 206 | /*!< Thrown if one of more zones have peak rate higher than 207 | that 50.0Mcps. This is the recommended max rate to avoid 208 | pile-up influencing the offset measurement */ 209 | 210 | 211 | #define VL53L1X_WARNING_XTALK_MISSING_SAMPLES ((VL53L1X_Error) - 38) 212 | /*!< Thrown to notify that some of the xtalk samples did not yield 213 | * valid ranging pulse data while attempting to measure 214 | * the xtalk signal in vl53l1_run_xtalk_extract(). This can signify any of 215 | * the zones are missing samples, for further debug information the 216 | * xtalk_results struct should be referred to. This warning is for 217 | * notification only, the xtalk pulse and shape have still been generated 218 | */ 219 | #define VL53L1X_WARNING_XTALK_NO_SAMPLES_FOR_GRADIENT ((VL53L1X_Error) - 39) 220 | /*!< Thrown to notify that some of teh xtalk samples used for gradient 221 | * generation did not yield valid ranging pulse data while attempting to 222 | * measure the xtalk signal in vl53l1_run_xtalk_extract(). This can signify 223 | * that any one of the zones 0-3 yielded no successful samples. The 224 | * xtalk_results struct should be referred to for further debug info. 225 | * This warning is for notification only, the xtalk pulse and shape 226 | * have still been generated. 227 | */ 228 | #define VL53L1X_WARNING_XTALK_SIGMA_LIMIT_FOR_GRADIENT ((VL53L1X_Error) - 40) 229 | /*!< Thrown to notify that some of the xtalk samples used for gradient 230 | * generation did not pass the sigma limit check while attempting to 231 | * measure the xtalk signal in vl53l1_run_xtalk_extract(). This can signify 232 | * that any one of the zones 0-3 yielded an avg sigma_mm value > the limit. 233 | * The xtalk_results struct should be referred to for further debug info. 234 | * This warning is for notification only, the xtalk pulse and shape 235 | * have still been generated. 236 | */ 237 | 238 | #define VL53L1X_ERROR_NOT_IMPLEMENTED ((VL53L1X_Error) - 41) 239 | /*!< Tells requested functionality has not been implemented yet or 240 | * not compatible with the device */ 241 | #define VL53L1X_ERROR_PLATFORM_SPECIFIC_START ((VL53L1X_Error) - 60) 242 | /*!< Tells the starting code for platform */ 243 | /** @} VL53L1X_define_Error_group */ 244 | 245 | 246 | #ifdef __cplusplus 247 | } 248 | #endif 249 | 250 | 251 | #endif /* _VL53L1X_ERROR_CODES_H_ */ 252 | --------------------------------------------------------------------------------