├── .github └── workflows │ ├── add_issue_to_project.yml │ └── LibraryBuild.yml ├── library.properties ├── LICENSE.md ├── src ├── st_src │ ├── LICENSE.md │ ├── RangeSensor.h │ ├── ComponentObject.h │ ├── vl53l1_error_codes.h │ ├── vl53l1x_class.h │ └── vl53l1x_class.cpp ├── SparkFun_VL53L1X.h └── SparkFun_VL53L1X.cpp ├── keywords.txt ├── examples ├── Example1_ReadDistance │ └── Example1_ReadDistance.ino ├── Example9_OneShotMeasurement │ └── Example9_OneShotMeasurement.ino ├── Example2_SetDistanceMode │ └── Example2_SetDistanceMode.ino ├── Example4_SetIntermeasurementPeriod │ └── Example4_SetIntermeasurementPeriod.ino ├── Example3_StatusAndRate │ └── Example3_StatusAndRate.ino ├── Example6_ArduinoPlotterOutput │ └── Example6_ArduinoPlotterOutput.ino ├── Example8_SetGetDetectionThresholds │ └── Example8_SetGetDetectionThresholds.ino ├── Example7_Calibration │ └── Example7_Calibration.ino └── Example5_LCDDemo │ └── Example5_LCDDemo.ino └── README.md /.github/workflows/add_issue_to_project.yml: -------------------------------------------------------------------------------- 1 | name: Add new issue to our main project 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | 8 | jobs: 9 | add-to-project: 10 | name: Add issue to project 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/add-to-project@main 14 | with: 15 | # You can target a project in a different organization 16 | # to the issue 17 | project-url: https://github.com/orgs/sparkfun/projects/19 18 | github-token: ${{ secrets.DEFECT_ADD_TO_PROJECT }} 19 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=SparkFun VL53L1X 4m Laser Distance Sensor 2 | version=1.2.12 3 | author=SparkFun Electronics 4 | maintainer=SparkFun Electronics 5 | sentence=Library for the SparkFun Qwiic 4m Distance Sensor - VL53L1X 6 | paragraph=The VL53L1X is the latest Time Of Flight (ToF) sensor to be released. It uses a VCSEL (vertical cavity surface emitting laser) to emit a class 1 IR laser and time the reflection to the target. What does all this mean? You can measure the distance to an object up to 4 meters away with millimeter resolution! That’s pretty incredible. We’ve found the precision of the sensor to be 1mm but the accuracy is around +/-5mm. Available at: https://www.sparkfun.com/products/14667 7 | category=Sensors 8 | url=https://github.com/sparkfun/SparkFun_VL53L1X_Arduino_Library 9 | architectures=* 10 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © 2022 SparkFun Electronics 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), 4 | to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 5 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 10 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 11 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 12 | IN THE SOFTWARE. 13 | -------------------------------------------------------------------------------- /src/st_src/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 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For ST_FlightSense_Sensor_Shields 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | SFEVL53L1X KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | init KEYWORD2 16 | begin KEYWORD2 17 | checkID KEYWORD2 18 | sensorOn KEYWORD2 19 | sensorOff KEYWORD2 20 | getSoftwareVersion KEYWORD2 21 | setI2CAddress KEYWORD2 22 | getI2CAddress KEYWORD2 23 | clearInterrupt KEYWORD2 24 | setInterruptPolarityHigh KEYWORD2 25 | setInterruptPolarityLow KEYWORD2 26 | getInterruptPolarity KEYWORD2 27 | startRanging KEYWORD2 28 | stopRanging KEYWORD2 29 | checkForDataReady KEYWORD2 30 | setTimingBudgetInMs KEYWORD2 31 | getTimingBudgetInMs KEYWORD2 32 | setDistanceModeLong KEYWORD2 33 | setDistanceModeShort KEYWORD2 34 | getDistanceMode KEYWORD2 35 | setIntermeasurementPeriod KEYWORD2 36 | getIntermeasurementPeriod KEYWORD2 37 | checkBootState KEYWORD2 38 | getSensorID KEYWORD2 39 | getDistance KEYWORD2 40 | getSignalPerSpad KEYWORD2 41 | getAmbientPerSpad KEYWORD2 42 | getSignalRate KEYWORD2 43 | getSpadNb KEYWORD2 44 | getAmbientRate KEYWORD2 45 | getRangeStatus KEYWORD2 46 | setOffset KEYWORD2 47 | getOffset KEYWORD2 48 | setXTalk KEYWORD2 49 | getXTalk KEYWORD2 50 | setDistanceThreshold KEYWORD2 51 | getDistanceThresholdWindow KEYWORD2 52 | getDistanceThresholdLow KEYWORD2 53 | getDistanceThresholdHig KEYWORD2 54 | setROI KEYWORD2 55 | getROIX KEYWORD2 56 | getROIY KEYWORD2 57 | setSignalThreshold KEYWORD2 58 | getSignalThreshold KEYWORD2 59 | setSigmaThreshold KEYWORD2 60 | getSigmaThreshold KEYWORD2 61 | startTemperatureUpdate KEYWORD2 62 | calibrateOffset KEYWORD2 63 | calibrateXTalk KEYWORD2 64 | 65 | ####################################### 66 | # Constants (LITERAL1) 67 | ####################################### 68 | 69 | 70 | -------------------------------------------------------------------------------- /examples/Example1_ReadDistance/Example1_ReadDistance.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Reading distance from the laser based VL53L1X 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: April 4th, 2018 6 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 7 | 8 | SparkFun labored with love to create this code. Feel like supporting open source hardware? 9 | Buy a board from SparkFun! https://www.sparkfun.com/products/14667 10 | 11 | This example prints the distance to an object. 12 | 13 | Are you getting weird readings? Be sure the vacuum tape has been removed from the sensor. 14 | */ 15 | 16 | #include 17 | #include "SparkFun_VL53L1X.h" //Click here to get the library: http://librarymanager/All#SparkFun_VL53L1X 18 | 19 | //Optional interrupt and shutdown pins. 20 | #define SHUTDOWN_PIN 2 21 | #define INTERRUPT_PIN 3 22 | 23 | SFEVL53L1X distanceSensor; 24 | //Uncomment the following line to use the optional shutdown and interrupt pins. 25 | //SFEVL53L1X distanceSensor(Wire, SHUTDOWN_PIN, INTERRUPT_PIN); 26 | 27 | void setup(void) 28 | { 29 | Wire.begin(); 30 | 31 | Serial.begin(115200); 32 | Serial.println("VL53L1X Qwiic Test"); 33 | 34 | if (distanceSensor.begin() != 0) //Begin returns 0 on a good init 35 | { 36 | Serial.println("Sensor failed to begin. Please check wiring. Freezing..."); 37 | while (1) 38 | ; 39 | } 40 | Serial.println("Sensor online!"); 41 | } 42 | 43 | void loop(void) 44 | { 45 | distanceSensor.startRanging(); //Write configuration bytes to initiate measurement 46 | while (!distanceSensor.checkForDataReady()) 47 | { 48 | delay(1); 49 | } 50 | int distance = distanceSensor.getDistance(); //Get the result of the measurement from the sensor 51 | distanceSensor.clearInterrupt(); 52 | distanceSensor.stopRanging(); 53 | 54 | Serial.print("Distance(mm): "); 55 | Serial.print(distance); 56 | 57 | float distanceInches = distance * 0.0393701; 58 | float distanceFeet = distanceInches / 12.0; 59 | 60 | Serial.print("\tDistance(ft): "); 61 | Serial.print(distanceFeet, 2); 62 | 63 | Serial.println(); 64 | } 65 | -------------------------------------------------------------------------------- /examples/Example9_OneShotMeasurement/Example9_OneShotMeasurement.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Reading distance from the laser based VL53L1X using a one-shot measurement. 3 | By: Nathan Seidle 4 | Revised by: Andy England, Ricardo Ramos 5 | Pull request by: Joseph Duchesne 6 | SparkFun Electronics 7 | Date: January 31st, 2022 8 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 9 | 10 | SparkFun labored with love to create this code. Feel like supporting open source hardware? 11 | Buy a board from SparkFun! https://www.sparkfun.com/products/14667 12 | 13 | This example makes a one shot measurement. 14 | 15 | Are you getting weird readings? Be sure the vacuum tape has been removed from the sensor. 16 | */ 17 | 18 | #include 19 | #include "SparkFun_VL53L1X.h" //Click here to get the library: http://librarymanager/All#SparkFun_VL53L1X 20 | 21 | //Optional interrupt and shutdown pins. 22 | #define SHUTDOWN_PIN 2 23 | #define INTERRUPT_PIN 3 24 | 25 | SFEVL53L1X distanceSensor; 26 | //Uncomment the following line to use the optional shutdown and interrupt pins. 27 | //SFEVL53L1X distanceSensor(Wire, SHUTDOWN_PIN, INTERRUPT_PIN); 28 | 29 | void setup(void) 30 | { 31 | Wire.begin(); 32 | 33 | Serial.begin(115200); 34 | Serial.println("VL53L1X Qwiic Test"); 35 | 36 | if (distanceSensor.begin() != 0) //Begin returns 0 on a good init 37 | { 38 | Serial.println("Sensor failed to begin. Please check wiring. Freezing..."); 39 | while (1) 40 | ; 41 | } 42 | Serial.println("Sensor online!"); 43 | 44 | 45 | } 46 | 47 | void loop(void) 48 | { 49 | distanceSensor.startOneshotRanging(); //Write configuration bytes to initiate measurement 50 | while (!distanceSensor.checkForDataReady()) 51 | { 52 | delay(1); 53 | } 54 | int distance = distanceSensor.getDistance(); //Get the result of the measurement from the sensor 55 | 56 | Serial.print("Distance(mm): "); 57 | Serial.print(distance); 58 | 59 | float distanceInches = distance * 0.0393701; 60 | float distanceFeet = distanceInches / 12.0; 61 | 62 | Serial.print("\tDistance(ft): "); 63 | Serial.print(distanceFeet, 2); 64 | 65 | Serial.println(); 66 | } 67 | -------------------------------------------------------------------------------- /examples/Example2_SetDistanceMode/Example2_SetDistanceMode.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Reading distance from the laser based VL53L1X 3 | By: Nathan Seidle 4 | Revised by: Andy England 5 | SparkFun Electronics 6 | Date: April 4th, 2018 7 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 8 | 9 | SparkFun labored with love to create this code. Feel like supporting open source hardware? 10 | Buy a board from SparkFun! https://www.sparkfun.com/products/14667 11 | 12 | This example prints the distance to an object. 13 | 14 | Are you getting weird readings? Be sure the vacuum tape has been removed from the sensor. 15 | */ 16 | 17 | #include 18 | #include "SparkFun_VL53L1X.h" //Click here to get the library: http://librarymanager/All#SparkFun_VL53L1X 19 | 20 | //Optional interrupt and shutdown pins. 21 | #define SHUTDOWN_PIN 2 22 | #define INTERRUPT_PIN 3 23 | 24 | SFEVL53L1X distanceSensor; 25 | //Uncomment the following line to use the optional shutdown and interrupt pins. 26 | //SFEVL53L1X distanceSensor(Wire, SHUTDOWN_PIN, INTERRUPT_PIN); 27 | 28 | void setup(void) 29 | { 30 | Wire.begin(); 31 | 32 | Serial.begin(115200); 33 | Serial.println("VL53L1X Qwiic Test"); 34 | 35 | if (distanceSensor.begin() != 0) //Begin returns 0 on a good init 36 | { 37 | Serial.println("Sensor failed to begin. Please check wiring. Freezing..."); 38 | while (1) 39 | ; 40 | } 41 | Serial.println("Sensor online!"); 42 | 43 | distanceSensor.setDistanceModeShort(); 44 | //distanceSensor.setDistanceModeLong(); 45 | } 46 | 47 | void loop(void) 48 | { 49 | distanceSensor.startRanging(); //Write configuration bytes to initiate measurement 50 | 51 | while (!distanceSensor.checkForDataReady()) 52 | { 53 | delay(1); 54 | } 55 | int distance = distanceSensor.getDistance(); //Get the result of the measurement from the sensor 56 | distanceSensor.clearInterrupt(); 57 | 58 | distanceSensor.stopRanging(); 59 | 60 | Serial.print("Distance(mm): "); 61 | Serial.print(distance); 62 | 63 | float distanceInches = distance * 0.0393701; 64 | float distanceFeet = distanceInches / 12.0; 65 | 66 | Serial.print("\tDistance(ft): "); 67 | Serial.print(distanceFeet, 2); 68 | 69 | Serial.println(); 70 | } 71 | -------------------------------------------------------------------------------- /examples/Example4_SetIntermeasurementPeriod/Example4_SetIntermeasurementPeriod.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Reading distance from the laser based VL53L1X 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: April 4th, 2018 6 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 7 | 8 | SparkFun labored with love to create this code. Feel like supporting open source hardware? 9 | Buy a board from SparkFun! https://www.sparkfun.com/products/14667 10 | 11 | This example prints the distance to an object. 12 | 13 | Are you getting weird readings? Be sure the vacuum tape has been removed from the sensor. 14 | */ 15 | 16 | #include 17 | #include "SparkFun_VL53L1X.h" //Click here to get the library: http://librarymanager/All#SparkFun_VL53L1X 18 | 19 | //Optional interrupt and shutdown pins. 20 | #define SHUTDOWN_PIN 2 21 | #define INTERRUPT_PIN 3 22 | 23 | SFEVL53L1X distanceSensor; 24 | //Uncomment the following line to use the optional shutdown and interrupt pins. 25 | //SFEVL53L1X distanceSensor(Wire, SHUTDOWN_PIN, INTERRUPT_PIN); 26 | 27 | void setup(void) 28 | { 29 | Wire.begin(); 30 | 31 | Serial.begin(115200); 32 | Serial.println("VL53L1X Qwiic Test"); 33 | 34 | if (distanceSensor.begin() != 0) //Begin returns 0 on a good init 35 | { 36 | Serial.println("Sensor failed to begin. Please check wiring. Freezing..."); 37 | while (1) 38 | ; 39 | } 40 | Serial.println("Sensor online!"); 41 | 42 | // Intermeasurement period must be >= timing budget. Default = 100 ms. 43 | distanceSensor.setIntermeasurementPeriod(200); 44 | Serial.println(distanceSensor.getIntermeasurementPeriod()); 45 | distanceSensor.startRanging(); // Start only once (and do never call stop) 46 | } 47 | 48 | void loop(void) 49 | { 50 | while (!distanceSensor.checkForDataReady()) 51 | { 52 | delay(1); 53 | } 54 | int distance = distanceSensor.getDistance(); //Get the result of the measurement from the sensor 55 | distanceSensor.clearInterrupt(); 56 | 57 | Serial.print("Distance(mm): "); 58 | Serial.print(distance); 59 | 60 | float distanceInches = distance * 0.0393701; 61 | float distanceFeet = distanceInches / 12.0; 62 | 63 | Serial.print("\tDistance(ft): "); 64 | Serial.print(distanceFeet, 2); 65 | 66 | Serial.println(); 67 | } 68 | -------------------------------------------------------------------------------- /src/st_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/st_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 | -------------------------------------------------------------------------------- /examples/Example3_StatusAndRate/Example3_StatusAndRate.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Reading distance from the laser based VL53L1X 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: April 4th, 2018 6 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 7 | 8 | SparkFun labored with love to create this code. Feel like supporting open source hardware? 9 | Buy a board from SparkFun! https://www.sparkfun.com/products/14667 10 | 11 | This example demonstrates how to read and average distance, the measurement status, and the signal rate. 12 | 13 | Are you getting weird readings? Be sure the vacuum tape has been removed from the sensor. 14 | */ 15 | 16 | #include 17 | #include "SparkFun_VL53L1X.h" //Click here to get the library: http://librarymanager/All#SparkFun_VL53L1X 18 | 19 | //Optional interrupt and shutdown pins. 20 | #define SHUTDOWN_PIN 2 21 | #define INTERRUPT_PIN 3 22 | 23 | SFEVL53L1X distanceSensor; 24 | //Uncomment the following line to use the optional shutdown and interrupt pins. 25 | //SFEVL53L1X distanceSensor(Wire, SHUTDOWN_PIN, INTERRUPT_PIN); 26 | 27 | //Store distance readings to get rolling average 28 | #define HISTORY_SIZE 10 29 | int history[HISTORY_SIZE]; 30 | byte historySpot; 31 | 32 | void setup(void) 33 | { 34 | Wire.begin(); 35 | 36 | Serial.begin(115200); 37 | Serial.println("VL53L1X Qwiic Test"); 38 | 39 | if (distanceSensor.begin() != 0) //Begin returns 0 on a good init 40 | { 41 | Serial.println("Sensor failed to begin. Please check wiring. Freezing..."); 42 | while (1) 43 | ; 44 | } 45 | Serial.println("Sensor online!"); 46 | 47 | for (int x = 0; x < HISTORY_SIZE; x++) 48 | history[x] = 0; 49 | } 50 | 51 | void loop(void) 52 | { 53 | long startTime = millis(); 54 | distanceSensor.startRanging(); //Write configuration block of 135 bytes to setup a measurement 55 | while (!distanceSensor.checkForDataReady()) 56 | { 57 | delay(1); 58 | } 59 | int distance = distanceSensor.getDistance(); //Get the result of the measurement from the sensor 60 | distanceSensor.clearInterrupt(); 61 | distanceSensor.stopRanging(); 62 | long endTime = millis(); 63 | 64 | Serial.print("Distance(mm): "); 65 | Serial.print(distance); 66 | 67 | history[historySpot] = distance; 68 | if (++historySpot == HISTORY_SIZE) 69 | historySpot = 0; 70 | 71 | long avgDistance = 0; 72 | for (int x = 0; x < HISTORY_SIZE; x++) 73 | avgDistance += history[x]; 74 | 75 | avgDistance /= HISTORY_SIZE; 76 | Serial.print("\tavgDistance: "); 77 | Serial.print(avgDistance); 78 | 79 | float distanceInches = avgDistance * 0.0393701; 80 | float distanceFeet = distanceInches / 12; 81 | 82 | Serial.print("\tavgDistance(ft): "); 83 | Serial.print(distanceFeet, 2); 84 | 85 | int signalRate = distanceSensor.getSignalRate(); 86 | Serial.print("\tSignal rate: "); 87 | Serial.print(signalRate); 88 | 89 | byte rangeStatus = distanceSensor.getRangeStatus(); 90 | Serial.print("\tRange Status: "); 91 | 92 | //Make it human readable 93 | switch (rangeStatus) 94 | { 95 | case 0: 96 | Serial.print("Good"); 97 | break; 98 | case 1: 99 | Serial.print("Sigma fail"); 100 | break; 101 | case 2: 102 | Serial.print("Signal fail"); 103 | break; 104 | case 7: 105 | Serial.print("Wrapped target fail"); 106 | break; 107 | default: 108 | Serial.print("Unknown: "); 109 | Serial.print(rangeStatus); 110 | break; 111 | } 112 | 113 | Serial.print("\tHz: "); 114 | Serial.print(1000.0 / (float)(endTime - startTime), 2); 115 | 116 | Serial.println(); 117 | } 118 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SparkFun Qwiic 4m Distance Sensor with VL53L1X 2 | ======================================== 3 | [![Build Status](https://github.com/sparkfun/SparkFun_VL53L1X_Arduino_Library/workflows/LibraryBuild/badge.svg)](https://github.com/sparkfun/SparkFun_VL53L1X_Arduino_Library/actions) 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
SparkFun Distance Sensor Breakout - 4 Meter, VL53L1X (Qwiic)SparkFun Distance Sensor - 1.3 Meter, VL53L4CD (Qwiic)
SparkFun Distance Sensor Breakout - 4 Meter, VL53L1X (Qwiic) [SEN-14722]SparkFun Distance Sensor - 1.3 Meter, VL53L4CD (Qwiic)[SEN-18993]
16 | 17 | The VL53L1X is a Time Of Flight (ToF) sensor that use a VCSEL (vertical cavity surface emitting laser) to emit a class 1 IR laser and time the reflection to the target. What does all this mean? Using the VL53L1X, you can measure the distance to an object up to 4 meters away with millimeter resolution! That’s pretty incredible. 18 | 19 | We’re far from done: The VL53L1X is a highly complex sensor with a multitude of options and configurations. We’ve written example sketches that allow you to read the distance, signal rate, and range status. Because STMicroelectronics has chosen not to release a complete datasheet we are forced to reverse engineer the interface from their example code and I2C data stream captures. If you’re into puzzles we could use your help to make the library better! 20 | 21 | We’ve found the precision of VL53L1X sensor to be 1mm but the accuracy is around +/-5mm. 22 | 23 | SparkFun labored with love to create this code. Feel like supporting open source hardware? 24 | Buy a [breakout board](https://www.sparkfun.com/products/14722) from SparkFun! 25 | 26 | *Note: The VL53L4CD is the cousin of VL53L1X. Overall, the sensor functions the same except for a few differences in the specifications. We've also found the precision of VL53L4CD sensor to be 1mm but the accuracy is around +/-7mm (white target: 88%, indoor, no infrared).* 27 | 28 | Repository Contents 29 | ------------------- 30 | 31 | * **/Documents** - Datasheet and User Manual 32 | * **/Hardware** - Eagle design files (.brd, .sch) 33 | * **/Production** - .brd files 34 | 35 | Documentation 36 | -------------- 37 | * **[Installing an Arduino Library Guide](https://learn.sparkfun.com/tutorials/installing-an-arduino-library)** - Basic information on how to install an Arduino library. 38 | * **[Hookup Guide](https://learn.sparkfun.com/tutorials/qwiic-distance-sensor-vl53l1x-vl53l4cd-hookup-guide)**- Basic tutorial for the VL53L1X and VL53L4CD 39 | 40 | Products that use this Library 41 | -------------- 42 | 43 | * **[SEN-18993](https://www.sparkfun.com/products/18993)** - SparkFun red version for VL53L4CD 44 | * **[SEN-14722](https://www.sparkfun.com/products/14722)** - SparkFun red version for VL53L1X 45 | * **[SPX-14667](https://www.sparkfun.com/products/14667)** - SparkX Version for VL53L1X 46 | 47 | License Information 48 | ------------------- 49 | 50 | SparkFun's source files are _**open source**_! 51 | 52 | Please review the LICENSE.md file for license information. 53 | 54 | If you have any questions or concerns on licensing, please contact techsupport@sparkfun.com. 55 | 56 | Please use, reuse, and modify these files as you see fit. Please maintain attribution to SparkFun Electronics and release any derivative under the same license. 57 | 58 | Distributed as-is; no warranty is given. 59 | 60 | The source files included in the subfolder **st_src** are licensed differently. They are licensed under the BSD-3 license, check the License.md in 61 | that subfolder for specifics. 62 | - Your friends at SparkFun. 63 | -------------------------------------------------------------------------------- /examples/Example6_ArduinoPlotterOutput/Example6_ArduinoPlotterOutput.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Reading distance from the laser based VL53L1X 3 | By: Armin Joachimsmeyer 4 | for SparkFun Electronics 5 | Date: February 20th, 2020 6 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 7 | 8 | SparkFun labored with love to create this code. Feel like supporting open source hardware? 9 | Buy a board from SparkFun! https://www.sparkfun.com/products/14667 10 | 11 | This example prints the distance to an object to the Arduino Serial Plotter and generates a tone depending on distance. 12 | 13 | Are you getting weird readings? Be sure the vacuum tape has been removed from the sensor. 14 | */ 15 | 16 | #include 17 | #include "SparkFun_VL53L1X.h" //Click here to get the library: http://librarymanager/All#SparkFun_VL53L1X 18 | 19 | //Optional interrupt and shutdown pins. 20 | #define SHUTDOWN_PIN 2 21 | #define INTERRUPT_PIN 3 22 | #define TONE_PIN 11 23 | 24 | SFEVL53L1X distanceSensor; 25 | //Uncomment the following line to use the optional shutdown and interrupt pins. 26 | //SFEVL53L1X distanceSensor(Wire, SHUTDOWN_PIN, INTERRUPT_PIN); 27 | 28 | void setup(void) 29 | { 30 | Wire.begin(); 31 | 32 | // initialize the digital pin as an output. 33 | pinMode(LED_BUILTIN, OUTPUT); 34 | Serial.begin(115200); 35 | while (!Serial) 36 | ; //delay for Leonardo 37 | // Just to know which program is running on my Arduino 38 | Serial.println(F("START " __FILE__)); 39 | 40 | #if !defined(ESP32) && !defined(ARDUINO_SAM_DUE) && !defined(__SAM3X8E__) 41 | // test beep for the connected speaker 42 | tone(TONE_PIN, 1000, 100); 43 | delay(200); 44 | #endif 45 | 46 | if (distanceSensor.begin() != 0) //Begin returns 0 on a good init 47 | { 48 | Serial.println("Sensor failed to begin. Please check wiring. Freezing..."); 49 | while (1) 50 | ; 51 | } 52 | Serial.println("Sensor online!"); 53 | 54 | // Short mode max distance is limited to 1.3 m but has a better ambient immunity. 55 | // Above 1.3 meter error 4 is thrown (wrap around). 56 | distanceSensor.setDistanceModeShort(); 57 | //distanceSensor.setDistanceModeLong(); // default 58 | 59 | // Print Legend 60 | Serial.println("Distance Signal-Rate/100 Ambient-Rate/100"); 61 | 62 | /* 63 | * The minimum timing budget is 20 ms for the short distance mode and 33 ms for the medium and long distance modes. 64 | * Predefined values = 15, 20, 33, 50, 100(default), 200, 500. 65 | * This function must be called after SetDistanceMode. 66 | */ 67 | distanceSensor.setTimingBudgetInMs(50); 68 | 69 | // measure periodically. Intermeasurement period must be >/= timing budget. 70 | distanceSensor.setIntermeasurementPeriod(100); 71 | distanceSensor.startRanging(); // Start once 72 | } 73 | 74 | void loop(void) 75 | { 76 | while (!distanceSensor.checkForDataReady()) 77 | { 78 | delay(1); 79 | } 80 | byte rangeStatus = distanceSensor.getRangeStatus(); 81 | unsigned int distance = distanceSensor.getDistance(); //Get the result of the measurement from the sensor 82 | distanceSensor.clearInterrupt(); 83 | 84 | /* 85 | * With signed int we get overflow at short distances. 86 | * With unsigned we get an overflow below around 2.5 cm. 87 | */ 88 | unsigned int tSignalRate = distanceSensor.getSignalRate(); 89 | unsigned int tAmbientRate = distanceSensor.getAmbientRate(); 90 | 91 | if (rangeStatus == 0) 92 | { 93 | #if !defined(ESP32) && !defined(ARDUINO_SAM_DUE) && !defined(__SAM3X8E__) 94 | tone(11, distance + 500); 95 | #endif 96 | } 97 | else 98 | { 99 | // if tAmbientRate > tSignalRate we likely get a signal fail error condition 100 | // in Distance mode short we get error 4 (out of bounds) or 7 (wrap around) if the distance is greater than 1.3 meter. 101 | distance = rangeStatus; 102 | #if !defined(ESP32) && !defined(ARDUINO_SAM_DUE) && !defined(__SAM3X8E__) 103 | noTone(11); 104 | #endif 105 | } 106 | 107 | Serial.print(distance); 108 | Serial.print(' '); 109 | Serial.print(tSignalRate / 100); 110 | Serial.print(' '); 111 | Serial.println(tAmbientRate / 100); 112 | } 113 | -------------------------------------------------------------------------------- /examples/Example8_SetGetDetectionThresholds/Example8_SetGetDetectionThresholds.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Reading distance from the laser based VL53L1X 3 | By: Nathan Seidle 4 | Revised by: Andy England and Ricardo Ramos 5 | SparkFun Electronics 6 | Date: January 21st, 2022 7 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 8 | 9 | SparkFun labored with love to create this code. Feel like supporting open source hardware? 10 | Buy a board from SparkFun! https://www.sparkfun.com/products/14667 11 | 12 | This example sets high and low thresholds for detection. 13 | 14 | Are you getting weird readings? Be sure the vacuum tape has been removed from the sensor. 15 | */ 16 | 17 | #include 18 | #include "SparkFun_VL53L1X.h" //Click here to get the library: http://librarymanager/All#SparkFun_VL53L1X 19 | 20 | //Optional interrupt and shutdown pins. 21 | #define SHUTDOWN_PIN 2 22 | #define INTERRUPT_PIN 3 23 | 24 | SFEVL53L1X distanceSensor; 25 | //Uncomment the following line to use the optional shutdown and interrupt pins. 26 | //SFEVL53L1X distanceSensor(Wire, SHUTDOWN_PIN, INTERRUPT_PIN); 27 | 28 | void setup(void) 29 | { 30 | Wire.begin(); 31 | 32 | Serial.begin(115200); 33 | Serial.println("VL53L1X Qwiic Test"); 34 | 35 | if (distanceSensor.begin() != 0) //Begin returns 0 on a good init 36 | { 37 | Serial.println("Sensor failed to begin. Please check wiring. Freezing..."); 38 | while (1) 39 | ; 40 | } 41 | Serial.println("Sensor online!"); 42 | 43 | DetectionConfig dc; // struct instance which holds the detection configuration 44 | dc.IntOnNoTarget = 1; // No longer used - just use 1 per ST 45 | dc.distanceMode = DISTANCE_SHORT; // short distance mode 46 | dc.thresholdHigh = 300; // high threshold of 300 mm 47 | dc.thresholdLow = 70; // low threshold of 70 mm 48 | dc.windowMode = WINDOW_IN; // will measure and trigger interrrupt when measurement fall between 70 and 300 mm 49 | 50 | if(distanceSensor.setThresholdConfig(&dc) == true) 51 | { 52 | Serial.println("Thresholds programmed. Reading configuration back..."); 53 | dc = {}; 54 | if(distanceSensor.getThresholdConfig(&dc) == true) 55 | { 56 | Serial.print("IntOnNoTarget: "); 57 | Serial.println(dc.IntOnNoTarget); 58 | Serial.print("Distance Mode: "); 59 | 60 | if(dc.distanceMode == DISTANCE_SHORT) 61 | Serial.println("DISTANCE_SHORT (0)"); 62 | else 63 | Serial.println("DISTANCE_LONG (1)"); 64 | 65 | Serial.print("Threshold High: "); 66 | Serial.println(dc.thresholdHigh); 67 | Serial.print("Threshold Low: "); 68 | Serial.println(dc.thresholdLow); 69 | Serial.print("Window mode: "); 70 | switch (dc.windowMode) 71 | { 72 | case WINDOW_BELOW: 73 | Serial.println("WINDOW_BELOW (0)"); 74 | break; 75 | 76 | case WINDOW_ABOVE: 77 | Serial.println("WINDOW_ABOVE (1)"); 78 | break; 79 | 80 | case WINDOW_OUT: 81 | Serial.println("WINDOW_OUT (2)"); 82 | break; 83 | 84 | case WINDOW_IN: 85 | Serial.println("WINDOW_IN (3)"); 86 | break; 87 | 88 | default: 89 | break; 90 | } 91 | } 92 | } 93 | else 94 | { 95 | Serial.println("Could not set threshold configuration."); 96 | } 97 | Serial.println("Starting measurements in 2 seconds."); 98 | delay(2000); 99 | Serial.println("Measurements started!"); 100 | 101 | } 102 | 103 | void loop(void) 104 | { 105 | distanceSensor.startRanging(); //Write configuration bytes to initiate measurement 106 | 107 | while (!distanceSensor.checkForDataReady()) 108 | { 109 | delay(1); 110 | } 111 | int distance = distanceSensor.getDistance(); //Get the result of the measurement from the sensor 112 | distanceSensor.clearInterrupt(); 113 | 114 | distanceSensor.stopRanging(); 115 | 116 | Serial.print("Distance(mm): "); 117 | Serial.print(distance); 118 | 119 | float distanceInches = distance * 0.0393701; 120 | float distanceFeet = distanceInches / 12.0; 121 | 122 | Serial.print("\tDistance(ft): "); 123 | Serial.print(distanceFeet, 2); 124 | 125 | Serial.println(); 126 | } 127 | -------------------------------------------------------------------------------- /.github/workflows/LibraryBuild.yml: -------------------------------------------------------------------------------- 1 | # LibraryBuild.yml 2 | # Github workflow script to test compile all examples of an Arduino library repository. 3 | # 4 | # Copyright (C) 2020 Armin Joachimsmeyer 5 | # https://github.com/ArminJo/Github-Actions 6 | # License: MIT 7 | # 8 | # Before being able to push to my .github\workflows directories, 9 | # I had to create a new personal token with workflow enabled at https://github.com/settings/tokens 10 | 11 | # This is the name of the workflow, visible on GitHub UI. 12 | name: LibraryBuild 13 | on: 14 | push: # see: https://help.github.com/en/actions/reference/events-that-trigger-workflows#pull-request-event-pull_request 15 | paths: 16 | - '**.ino' 17 | - '**.cpp' 18 | - '**.h' 19 | - '**LibraryBuild.yml' 20 | pull_request: 21 | 22 | jobs: 23 | build: 24 | name: ${{ matrix.arduino-boards-fqbn }} - test compiling examples 25 | 26 | runs-on: ubuntu-18.04 # I picked Ubuntu to use shell scripts. 27 | 28 | env: 29 | # Comma separated list without double quotes around the list. 30 | PLATFORM_DEFAULT_URL: https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json 31 | REQUIRED_LIBRARIES: EspSoftwareSerial 32 | 33 | strategy: 34 | matrix: 35 | # The matrix will produce one job for each configuration parameter of type `arduino-boards-fqbn` 36 | # In the Arduino IDE, the fqbn is printed in the first line of the verbose output for compilation as parameter -fqbn=... for the "arduino-builder -dump-prefs" command 37 | # 38 | # Examples: arduino:avr:uno, arduino:avr:leonardo, arduino:avr:nano, arduino:avr:mega 39 | # arduino:sam:arduino_due_x, arduino:samd:arduino_zero_native" 40 | # ATTinyCore:avr:attinyx5:chip=85,clock=1internal, digistump:avr:digispark-tiny, digistump:avr:digispark-pro 41 | # STM32:stm32:GenF1:pnum=BLUEPILL_F103C8 42 | # esp8266:esp8266:huzzah:eesz=4M3M,xtal=80, esp32:esp32:featheresp32:FlashFreq=80 43 | # You may add a suffix behind the fqbn with "|" to specify one board for e.g. different compile options like arduino:avr:uno|trace 44 | ############################################################################################################# 45 | arduino-boards-fqbn: 46 | - arduino:avr:uno 47 | - arduino:avr:leonardo 48 | - arduino:avr:mega 49 | - arduino:sam:arduino_due_x 50 | - SparkFun:apollo3:artemis 51 | - SparkFun:apollo3:amap3redboard 52 | - SparkFun:apollo3:amap3nano 53 | - SparkFun:apollo3:amap3atp 54 | - SparkFun:apollo3:amap3thing 55 | - SparkFun:apollo3:edge 56 | - SparkFun:apollo3:edge2 57 | - esp8266:esp8266:huzzah:eesz=4M3M,xtal=80 58 | - esp32:esp32:featheresp32:FlashFreq=80 59 | - STM32:stm32:GenF1:pnum=BLUEPILL_F103C8 60 | 61 | # Choose the right platform for the boards we want to test. (maybe in the future Arduino will automatically do this for you). 62 | # This works like this: when the fqbn is "arduino:avr:uno" the variable `platform` is set to "arduino:avr". 63 | # Just take the first 2 token of the fqbn - this cannot be automatically done by GitHub workflow :-( 64 | # You may exclude specific examples for a board with examples-exclude: Use a space separated list. 65 | ############################################################################################################# 66 | include: 67 | - arduino-boards-fqbn: arduino:sam:arduino_due_x 68 | examples-exclude: Example5_LCDDemo # No SoftwareSerial available. Space separated list of (unique substrings of) example names to exclude in build 69 | 70 | - arduino-boards-fqbn: esp8266:esp8266:huzzah:eesz=4M3M,xtal=80 71 | platform-url: https://arduino.esp8266.com/stable/package_esp8266com_index.json 72 | 73 | - arduino-boards-fqbn: esp32:esp32:featheresp32:FlashFreq=80 74 | platform-url: https://dl.espressif.com/dl/package_esp32_index.json 75 | 76 | - arduino-boards-fqbn: STM32:stm32:GenF1:pnum=BLUEPILL_F103C8 77 | platform-url: https://github.com/stm32duino/BoardManagerFiles/raw/dev/STM32/package_stm_index.json 78 | 79 | # Do not cancel all jobs / architectures if one job fails 80 | fail-fast: false 81 | 82 | # This is the list of steps this job will run. 83 | steps: 84 | 85 | # First of all, we clone the repo using the `checkout` action. 86 | - name: Checkout 87 | uses: actions/checkout@v2 88 | 89 | - name: Compile all examples 90 | uses: ArminJo/arduino-test-compile@v2 91 | with: 92 | required-libraries: ${{ env.REQUIRED_LIBRARIES }} 93 | arduino-board-fqbn: ${{ matrix.arduino-boards-fqbn }} 94 | platform-default-url: ${{ env.PLATFORM_DEFAULT_URL }} 95 | platform-url: ${{ matrix.platform-url }} 96 | examples-exclude: ${{ matrix.examples-exclude }} 97 | -------------------------------------------------------------------------------- /examples/Example7_Calibration/Example7_Calibration.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Calling distance offset calibration for the laser based VL53L1X 3 | By: Armin Joachimsmeyer 4 | for SparkFun Electronics 5 | Date: February 20th, 2020 6 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 7 | 8 | SparkFun labored with love to create this code. Feel like supporting open source hardware? 9 | Buy a board from SparkFun! https://www.sparkfun.com/products/14667 10 | 11 | This example calls the offset calibration for a VL53L1X sensor and stores the value to EEPROM. 12 | 13 | Are you getting weird readings? Be sure the vacuum tape has been removed from the sensor. 14 | */ 15 | 16 | #include 17 | #include "SparkFun_VL53L1X.h" //Click here to get the library: http://librarymanager/All#SparkFun_VL53L1X 18 | 19 | #define VERSION_EXAMPLE "1.0" 20 | 21 | #define EEPROM_ADDRESS_FOR_OFFSET (E2END - 2) // last 2 bytes of EEPROM 22 | 23 | //Optional interrupt and shutdown pins. 24 | #define SHUTDOWN_PIN 2 25 | #define INTERRUPT_PIN 3 26 | #define TONE_PIN 11 27 | 28 | SFEVL53L1X distanceSensor; 29 | //Uncomment the following line to use the optional shutdown and interrupt pins. 30 | //SFEVL53L1X distanceSensor(Wire, SHUTDOWN_PIN, INTERRUPT_PIN); 31 | 32 | void setup(void) 33 | { 34 | Wire.begin(); 35 | 36 | // initialize the digital pin as an output. 37 | pinMode(LED_BUILTIN, OUTPUT); 38 | Serial.begin(115200); 39 | #if defined(__AVR_ATmega32U4__) 40 | while (!Serial) 41 | ; //delay for Leonardo, but this loops forever for Maple Serial 42 | #endif 43 | #if defined(SERIAL_USB) 44 | delay(2000); // To be able to connect Serial monitor after reset and before first printout 45 | #endif 46 | // Just to know which program is running on my Arduino 47 | Serial.println(F("START " __FILE__ "\r\nVersion " VERSION_EXAMPLE " from " __DATE__)); 48 | 49 | #if !defined(ESP32) && !defined(ARDUINO_SAM_DUE) && !defined(__SAM3X8E__) 50 | tone(TONE_PIN, 1000, 100); 51 | delay(200); 52 | #endif 53 | 54 | Serial.println(); 55 | Serial.println("*****************************************************************************************************"); 56 | Serial.println(" Offset calibration"); 57 | Serial.println("Place a light grey (17 % gray) target at a distance of 140mm in front of the VL53L1X sensor."); 58 | Serial.println("The calibration will start 5 seconds after a distance below 10 cm was detected for 1 second."); 59 | Serial.println("Use the resulting offset distance as parameter for the setOffset() function called after begin()."); 60 | Serial.println("*****************************************************************************************************"); 61 | Serial.println(); 62 | 63 | #ifdef AVR 64 | Serial.print("Old offset value read from EEPROM="); 65 | Serial.print((int16_t)eeprom_read_word((uint16_t *)EEPROM_ADDRESS_FOR_OFFSET)); 66 | Serial.println(" mm"); 67 | #endif 68 | 69 | if (distanceSensor.begin() != 0) //Begin returns 0 on a good init 70 | { 71 | Serial.println("Sensor failed to begin. Please check wiring. Freezing..."); 72 | while (1) 73 | ; 74 | } 75 | Serial.println("Sensor online!"); 76 | 77 | // Short mode max distance is limited to 1.3 m but has a better ambient immunity. 78 | // Above 1.3 meter error 4 is thrown (wrap around). 79 | distanceSensor.setDistanceModeShort(); 80 | //distanceSensor.setDistanceModeLong(); // default 81 | distanceSensor.setTimingBudgetInMs(50); 82 | 83 | int tLowDistanceCount = 0; 84 | while (tLowDistanceCount < 20) 85 | { 86 | while (!distanceSensor.checkForDataReady()) 87 | { 88 | delay(1); 89 | } 90 | if (distanceSensor.getDistance() < 100) 91 | { 92 | tLowDistanceCount++; 93 | } 94 | else 95 | { 96 | tLowDistanceCount = 0; 97 | } 98 | distanceSensor.clearInterrupt(); 99 | } 100 | 101 | Serial.println("Distance below 10cm detected for more than a second, start offset calibration in 5 seconds"); 102 | #if !defined(ESP32) && !defined(ARDUINO_SAM_DUE) && !defined(__SAM3X8E__) 103 | tone(TONE_PIN, 1000, 100); 104 | delay(1000); 105 | tone(TONE_PIN, 1000, 100); 106 | delay(1000); 107 | tone(TONE_PIN, 1000, 100); 108 | delay(1000); 109 | tone(TONE_PIN, 1000, 100); 110 | delay(1000); 111 | tone(TONE_PIN, 1000, 900); 112 | delay(1000); 113 | #else 114 | delay(5000); 115 | #endif 116 | 117 | /* 118 | * Place a target, 17 % gray, at a distance of 140 mm from the sensor and call the VL53L1X_CalibrateOffset (dev, 140, &offset) function. 119 | * The calibration may take a few seconds. The offset correction is applied to the sensor at the end of calibration. 120 | * 121 | * The calibration function takes 50 measurements and then takes the difference between the target distance 122 | * and the average distance and then calls setOffset() with this value. Thats all. No magic. 123 | */ 124 | distanceSensor.calibrateOffset(140); 125 | Serial.print("Result of offset calibration. RealDistance - MeasuredDistance="); 126 | Serial.print(distanceSensor.getOffset()); 127 | Serial.print(" mm"); 128 | Serial.println(); 129 | 130 | #ifdef AVR 131 | eeprom_write_word((uint16_t *)EEPROM_ADDRESS_FOR_OFFSET, distanceSensor.getOffset()); 132 | Serial.println("Offset value written to end of EEPROM."); 133 | #endif 134 | 135 | // measure periodically. Intermeasurement period must be >/= timing budget. 136 | distanceSensor.setIntermeasurementPeriod(100); 137 | distanceSensor.startRanging(); // Start once 138 | 139 | #if !defined(ESP32) && !defined(ARDUINO_SAM_DUE) && !defined(__SAM3X8E__) 140 | tone(TONE_PIN, 1000, 900); 141 | #endif 142 | } 143 | 144 | void loop(void) 145 | { 146 | } 147 | -------------------------------------------------------------------------------- /examples/Example5_LCDDemo/Example5_LCDDemo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Reading distance from the laser based VL53L1X 3 | By: Nathan Seidle 4 | SparkFun Electronics 5 | Date: April 4th, 2018 6 | License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). 7 | 8 | SparkFun labored with love to create this code. Feel like supporting open source hardware? 9 | Buy a board from SparkFun! https://www.sparkfun.com/products/14667 10 | 11 | Reading distance and outputting the distance and speed to a SerLCD. 12 | This is based on the Speed Trap project: https://www.youtube.com/watch?v=uC9CkhJiIaQ 13 | 14 | Are you getting weird readings? Make sure the vacuum tape has been removed. 15 | 16 | */ 17 | #include 18 | #include "SparkFun_VL53L1X.h" //Click here to get the library: http://librarymanager/All#SparkFun_VL53L1X 19 | #include 20 | 21 | //Optional interrupt and shutdown pins. 22 | #define SHUTDOWN_PIN 2 23 | #define INTERRUPT_PIN 3 24 | 25 | SFEVL53L1X distanceSensor; 26 | //Uncomment the following line to use the optional shutdown and interrupt pins. 27 | //SFEVL53L1X distanceSensor(Wire, SHUTDOWN_PIN, INTERRUPT_PIN); 28 | 29 | #if defined(ESP8266) 30 | SoftwareSerial lcd(10, 9); // RX, TX 31 | #elif defined(ARDUINO_ARCH_APOLLO3) 32 | SoftwareSerial lcd(14, 15); // use RX1, TX1 of Apollo boards 33 | #else 34 | SoftwareSerial lcd(10, A3); // RX, TX 35 | #endif 36 | 37 | //Store distance readings to get rolling average 38 | #define HISTORY_SIZE 8 39 | int history[HISTORY_SIZE]; 40 | byte historySpot; 41 | 42 | long lastReading = 0; 43 | long lastDistance = 0; 44 | float newDistance; 45 | int maxDistance = 0; 46 | 47 | const byte numberOfDeltas = 8; 48 | float deltas[numberOfDeltas]; 49 | byte deltaSpot = 0; //Keeps track of where we are within the deltas array 50 | 51 | //This controls how quickly the display updates 52 | //Too quickly and it gets twitchy. Too slow and it doesn't seem like it's responding. 53 | #define LOOPTIME 50 54 | 55 | int maxMPH = 0; //Keeps track of what the latest fastest speed is 56 | long maxMPH_timeout = 0; //Forget the max speed after some length of time 57 | 58 | #define maxMPH_remember 3000 //After this number of ms the system will forget the max speed 59 | 60 | boolean readingValid = false; 61 | long validCount = 0; 62 | 63 | void setup(void) 64 | { 65 | Wire.begin(); 66 | Wire.setClock(400000); 67 | 68 | Serial.begin(115200); 69 | Serial.println("VL53L1X Qwiic Test"); 70 | 71 | lcd.begin(9600); 72 | 73 | lcd.write(254); //Move cursor to beginning of first line 74 | lcd.write(128); 75 | lcd.print("Distance: 3426 "); 76 | lcd.print("12 mph "); 77 | 78 | if (distanceSensor.begin() != 0) //Begin returns 0 on a good init 79 | { 80 | Serial.println("Sensor failed to begin. Please check wiring. Freezing..."); 81 | while (1) 82 | ; 83 | } 84 | Serial.println("Sensor online!"); 85 | 86 | for (int x = 0; x < HISTORY_SIZE; x++) 87 | history[x] = 0; 88 | } 89 | 90 | void loop(void) 91 | { 92 | 93 | //Write configuration block of 135 bytes to setup a measurement 94 | distanceSensor.startRanging(); 95 | while (!distanceSensor.checkForDataReady()) 96 | { 97 | delay(1); 98 | } 99 | int distanceMM = distanceSensor.getDistance(); 100 | distanceSensor.clearInterrupt(); 101 | distanceSensor.stopRanging(); 102 | 103 | lastReading = millis(); 104 | 105 | history[historySpot] = distanceMM; 106 | if (historySpot++ == HISTORY_SIZE) 107 | historySpot = 0; 108 | 109 | long avgDistance = 0; 110 | for (int x = 0; x < HISTORY_SIZE; x++) 111 | avgDistance += history[x]; 112 | 113 | avgDistance /= HISTORY_SIZE; 114 | 115 | //Every loop let's get a reading 116 | newDistance = distanceMM / 10; //Go get distance in cm 117 | 118 | int deltaDistance = lastDistance - newDistance; 119 | lastDistance = newDistance; 120 | 121 | //Scan delta array to see if this new delta is sane or not 122 | boolean safeDelta = true; 123 | for (int x = 0; x < numberOfDeltas; x++) 124 | { 125 | //We don't want to register jumps greater than 30cm in 50ms 126 | //But if we're less than 1000cm then maybe 127 | //30 works well 128 | if (abs(deltaDistance - deltas[x]) > 40) 129 | safeDelta = false; 130 | } 131 | 132 | //Insert this new delta into the array 133 | if (safeDelta) 134 | { 135 | deltas[deltaSpot++] = deltaDistance; 136 | if (deltaSpot > numberOfDeltas) 137 | deltaSpot = 0; //Wrap this variable 138 | } 139 | 140 | //Get average of the current deltas array 141 | float avgDeltas = 0.0; 142 | for (byte x = 0; x < numberOfDeltas; x++) 143 | avgDeltas += (float)deltas[x]; 144 | avgDeltas /= numberOfDeltas; 145 | 146 | //22.36936 comes from a big coversion from cm per 50ms to mile per hour 147 | float instantMPH = 22.36936 * (float)avgDeltas / (float)LOOPTIME; 148 | 149 | instantMPH = abs(instantMPH); //We want to measure as you walk away 150 | 151 | instantMPH = ceil(instantMPH); //Round up to the next number. This is helpful if we're not displaying decimals. 152 | 153 | if (instantMPH > maxMPH) 154 | { 155 | maxMPH = instantMPH; 156 | maxMPH_timeout = millis(); 157 | } 158 | 159 | if (millis() - maxMPH_timeout > maxMPH_remember) 160 | { 161 | maxMPH = 0; 162 | } 163 | 164 | int signalRate = distanceSensor.getSignalRate(); 165 | if (signalRate < 10) 166 | { 167 | readingValid = false; 168 | validCount = 0; 169 | } 170 | else 171 | { 172 | validCount++; 173 | if (avgDistance > maxDistance) 174 | maxDistance = avgDistance; 175 | } 176 | 177 | if (validCount > 10) 178 | readingValid = true; 179 | 180 | if (readingValid == false) 181 | { 182 | instantMPH = 0; 183 | avgDistance = 0; 184 | } 185 | 186 | //Convert mm per millisecond to miles per hour 187 | //float mph = distanceDelta * 2.236936 / (float)timeDelta; 188 | //mph *= -1; //Flip sign as we will be traveling towards sensor, decreasing the distance 189 | 190 | lcd.write(254); //Move cursor 191 | lcd.write(138); 192 | lcd.print(" "); 193 | lcd.write(254); //Move cursor 194 | lcd.write(138); 195 | 196 | if (readingValid == true) 197 | lcd.print(avgDistance); 198 | else 199 | lcd.print(maxDistance); 200 | 201 | lcd.write(254); //Move cursor 202 | lcd.write(192); 203 | lcd.print(instantMPH, 0); 204 | lcd.print(" mph "); 205 | 206 | delay(25); 207 | } 208 | -------------------------------------------------------------------------------- /src/SparkFun_VL53L1X.h: -------------------------------------------------------------------------------- 1 | /* 2 | This is a library written for the VL53L1X I2C Distance sensor. 3 | 4 | Written by Andy England @ SparkFun Electronics, October 17th, 2017 5 | 6 | The sensor uses I2C to communicate, as well as a single (optional) 7 | interrupt line that is not currently supported in this driver. 8 | 9 | https://github.com/sparkfun/SparkFun_VL53L1X_Arduino_Library 10 | 11 | Do you like this library? Help support SparkFun. Buy a board! 12 | 13 | Development environment specifics: 14 | Arduino IDE 1.8.1 15 | 16 | ==== MIT License ==== 17 | Copyright © 2022 SparkFun Electronics 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 20 | software and associated documentation files (the “Software”), to deal in the Software without restriction, 21 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 22 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 23 | 24 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 27 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 28 | OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 29 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | ===================== 31 | */ 32 | 33 | #pragma once 34 | 35 | #include "Arduino.h" 36 | #include "Wire.h" 37 | #include "st_src/RangeSensor.h" 38 | #include "st_src/vl53l1_error_codes.h" 39 | #include "st_src/vl53l1x_class.h" 40 | #include "st_src/ComponentObject.h" 41 | #include "st_src/RangeSensor.h" 42 | 43 | #define DISTANCE_SHORT 1 44 | #define DISTANCE_LONG 2 45 | #define WINDOW_BELOW 0 46 | #define WINDOW_ABOVE 1 47 | #define WINDOW_OUT 2 48 | #define WINDOW_IN 3 49 | 50 | struct DetectionConfig 51 | { 52 | uint16_t distanceMode = DISTANCE_SHORT; // distance mode : DISTANCE_SHORT (0) or DISTANCE_LONG (1) 53 | uint16_t windowMode = WINDOW_IN; // window mode : WINDOW_BELOW (0), WINDOW_ABOVE (1), WINDOW_OUT (2), WINDOW_IN (3) 54 | uint8_t IntOnNoTarget = 1; // = 1 (No longer used - just use 1) 55 | uint16_t thresholdHigh = 0; // (in mm) : the threshold above which one the device raises an interrupt if Window = 1 56 | uint16_t thresholdLow = 0; // (in mm) : the threshold under which one the device raises an interrupt if Window = 0 57 | }; 58 | 59 | class SFEVL53L1X 60 | { 61 | public: 62 | //Constructs our Distance sensor 63 | SFEVL53L1X(); // Default to Wire. Set both pins to -1 (undefined). 64 | SFEVL53L1X(TwoWire &i2cPort, int shutdownPin = -1, int interruptPin = -1); 65 | ~SFEVL53L1X(); 66 | bool init(); //Deprecated version of begin 67 | bool begin(); //Initialization of sensor 68 | bool begin(TwoWire &i2cPort); //Initialization of sensor 69 | bool checkID(); //Check the ID of the sensor, returns true if ID is correct 70 | void sensorOn(); //Toggles shutdown pin to turn sensor on and off 71 | void sensorOff(); //Toggles shutdown pin to turn sensor on and off 72 | VL53L1X_Version_t getSoftwareVersion(); //Get's the current ST software version 73 | void setI2CAddress(uint8_t addr); //Set the I2C address 74 | int getI2CAddress(); //Get the I2C address 75 | void clearInterrupt(); // Clear the interrupt flag 76 | void setInterruptPolarityHigh(); //Set the polarity of an active interrupt to High 77 | void setInterruptPolarityLow(); //Set the polarity of an active interrupt to Low 78 | uint8_t getInterruptPolarity(); //get the current interrupt polarity 79 | void startRanging(); //Begins taking measurements 80 | void startOneshotRanging(); // Start one-shot ranging 81 | void stopRanging(); //Stops taking measurements 82 | bool checkForDataReady(); //Checks the to see if data is ready 83 | void setTimingBudgetInMs(uint16_t timingBudget); //Set the timing budget for a measurement 84 | uint16_t getTimingBudgetInMs(); //Get the timing budget for a measurement 85 | void setDistanceModeLong(); //Set to 4M range 86 | void setDistanceModeShort(); //Set to 1.3M range 87 | uint8_t getDistanceMode(); //Get the distance mode, returns 1 for short and 2 for long 88 | void setIntermeasurementPeriod(uint16_t intermeasurement); //Set time between measurements in ms 89 | uint16_t getIntermeasurementPeriod(); //Get time between measurements in ms 90 | bool checkBootState(); //Check if the VL53L1X has been initialized 91 | uint16_t getSensorID(); //Get the sensor ID 92 | uint16_t getDistance(); //Returns distance 93 | uint16_t getSignalPerSpad(); //Returns the average signal rate per SPAD (The sensitive pads that detect light, the VL53L1X has a 16x16 array of these) in kcps/SPAD, or kilo counts per second per SPAD. 94 | uint16_t getAmbientPerSpad(); //Returns the ambient noise when not measuring a signal in kcps/SPAD. 95 | uint16_t getSignalRate(); //Returns the signal rate in kcps. All SPADs combined. 96 | uint16_t getSpadNb(); //Returns the current number of enabled SPADs 97 | uint16_t getAmbientRate(); // Returns the total ambinet rate in kcps. All SPADs combined. 98 | uint8_t getRangeStatus(); //Returns the range status, which can be any of the following. 0 = no error, 1 = signal fail, 2 = sigma fail, 7 = wrapped target fail 99 | void setOffset(int16_t offset); //Manually set an offset in mm 100 | int16_t getOffset(); //Get the current offset in mm 101 | void setXTalk(uint16_t xTalk); //Manually set the value of crosstalk in counts per second (cps), which is interference from any sort of window in front of your sensor. 102 | uint16_t getXTalk(); //Returns the current crosstalk value in cps. 103 | void setDistanceThreshold(uint16_t lowThresh, uint16_t hiThresh, uint8_t window);//Set bounds for the interrupt. lowThresh and hiThresh are the bounds of your interrupt while window decides when the interrupt should fire. The options for window are shown below. 104 | //0: Interrupt triggered on measured distance below lowThresh. 105 | //1: Interrupt triggered on measured distance above hiThresh. 106 | //2: Interrupt triggered on measured distance outside of bounds. 107 | //3: Interrupt triggered on measured distance inside of bounds. 108 | uint16_t getDistanceThresholdWindow(); //Returns distance threshold window option 109 | uint16_t getDistanceThresholdLow(); //Returns lower bound in mm. 110 | uint16_t getDistanceThresholdHigh(); //Returns upper bound in mm 111 | /**Table of Optical Centers** 112 | * 113 | * 128,136,144,152,160,168,176,184, 192,200,208,216,224,232,240,248 114 | * 129,137,145,153,161,169,177,185, 193,201,209,217,225,233,241,249 115 | * 130,138,146,154,162,170,178,186, 194,202,210,218,226,234,242,250 116 | * 131,139,147,155,163,171,179,187, 195,203,211,219,227,235,243,251 117 | * 132,140,148,156,164,172,180,188, 196,204,212,220,228,236,244,252 118 | * 133,141,149,157,165,173,181,189, 197,205,213,221,229,237,245,253 119 | * 134,142,150,158,166,174,182,190, 198,206,214,222,230,238,246,254 120 | * 135,143,151,159,167,175,183,191, 199,207,215,223,231,239,247,255 121 | 122 | * 127,119,111,103, 95, 87, 79, 71, 63, 55, 47, 39, 31, 23, 15, 7 123 | * 126,118,110,102, 94, 86, 78, 70, 62, 54, 46, 38, 30, 22, 14, 6 124 | * 125,117,109,101, 93, 85, 77, 69, 61, 53, 45, 37, 29, 21, 13, 5 125 | * 124,116,108,100, 92, 84, 76, 68, 60, 52, 44, 36, 28, 20, 12, 4 126 | * 123,115,107, 99, 91, 83, 75, 67, 59, 51, 43, 35, 27, 19, 11, 3 127 | * 122,114,106, 98, 90, 82, 74, 66, 58, 50, 42, 34, 26, 18, 10, 2 128 | * 121,113,105, 97, 89, 81, 73, 65, 57, 49, 41, 33, 25, 17, 9, 1 129 | * 120,112,104, 96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0 Pin 1 130 | * 131 | * To set the center, set the pad that is to the right and above the exact center of the region you'd like to measure as your opticalCenter*/ 132 | void setROI(uint8_t x, uint8_t y, uint8_t opticalCenter); //Set the height and width of the ROI(region of interest) in SPADs, lowest possible option is 4. Set optical center based on above table 133 | uint16_t getROIX(); //Returns the width of the ROI in SPADs 134 | uint16_t getROIY(); //Returns the height of the ROI in SPADs 135 | void setSignalThreshold(uint16_t signalThreshold); //Programs the necessary threshold to trigger a measurement. Default is 1024 kcps. 136 | uint16_t getSignalThreshold(); //Returns the signal threshold in kcps 137 | void setSigmaThreshold(uint16_t sigmaThreshold); //Programs a new sigma threshold in mm. (default=15 mm) 138 | uint16_t getSigmaThreshold(); //Returns the current sigma threshold. 139 | void startTemperatureUpdate(); //Recalibrates the sensor for temperature changes. Run this any time the temperature has changed by more than 8°C 140 | void calibrateOffset(uint16_t targetDistanceInMm); //Autocalibrate the offset by placing a target a known distance away from the sensor and passing this known distance into the function. 141 | void calibrateXTalk(uint16_t targetDistanceInMm); //Autocalibrate the crosstalk by placing a target a known distance away from the sensor and passing this known distance into the function. 142 | bool setThresholdConfig(DetectionConfig* config); //Sets threshold configuration struct 143 | bool getThresholdConfig(DetectionConfig* config); //Gets current threshold settings. Returns false on error, true otherwise. Stores results in pointer to struct argument. 144 | 145 | private: 146 | TwoWire *_i2cPort; 147 | int _shutdownPin; 148 | int _interruptPin; 149 | int _i2cAddress = 0x52; 150 | VL53L1X* _device; 151 | }; 152 | -------------------------------------------------------------------------------- /src/SparkFun_VL53L1X.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This is a library written for the VL53L1X I2C Distance sensor. 3 | 4 | Written by Andy England @ SparkFun Electronics, October 17th, 2017 5 | 6 | The sensor uses I2C to communicate, as well as a single (optional) 7 | interrupt line that is not currently supported in this driver. 8 | 9 | https://github.com/sparkfun/SparkFun_VL53L1X_Arduino_Library 10 | 11 | Do you like this library? Help support SparkFun. Buy a board! 12 | 13 | Development environment specifics: 14 | Arduino IDE 1.8.1 15 | 16 | ==== MIT License ==== 17 | Copyright © 2022 SparkFun Electronics 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 20 | software and associated documentation files (the “Software”), to deal in the Software without restriction, 21 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 22 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 23 | 24 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 27 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 28 | OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 29 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | ===================== 31 | */ 32 | 33 | #include 34 | #include "SparkFun_VL53L1X.h" 35 | 36 | SFEVL53L1X::SFEVL53L1X() 37 | { 38 | _i2cPort = &Wire; 39 | _shutdownPin = -1; 40 | _interruptPin = -1; 41 | _device = new VL53L1X(&Wire, -1, -1); 42 | } 43 | SFEVL53L1X::SFEVL53L1X(TwoWire &i2cPort, int shutdownPin, int interruptPin) 44 | { 45 | _i2cPort = &i2cPort; 46 | _shutdownPin = shutdownPin; 47 | _interruptPin = interruptPin; 48 | _device = new VL53L1X(&i2cPort, shutdownPin, interruptPin); 49 | } 50 | SFEVL53L1X::~SFEVL53L1X() 51 | { 52 | delete (VL53L1X *)_device; 53 | } 54 | 55 | bool SFEVL53L1X::init() 56 | { 57 | return _device->VL53L1X_SensorInit(); 58 | } 59 | 60 | bool SFEVL53L1X::begin() 61 | { 62 | if (checkID() == false) 63 | return (VL53L1_ERROR_PLATFORM_SPECIFIC_START); 64 | 65 | return _device->VL53L1X_SensorInit(); 66 | } 67 | 68 | bool SFEVL53L1X::begin(TwoWire &i2cPort) 69 | { 70 | _i2cPort = &i2cPort; 71 | _device->dev_i2c = &i2cPort; 72 | 73 | return begin(); 74 | } 75 | 76 | /*Checks the ID of the device, returns true if ID is correct*/ 77 | 78 | bool SFEVL53L1X::checkID() 79 | { 80 | uint16_t sensorId; 81 | _device->VL53L1X_GetSensorId(&sensorId); 82 | if ((sensorId == 0xEACC) || (sensorId == 0xEBAA)) 83 | return true; 84 | return false; 85 | } 86 | 87 | /*Turns the sensor on if the Shutdown pin is connected*/ 88 | 89 | void SFEVL53L1X::sensorOn() 90 | { 91 | if (_shutdownPin >= 0) 92 | { 93 | digitalWrite(_shutdownPin, HIGH); 94 | } 95 | delay(10); 96 | } 97 | 98 | /*Turns the sensor off if the Shutdown pin is connected*/ 99 | 100 | void SFEVL53L1X::sensorOff() 101 | { 102 | if (_shutdownPin >= 0) 103 | { 104 | digitalWrite(_shutdownPin, LOW); 105 | } 106 | delay(10); 107 | } 108 | 109 | /*Gets the software version number of the current library installed.*/ 110 | 111 | VL53L1X_Version_t SFEVL53L1X::getSoftwareVersion() 112 | { 113 | VL53L1X_Version_t tempVersion; 114 | _device->VL53L1X_GetSWVersion(&tempVersion); 115 | return tempVersion; 116 | } 117 | 118 | void SFEVL53L1X::setI2CAddress(uint8_t addr) 119 | { 120 | _i2cAddress = addr; 121 | _device->VL53L1X_SetI2CAddress(addr); 122 | } 123 | 124 | int SFEVL53L1X::getI2CAddress() 125 | { 126 | return _i2cAddress; 127 | } 128 | 129 | void SFEVL53L1X::clearInterrupt() 130 | { 131 | _device->VL53L1X_ClearInterrupt(); 132 | } 133 | 134 | void SFEVL53L1X::setInterruptPolarityHigh() 135 | { 136 | _device->VL53L1X_SetInterruptPolarity(1); 137 | } 138 | 139 | void SFEVL53L1X::setInterruptPolarityLow() 140 | { 141 | _device->VL53L1X_SetInterruptPolarity(0); 142 | } 143 | 144 | /** 145 | * This function gets the interrupt polarity\n 146 | * 1=active high (default), 0=active low 147 | */ 148 | 149 | uint8_t SFEVL53L1X::getInterruptPolarity() 150 | { 151 | uint8_t tmp; 152 | _device->VL53L1X_GetInterruptPolarity(&tmp); 153 | return tmp; 154 | } 155 | 156 | void SFEVL53L1X::startRanging() 157 | { 158 | _device->VL53L1X_StartRanging(); 159 | } 160 | 161 | void SFEVL53L1X::startOneshotRanging() 162 | { 163 | _device->VL53L1X_StartOneshotRanging(); 164 | } 165 | 166 | void SFEVL53L1X::stopRanging() 167 | { 168 | _device->VL53L1X_StopRanging(); 169 | } 170 | 171 | bool SFEVL53L1X::checkForDataReady() 172 | { 173 | uint8_t dataReady; 174 | _device->VL53L1X_CheckForDataReady(&dataReady); 175 | return (bool)dataReady; 176 | } 177 | 178 | void SFEVL53L1X::setTimingBudgetInMs(uint16_t timingBudget) 179 | { 180 | _device->VL53L1X_SetTimingBudgetInMs(timingBudget); 181 | } 182 | 183 | uint16_t SFEVL53L1X::getTimingBudgetInMs() 184 | { 185 | uint16_t timingBudget; 186 | _device->VL53L1X_GetTimingBudgetInMs(&timingBudget); 187 | return timingBudget; 188 | } 189 | 190 | void SFEVL53L1X::setDistanceModeLong() 191 | { 192 | _device->VL53L1X_SetDistanceMode(DISTANCE_LONG); 193 | } 194 | 195 | void SFEVL53L1X::setDistanceModeShort() 196 | { 197 | _device->VL53L1X_SetDistanceMode(DISTANCE_SHORT); 198 | } 199 | 200 | uint8_t SFEVL53L1X::getDistanceMode() 201 | { 202 | uint16_t distanceMode; 203 | _device->VL53L1X_GetDistanceMode(&distanceMode); 204 | return distanceMode; 205 | } 206 | 207 | void SFEVL53L1X::setIntermeasurementPeriod(uint16_t intermeasurement) 208 | { 209 | _device->VL53L1X_SetInterMeasurementInMs(intermeasurement); 210 | } 211 | 212 | uint16_t SFEVL53L1X::getIntermeasurementPeriod() 213 | { 214 | uint16_t intermeasurement; 215 | _device->VL53L1X_GetInterMeasurementInMs(&intermeasurement); 216 | return intermeasurement; 217 | } 218 | 219 | bool SFEVL53L1X::checkBootState() 220 | { 221 | uint8_t bootState; 222 | _device->VL53L1X_BootState(&bootState); 223 | return (bool)bootState; 224 | } 225 | 226 | uint16_t SFEVL53L1X::getSensorID() 227 | { 228 | uint16_t id; 229 | _device->VL53L1X_GetSensorId(&id); 230 | return id; 231 | } 232 | 233 | uint16_t SFEVL53L1X::getDistance() 234 | { 235 | uint16_t distance; 236 | _device->VL53L1X_GetDistance(&distance); 237 | return (int)distance; 238 | } 239 | 240 | uint16_t SFEVL53L1X::getSignalPerSpad() 241 | { 242 | uint16_t temp; 243 | _device->VL53L1X_GetSignalPerSpad(&temp); 244 | return temp; 245 | } 246 | 247 | uint16_t SFEVL53L1X::getAmbientPerSpad() 248 | { 249 | uint16_t temp; 250 | _device->VL53L1X_GetAmbientPerSpad(&temp); 251 | return temp; 252 | } 253 | 254 | uint16_t SFEVL53L1X::getSignalRate() 255 | { 256 | uint16_t temp; 257 | _device->VL53L1X_GetSignalRate(&temp); 258 | return temp; 259 | } 260 | 261 | uint16_t SFEVL53L1X::getSpadNb() 262 | { 263 | uint16_t temp; 264 | _device->VL53L1X_GetSpadNb(&temp); 265 | return temp; 266 | } 267 | 268 | uint16_t SFEVL53L1X::getAmbientRate() 269 | { 270 | uint16_t temp; 271 | _device->VL53L1X_GetAmbientRate(&temp); 272 | return temp; 273 | } 274 | 275 | uint8_t SFEVL53L1X::getRangeStatus() 276 | { 277 | uint8_t temp; 278 | _device->VL53L1X_GetRangeStatus(&temp); 279 | return temp; 280 | } 281 | 282 | void SFEVL53L1X::setOffset(int16_t offset) 283 | { 284 | _device->VL53L1X_SetOffset(offset); 285 | } 286 | 287 | int16_t SFEVL53L1X::getOffset() 288 | { 289 | int16_t temp; 290 | _device->VL53L1X_GetOffset(&temp); 291 | return temp; 292 | } 293 | 294 | void SFEVL53L1X::setXTalk(uint16_t xTalk) 295 | { 296 | _device->VL53L1X_SetXtalk(xTalk); 297 | } 298 | 299 | uint16_t SFEVL53L1X::getXTalk() 300 | { 301 | uint16_t temp; 302 | _device->VL53L1X_GetXtalk(&temp); 303 | return temp; 304 | } 305 | 306 | void SFEVL53L1X::setDistanceThreshold(uint16_t lowThresh, uint16_t hiThresh, uint8_t window) 307 | { 308 | _device->VL53L1X_SetDistanceThreshold(lowThresh, hiThresh, window, 1); 309 | } 310 | 311 | uint16_t SFEVL53L1X::getDistanceThresholdWindow() 312 | { 313 | uint16_t temp; 314 | _device->VL53L1X_GetDistanceThresholdWindow(&temp); 315 | return temp; 316 | } 317 | 318 | uint16_t SFEVL53L1X::getDistanceThresholdLow() 319 | { 320 | uint16_t temp; 321 | _device->VL53L1X_GetDistanceThresholdLow(&temp); 322 | return temp; 323 | } 324 | 325 | uint16_t SFEVL53L1X::getDistanceThresholdHigh() 326 | { 327 | uint16_t temp; 328 | _device->VL53L1X_GetDistanceThresholdHigh(&temp); 329 | return temp; 330 | } 331 | 332 | void SFEVL53L1X::setROI(uint8_t x, uint8_t y, uint8_t opticalCenter) 333 | { 334 | _device->VL53L1X_SetROI(x, y, opticalCenter); 335 | } 336 | 337 | uint16_t SFEVL53L1X::getROIX() 338 | { 339 | uint16_t tempX; 340 | uint16_t tempY; 341 | _device->VL53L1X_GetROI_XY(&tempX, &tempY); 342 | return tempX; 343 | } 344 | 345 | uint16_t SFEVL53L1X::getROIY() 346 | { 347 | uint16_t tempX; 348 | uint16_t tempY; 349 | _device->VL53L1X_GetROI_XY(&tempX, &tempY); 350 | return tempY; 351 | } 352 | 353 | void SFEVL53L1X::setSignalThreshold(uint16_t signalThreshold) 354 | { 355 | _device->VL53L1X_SetSignalThreshold(signalThreshold); 356 | } 357 | 358 | uint16_t SFEVL53L1X::getSignalThreshold() 359 | { 360 | uint16_t temp; 361 | _device->VL53L1X_GetSignalThreshold(&temp); 362 | return temp; 363 | } 364 | 365 | void SFEVL53L1X::setSigmaThreshold(uint16_t sigmaThreshold) 366 | { 367 | _device->VL53L1X_SetSigmaThreshold(sigmaThreshold); 368 | } 369 | 370 | uint16_t SFEVL53L1X::getSigmaThreshold() 371 | { 372 | uint16_t temp; 373 | _device->VL53L1X_GetSigmaThreshold(&temp); 374 | return temp; 375 | } 376 | 377 | void SFEVL53L1X::startTemperatureUpdate() 378 | { 379 | _device->VL53L1X_StartTemperatureUpdate(); 380 | } 381 | 382 | void SFEVL53L1X::calibrateOffset(uint16_t targetDistanceInMm) 383 | { 384 | int16_t offset = getOffset(); 385 | _device->VL53L1X_CalibrateOffset(targetDistanceInMm, &offset); 386 | } 387 | 388 | void SFEVL53L1X::calibrateXTalk(uint16_t targetDistanceInMm) 389 | { 390 | uint16_t xTalk = getXTalk(); 391 | _device->VL53L1X_CalibrateXtalk(targetDistanceInMm, &xTalk); 392 | }; 393 | 394 | bool SFEVL53L1X::setThresholdConfig(DetectionConfig *config) 395 | { 396 | return _device->VL53L1X_SetDistanceMode(config->distanceMode) == VL53L1_ERROR_NONE && 397 | _device->VL53L1X_SetDistanceThreshold(config->thresholdLow, config->thresholdHigh, 398 | (uint8_t)config->windowMode, (uint8_t)config->IntOnNoTarget) == VL53L1_ERROR_NONE; 399 | } 400 | 401 | bool SFEVL53L1X::getThresholdConfig(DetectionConfig *config) 402 | { 403 | uint16_t temp16 = 0; 404 | 405 | VL53L1X_ERROR error = _device->VL53L1X_GetDistanceMode(&temp16); 406 | if (error != 0) 407 | return false; 408 | else 409 | config->distanceMode = temp16; 410 | 411 | error = _device->VL53L1X_GetDistanceThresholdWindow(&temp16); 412 | if (error != 0) 413 | return false; 414 | else 415 | config->windowMode = temp16; 416 | 417 | config->IntOnNoTarget = 1; 418 | 419 | error = _device->VL53L1X_GetDistanceThresholdLow(&temp16); 420 | if (error != 0) 421 | return false; 422 | else 423 | config->thresholdLow = temp16; 424 | 425 | error = _device->VL53L1X_GetDistanceThresholdHigh(&temp16); 426 | if (error != 0) 427 | return false; 428 | else 429 | config->thresholdHigh = temp16; 430 | 431 | return true; 432 | } 433 | -------------------------------------------------------------------------------- /src/st_src/vl53l1_error_codes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017, STMicroelectronics - All Rights Reserved 3 | * 4 | * This file is part of VL53L1 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, VL53L1 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 VL53L1 API. 67 | * 68 | */ 69 | 70 | #ifndef _VL53L1_ERROR_CODES_H_ 71 | #define _VL53L1_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 VL53L1_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 VL53L1_Error; 88 | 89 | #define VL53L1_ERROR_NONE ((VL53L1_Error) 0) 90 | #define VL53L1_ERROR_CALIBRATION_WARNING ((VL53L1_Error) - 1) 91 | /*!< Warning invalid calibration data may be in used 92 | \a VL53L1_InitData() 93 | \a VL53L1_GetOffsetCalibrationData 94 | \a VL53L1_SetOffsetCalibrationData */ 95 | #define VL53L1_ERROR_MIN_CLIPPED ((VL53L1_Error) - 2) 96 | /*!< Warning parameter passed was clipped to min before to be applied */ 97 | 98 | #define VL53L1_ERROR_UNDEFINED ((VL53L1_Error) - 3) 99 | /*!< Unqualified error */ 100 | #define VL53L1_ERROR_INVALID_PARAMS ((VL53L1_Error) - 4) 101 | /*!< Parameter passed is invalid or out of range */ 102 | #define VL53L1_ERROR_NOT_SUPPORTED ((VL53L1_Error) - 5) 103 | /*!< Function is not supported in current mode or configuration */ 104 | #define VL53L1_ERROR_RANGE_ERROR ((VL53L1_Error) - 6) 105 | /*!< Device report a ranging error interrupt status */ 106 | #define VL53L1_ERROR_TIME_OUT ((VL53L1_Error) - 7) 107 | /*!< Aborted due to time out */ 108 | #define VL53L1_ERROR_MODE_NOT_SUPPORTED ((VL53L1_Error) - 8) 109 | /*!< Asked mode is not supported by the device */ 110 | #define VL53L1_ERROR_BUFFER_TOO_SMALL ((VL53L1_Error) - 9) 111 | /*!< ... */ 112 | #define VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL ((VL53L1_Error) - 10) 113 | /*!< Supplied buffer is larger than I2C supports */ 114 | #define VL53L1_ERROR_GPIO_NOT_EXISTING ((VL53L1_Error) - 11) 115 | /*!< User tried to setup a non-existing GPIO pin */ 116 | #define VL53L1_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED ((VL53L1_Error) - 12) 117 | /*!< unsupported GPIO functionality */ 118 | #define VL53L1_ERROR_CONTROL_INTERFACE ((VL53L1_Error) - 13) 119 | /*!< error reported from IO functions */ 120 | #define VL53L1_ERROR_INVALID_COMMAND ((VL53L1_Error) - 14) 121 | /*!< The command is not allowed in the current device state 122 | * (power down) */ 123 | #define VL53L1_ERROR_DIVISION_BY_ZERO ((VL53L1_Error) - 15) 124 | /*!< In the function a division by zero occurs */ 125 | #define VL53L1_ERROR_REF_SPAD_INIT ((VL53L1_Error) - 16) 126 | /*!< Error during reference SPAD initialization */ 127 | #define VL53L1_ERROR_GPH_SYNC_CHECK_FAIL ((VL53L1_Error) - 17) 128 | /*!< GPH sync interrupt check fail - API out of sync with device*/ 129 | #define VL53L1_ERROR_STREAM_COUNT_CHECK_FAIL ((VL53L1_Error) - 18) 130 | /*!< Stream count check fail - API out of sync with device */ 131 | #define VL53L1_ERROR_GPH_ID_CHECK_FAIL ((VL53L1_Error) - 19) 132 | /*!< GPH ID check fail - API out of sync with device */ 133 | #define VL53L1_ERROR_ZONE_STREAM_COUNT_CHECK_FAIL ((VL53L1_Error) - 20) 134 | /*!< Zone dynamic config stream count check failed - API out of sync */ 135 | #define VL53L1_ERROR_ZONE_GPH_ID_CHECK_FAIL ((VL53L1_Error) - 21) 136 | /*!< Zone dynamic config GPH ID check failed - API out of sync */ 137 | 138 | #define VL53L1_ERROR_XTALK_EXTRACTION_NO_SAMPLE_FAIL ((VL53L1_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 VL53L1_ERROR_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL ((VL53L1_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 VL53L1_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL ((VL53L1_Error) - 24) 152 | /*!< Thrown if there one of stages has no valid offset calibration 153 | * samples. A fatal error calibration not valid */ 154 | #define VL53L1_ERROR_OFFSET_CAL_NO_SPADS_ENABLED_FAIL ((VL53L1_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 VL53L1_ERROR_ZONE_CAL_NO_SAMPLE_FAIL ((VL53L1_Error) - 26) 159 | /*!< Thrown if then some of the zones have no valid samples 160 | * A fatal error calibration not valid */ 161 | 162 | #define VL53L1_ERROR_TUNING_PARM_KEY_MISMATCH ((VL53L1_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 | * #VL53L1_TUNINGPARM_KEY_TABLE_VERSION_DEFAULT 167 | * */ 168 | 169 | #define VL53L1_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS ((VL53L1_Error) - 28) 170 | /*!< Thrown if there are less than 5 good SPADs are available. */ 171 | #define VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH ((VL53L1_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 VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW ((VL53L1_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 VL53L1_WARNING_OFFSET_CAL_MISSING_SAMPLES ((VL53L1_Error) - 31) 182 | /*!< Thrown if there is less than the requested number of 183 | * valid samples. */ 184 | #define VL53L1_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH ((VL53L1_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 VL53L1_WARNING_OFFSET_CAL_RATE_TOO_HIGH ((VL53L1_Error) - 33) 189 | /*!< Thrown when VL53L1_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 VL53L1_WARNING_OFFSET_CAL_SPAD_COUNT_TOO_LOW ((VL53L1_Error) - 34) 193 | /*!< Thrown when VL53L1_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 VL53L1_WARNING_ZONE_CAL_MISSING_SAMPLES ((VL53L1_Error) - 35) 199 | /*!< Thrown if one of more of the zones have less than 200 | the requested number of valid samples */ 201 | #define VL53L1_WARNING_ZONE_CAL_SIGMA_TOO_HIGH ((VL53L1_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 VL53L1_WARNING_ZONE_CAL_RATE_TOO_HIGH ((VL53L1_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 VL53L1_WARNING_XTALK_MISSING_SAMPLES ((VL53L1_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 VL53L1_WARNING_XTALK_NO_SAMPLES_FOR_GRADIENT ((VL53L1_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 VL53L1_WARNING_XTALK_SIGMA_LIMIT_FOR_GRADIENT ((VL53L1_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 VL53L1_ERROR_NOT_IMPLEMENTED ((VL53L1_Error) - 41) 239 | /*!< Tells requested functionality has not been implemented yet or 240 | * not compatible with the device */ 241 | #define VL53L1_ERROR_PLATFORM_SPECIFIC_START ((VL53L1_Error) - 60) 242 | /*!< Tells the starting code for platform */ 243 | /** @} VL53L1_define_Error_group */ 244 | 245 | 246 | #ifdef __cplusplus 247 | } 248 | #endif 249 | 250 | 251 | #endif /* _VL53L1_ERROR_CODES_H_ */ 252 | -------------------------------------------------------------------------------- /src/st_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 "vl53l1_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 SOFT_RESET 0x0000 59 | #define VL53L1_I2C_SLAVE__DEVICE_ADDRESS 0x0001 60 | #define VL53L1_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND 0x0008 61 | #define ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS 0x0016 62 | #define ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS 0x0018 63 | #define ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS 0x001A 64 | #define ALGO__PART_TO_PART_RANGE_OFFSET_MM 0x001E 65 | #define MM_CONFIG__INNER_OFFSET_MM 0x0020 66 | #define MM_CONFIG__OUTER_OFFSET_MM 0x0022 67 | #define GPIO_HV_MUX__CTRL 0x0030 68 | #define GPIO__TIO_HV_STATUS 0x0031 69 | #define SYSTEM__INTERRUPT_CONFIG_GPIO 0x0046 70 | #define PHASECAL_CONFIG__TIMEOUT_MACROP 0x004B 71 | #define RANGE_CONFIG__TIMEOUT_MACROP_A_HI 0x005E 72 | #define RANGE_CONFIG__VCSEL_PERIOD_A 0x0060 73 | #define RANGE_CONFIG__VCSEL_PERIOD_B 0x0063 74 | #define RANGE_CONFIG__TIMEOUT_MACROP_B_HI 0x0061 75 | #define RANGE_CONFIG__TIMEOUT_MACROP_B_LO 0x0062 76 | #define RANGE_CONFIG__SIGMA_THRESH 0x0064 77 | #define RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS 0x0066 78 | #define RANGE_CONFIG__VALID_PHASE_HIGH 0x0069 79 | #define VL53L1_SYSTEM__INTERMEASUREMENT_PERIOD 0x006C 80 | #define SYSTEM__THRESH_HIGH 0x0072 81 | #define SYSTEM__THRESH_LOW 0x0074 82 | #define SD_CONFIG__WOI_SD0 0x0078 83 | #define SD_CONFIG__INITIAL_PHASE_SD0 0x007A 84 | #define ROI_CONFIG__USER_ROI_CENTRE_SPAD 0x007F 85 | #define ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE 0x0080 86 | #define SYSTEM__SEQUENCE_CONFIG 0x0081 87 | #define VL53L1_SYSTEM__GROUPED_PARAMETER_HOLD 0x0082 88 | #define SYSTEM__INTERRUPT_CLEAR 0x0086 89 | #define SYSTEM__MODE_START 0x0087 90 | #define VL53L1_RESULT__RANGE_STATUS 0x0089 91 | #define VL53L1_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0 0x008C 92 | #define RESULT__AMBIENT_COUNT_RATE_MCPS_SD 0x0090 93 | #define VL53L1_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 0x0096 94 | #define VL53L1_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0 0x0098 95 | #define VL53L1_RESULT__OSC_CALIBRATE_VAL 0x00DE 96 | #define VL53L1_FIRMWARE__SYSTEM_STATUS 0x00E5 97 | #define VL53L1_IDENTIFICATION__MODEL_ID 0x010F 98 | #define VL53L1_ROI_CONFIG__MODE_ROI_CENTRE_SPAD 0x013E 99 | 100 | 101 | #define VL53L1X_DEFAULT_DEVICE_ADDRESS 0x52 102 | 103 | /**************************************** 104 | * PRIVATE define do not edit 105 | ****************************************/ 106 | 107 | /** 108 | * @brief defines SW Version 109 | */ 110 | typedef struct { 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 | uint8_t I2cDevAddr; 121 | TwoWire *I2cHandle; 122 | 123 | } VL53L1_Dev_t; 124 | 125 | typedef VL53L1_Dev_t *VL53L1_DEV; 126 | 127 | 128 | /* Classes -------------------------------------------------------------------*/ 129 | /** Class representing a VL53L1 sensor component 130 | */ 131 | class VL53L1X : public RangeSensor 132 | { 133 | public: 134 | /** Constructor 135 | * @param[in] &i2c device I2C to be used for communication 136 | * @param[in] &pin_gpio1 pin Mbed InterruptIn PinName to be used as component GPIO_1 INT 137 | * @param[in] DevAddr device address, 0x52 by default 138 | */ 139 | VL53L1X(TwoWire *i2c, int pin, int pin_gpio1) : RangeSensor(), dev_i2c(i2c), gpio0(pin), gpio1Int(pin_gpio1) 140 | { 141 | MyDevice.I2cDevAddr=VL53L1X_DEFAULT_DEVICE_ADDRESS; 142 | MyDevice.I2cHandle = i2c; 143 | Device = &MyDevice; 144 | if(gpio0 >= 0) 145 | { 146 | pinMode(gpio0, OUTPUT); 147 | } 148 | } 149 | 150 | /** Destructor 151 | */ 152 | virtual ~VL53L1X(){} 153 | /* warning: VL53L1 class inherits from GenericSensor, RangeSensor and LightSensor, that haven`t a destructor. 154 | The warning should request to introduce a virtual destructor to make sure to delete the object */ 155 | 156 | /*** Interface Methods ***/ 157 | /*** High level API ***/ 158 | /** 159 | * @brief PowerOn the sensor 160 | * @return void 161 | */ 162 | /* turns on the sensor */ 163 | virtual void VL53L1_On(void) 164 | { 165 | if(gpio0 >= 0) 166 | { 167 | digitalWrite(gpio0, HIGH); 168 | } 169 | delay(10); 170 | } 171 | 172 | /** 173 | * @brief PowerOff the sensor 174 | * @return void 175 | */ 176 | /* turns off the sensor */ 177 | virtual void VL53L1_Off(void) 178 | { 179 | if(gpio0 >= 0) 180 | { 181 | digitalWrite(gpio0, LOW); 182 | } 183 | delay(10); 184 | } 185 | 186 | /** 187 | * @brief Initialize the sensor with default values 188 | * @return 0 on Success 189 | */ 190 | 191 | VL53L1X_ERROR InitSensor(uint8_t address){ 192 | VL53L1X_ERROR status = 0; 193 | uint8_t sensorState = 0; 194 | VL53L1_Off(); 195 | VL53L1_On(); 196 | status = VL53L1X_SetI2CAddress(address); 197 | 198 | #ifdef DEBUG_MODE 199 | uint8_t byteData; 200 | uint16_t wordData; 201 | status = VL53L1_RdByte(Device, 0x010F, &byteData); 202 | Serial.println("VL53L1X Model_ID: " + String(byteData)); 203 | status = VL53L1_RdByte(Device, 0x0110, &byteData); 204 | Serial.println("VL53L1X Module_Type: " + String(byteData)); 205 | status = VL53L1_RdWord(Device, 0x010F, &wordData); 206 | Serial.println("VL53L1X: " + String(wordData)); 207 | #endif 208 | 209 | 210 | while (!sensorState && !status){ 211 | status = VL53L1X_BootState(&sensorState); 212 | delay(2); 213 | } 214 | if(!status){ 215 | status = VL53L1X_SensorInit(); 216 | } 217 | return status; 218 | } 219 | 220 | 221 | 222 | /** 223 | * 224 | * @brief One time device initialization 225 | * @param void 226 | * @return 0 on success, @a #CALIBRATION_WARNING if failed 227 | */ 228 | virtual int Init() 229 | { 230 | return VL53L1X_SensorInit(); 231 | } 232 | 233 | 234 | 235 | /* Read function of the ID device */ 236 | virtual int ReadID(){ 237 | uint16_t sensorId; 238 | VL53L1X_GetSensorId(&sensorId); 239 | if (sensorId == 0xEEAC) 240 | return 0; 241 | return -1; 242 | } 243 | 244 | 245 | 246 | /** 247 | * @brief Get ranging result and only that 248 | * @param pRange_mm Pointer to range distance 249 | * @return 0 on success 250 | */ 251 | int GetDistance(uint32_t *piData) 252 | { 253 | int status; 254 | uint16_t distance; 255 | status = VL53L1X_GetDistance(&distance); 256 | *piData = (uint32_t) distance; 257 | return status; 258 | } 259 | 260 | 261 | /* VL53L1X_api.h functions */ 262 | 263 | 264 | 265 | /** 266 | * @brief This function returns the SW driver version 267 | */ 268 | VL53L1X_ERROR VL53L1X_GetSWVersion(VL53L1X_Version_t *pVersion); 269 | 270 | /** 271 | * @brief This function sets the sensor I2C address used in case multiple devices application, default address 0x52 272 | */ 273 | VL53L1X_ERROR VL53L1X_SetI2CAddress(uint8_t new_address); 274 | 275 | /** 276 | * @brief This function loads the 135 bytes default values to initialize the sensor. 277 | * @param dev Device address 278 | * @return 0:success, != 0:failed 279 | */ 280 | VL53L1X_ERROR VL53L1X_SensorInit(); 281 | 282 | /** 283 | * @brief This function clears the interrupt, to be called after a ranging data reading 284 | * to arm the interrupt for the next data ready event. 285 | */ 286 | VL53L1X_ERROR VL53L1X_ClearInterrupt(); 287 | 288 | /** 289 | * @brief This function programs the interrupt polarity\n 290 | * 1=active high (default), 0=active low 291 | */ 292 | VL53L1X_ERROR VL53L1X_SetInterruptPolarity(uint8_t IntPol); 293 | 294 | /** 295 | * @brief This function returns the current interrupt polarity\n 296 | * 1=active high (default), 0=active low 297 | */ 298 | VL53L1X_ERROR VL53L1X_GetInterruptPolarity(uint8_t *pIntPol); 299 | 300 | /** 301 | * @brief This function starts the ranging distance operation\n 302 | * 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 303 | * 1=active high (default), 0=active low, use SetInterruptPolarity() to change the interrupt polarity if required. 304 | */ 305 | VL53L1X_ERROR VL53L1X_StartRanging(); 306 | 307 | /** 308 | * @brief This function starts a one-shot ranging distance operation\n 309 | */ 310 | VL53L1X_ERROR VL53L1X_StartOneshotRanging(); 311 | 312 | /** 313 | * @brief This function stops the ranging. 314 | */ 315 | VL53L1X_ERROR VL53L1X_StopRanging(); 316 | 317 | /** 318 | * @brief This function checks if the new ranging data is available by polling the dedicated register. 319 | * @param : isDataReady==0 -> not ready; isDataReady==1 -> ready 320 | */ 321 | VL53L1X_ERROR VL53L1X_CheckForDataReady(uint8_t *isDataReady); 322 | 323 | /** 324 | * @brief This function programs the timing budget in ms. 325 | * Predefined values = 15, 20, 33, 50, 100(default), 200, 500. 326 | */ 327 | VL53L1X_ERROR VL53L1X_SetTimingBudgetInMs(uint16_t TimingBudgetInMs); 328 | 329 | /** 330 | * @brief This function returns the current timing budget in ms. 331 | */ 332 | VL53L1X_ERROR VL53L1X_GetTimingBudgetInMs(uint16_t *pTimingBudgetInMs); 333 | 334 | /** 335 | * @brief This function programs the distance mode (1=short, 2=long(default)). 336 | * Short mode max distance is limited to 1.3 m but better ambient immunity.\n 337 | * Long mode can range up to 4 m in the dark with 200 ms timing budget. 338 | */ 339 | VL53L1X_ERROR VL53L1X_SetDistanceMode(uint16_t DistanceMode); 340 | 341 | /** 342 | * @brief This function returns the current distance mode (1=short, 2=long). 343 | */ 344 | VL53L1X_ERROR VL53L1X_GetDistanceMode(uint16_t *pDistanceMode); 345 | 346 | /** 347 | * @brief This function programs the Intermeasurement period in ms\n 348 | * Intermeasurement period must be >/= timing budget. This condition is not checked by the API, 349 | * the customer has the duty to check the condition. Default = 100 ms 350 | */ 351 | VL53L1X_ERROR VL53L1X_SetInterMeasurementInMs(uint16_t InterMeasurementInMs); 352 | 353 | /** 354 | * @brief This function returns the Intermeasurement period in ms. 355 | */ 356 | VL53L1X_ERROR VL53L1X_GetInterMeasurementInMs(uint16_t * pIM); 357 | 358 | /** 359 | * @brief This function returns the boot state of the device (1:booted, 0:not booted) 360 | */ 361 | VL53L1X_ERROR VL53L1X_BootState(uint8_t *state); 362 | 363 | /** 364 | * @brief This function returns the sensor id, sensor Id must be 0xEEAC 365 | */ 366 | VL53L1X_ERROR VL53L1X_GetSensorId(uint16_t *id); 367 | 368 | /** 369 | * @brief This function returns the distance measured by the sensor in mm 370 | */ 371 | VL53L1X_ERROR VL53L1X_GetDistance(uint16_t *distance); 372 | 373 | /** 374 | * @brief This function returns the returned signal per SPAD in kcps/SPAD. 375 | * With kcps stands for Kilo Count Per Second 376 | */ 377 | VL53L1X_ERROR VL53L1X_GetSignalPerSpad(uint16_t *signalPerSp); 378 | 379 | /** 380 | * @brief This function returns the ambient per SPAD in kcps/SPAD 381 | */ 382 | VL53L1X_ERROR VL53L1X_GetAmbientPerSpad(uint16_t *amb); 383 | 384 | /** 385 | * @brief This function returns the returned signal in kcps. 386 | */ 387 | VL53L1X_ERROR VL53L1X_GetSignalRate(uint16_t *signalRate); 388 | 389 | /** 390 | * @brief This function returns the current number of enabled SPADs 391 | */ 392 | VL53L1X_ERROR VL53L1X_GetSpadNb(uint16_t *spNb); 393 | 394 | /** 395 | * @brief This function returns the ambient rate in kcps 396 | */ 397 | VL53L1X_ERROR VL53L1X_GetAmbientRate(uint16_t *ambRate); 398 | 399 | /** 400 | * @brief This function returns the ranging status error \n 401 | * (0:no error, 1:sigma failed, 2:signal failed, ..., 7:wrap-around) 402 | */ 403 | VL53L1X_ERROR VL53L1X_GetRangeStatus(uint8_t *rangeStatus); 404 | 405 | /** 406 | * @brief This function programs the offset correction in mm 407 | * @param OffsetValue:the offset correction value to program in mm 408 | */ 409 | VL53L1X_ERROR VL53L1X_SetOffset(int16_t OffsetValue); 410 | 411 | /** 412 | * @brief This function returns the programmed offset correction value in mm 413 | */ 414 | VL53L1X_ERROR VL53L1X_GetOffset(int16_t *Offset); 415 | 416 | /** 417 | * @brief This function programs the xtalk correction value in cps (Count Per Second).\n 418 | * This is the number of photons reflected back from the cover glass in cps. 419 | */ 420 | VL53L1X_ERROR VL53L1X_SetXtalk(uint16_t XtalkValue); 421 | 422 | /** 423 | * @brief This function returns the current programmed xtalk correction value in cps 424 | */ 425 | VL53L1X_ERROR VL53L1X_GetXtalk(uint16_t *Xtalk); 426 | 427 | /** 428 | * @brief This function programs the threshold detection mode\n 429 | * Example:\n 430 | * VL53L1X_SetDistanceThreshold(dev,100,300,0,1): Below 100 \n 431 | * VL53L1X_SetDistanceThreshold(dev,100,300,1,1): Above 300 \n 432 | * VL53L1X_SetDistanceThreshold(dev,100,300,2,1): Out of window \n 433 | * VL53L1X_SetDistanceThreshold(dev,100,300,3,1): In window \n 434 | * @param dev : device address 435 | * @param ThreshLow(in mm) : the threshold under which one the device raises an interrupt if Window = 0 436 | * @param ThreshHigh(in mm) : the threshold above which one the device raises an interrupt if Window = 1 437 | * @param Window detection mode : 0=below, 1=above, 2=out, 3=in 438 | * @param IntOnNoTarget = 1 (No longer used - just use 1) 439 | */ 440 | VL53L1X_ERROR VL53L1X_SetDistanceThreshold(uint16_t ThreshLow, 441 | uint16_t ThreshHigh, uint8_t Window, 442 | uint8_t IntOnNoTarget); 443 | 444 | /** 445 | * @brief This function returns the window detection mode (0=below; 1=above; 2=out; 3=in) 446 | */ 447 | VL53L1X_ERROR VL53L1X_GetDistanceThresholdWindow(uint16_t *window); 448 | 449 | /** 450 | * @brief This function returns the low threshold in mm 451 | */ 452 | VL53L1X_ERROR VL53L1X_GetDistanceThresholdLow(uint16_t *low); 453 | 454 | /** 455 | * @brief This function returns the high threshold in mm 456 | */ 457 | VL53L1X_ERROR VL53L1X_GetDistanceThresholdHigh(uint16_t *high); 458 | 459 | /** 460 | * @brief This function programs the ROI (Region of Interest)\n 461 | * The ROI position is centered, only the ROI size can be reprogrammed.\n 462 | * The smallest acceptable ROI size = 4\n 463 | * @param X:ROI Width; Y=ROI Height 464 | */ 465 | VL53L1X_ERROR VL53L1X_SetROI(uint8_t X, uint8_t Y, uint8_t opticalCenter); 466 | 467 | /** 468 | *@brief This function returns width X and height Y 469 | */ 470 | VL53L1X_ERROR VL53L1X_GetROI_XY(uint16_t *ROI_X, uint16_t *ROI_Y); 471 | 472 | /** 473 | * @brief This function programs a new signal threshold in kcps (default=1024 kcps\n 474 | */ 475 | VL53L1X_ERROR VL53L1X_SetSignalThreshold(uint16_t signal); 476 | 477 | /** 478 | * @brief This function returns the current signal threshold in kcps 479 | */ 480 | VL53L1X_ERROR VL53L1X_GetSignalThreshold(uint16_t *signal); 481 | 482 | /** 483 | * @brief This function programs a new sigma threshold in mm (default=15 mm) 484 | */ 485 | VL53L1X_ERROR VL53L1X_SetSigmaThreshold(uint16_t sigma); 486 | 487 | /** 488 | * @brief This function returns the current sigma threshold in mm 489 | */ 490 | VL53L1X_ERROR VL53L1X_GetSigmaThreshold(uint16_t *signal); 491 | 492 | /** 493 | * @brief This function performs the temperature calibration. 494 | * It is recommended to call this function any time the temperature might have changed by more than 8 deg C 495 | * without sensor ranging activity for an extended period. 496 | */ 497 | VL53L1X_ERROR VL53L1X_StartTemperatureUpdate(); 498 | 499 | 500 | /* VL53L1X_calibration.h functions */ 501 | 502 | /** 503 | * @brief This function performs the offset calibration.\n 504 | * The function returns the offset value found and programs the offset compensation into the device. 505 | * @param TargetDistInMm target distance in mm, ST recommended 100 mm 506 | * Target reflectance = grey17% 507 | * @return 0:success, !=0: failed 508 | * @return offset pointer contains the offset found in mm 509 | */ 510 | int8_t VL53L1X_CalibrateOffset(uint16_t TargetDistInMm, int16_t *offset); 511 | 512 | /** 513 | * @brief This function performs the xtalk calibration.\n 514 | * The function returns the xtalk value found and programs the xtalk compensation to the device 515 | * @param TargetDistInMm target distance in mm\n 516 | * The target distance : the distance where the sensor start to "under range"\n 517 | * due to the influence of the photons reflected back from the cover glass becoming strong\n 518 | * It's also called inflection point\n 519 | * Target reflectance = grey 17% 520 | * @return 0: success, !=0: failed 521 | * @return xtalk pointer contains the xtalk value found in cps (number of photons in count per second) 522 | */ 523 | int8_t VL53L1X_CalibrateXtalk(uint16_t TargetDistInMm, uint16_t *xtalk); 524 | 525 | 526 | 527 | 528 | 529 | 530 | protected: 531 | 532 | 533 | /* Write and read functions from I2C */ 534 | 535 | VL53L1X_ERROR VL53L1_WrByte(VL53L1_DEV dev, uint16_t index, uint8_t data); 536 | VL53L1X_ERROR VL53L1_WrWord(VL53L1_DEV dev, uint16_t index, uint16_t data); 537 | VL53L1X_ERROR VL53L1_WrDWord(VL53L1_DEV dev, uint16_t index, uint32_t data); 538 | VL53L1X_ERROR VL53L1_RdByte(VL53L1_DEV dev, uint16_t index, uint8_t *data); 539 | VL53L1X_ERROR VL53L1_RdWord(VL53L1_DEV dev, uint16_t index, uint16_t *data); 540 | VL53L1X_ERROR VL53L1_RdDWord(VL53L1_DEV dev, uint16_t index, uint32_t *data); 541 | VL53L1X_ERROR VL53L1_UpdateByte(VL53L1_DEV dev, uint16_t index, uint8_t AndData, uint8_t OrData); 542 | 543 | VL53L1X_ERROR VL53L1_WriteMulti(VL53L1_DEV Dev, uint16_t index, uint8_t *pdata, uint32_t count); 544 | VL53L1X_ERROR VL53L1_ReadMulti(VL53L1_DEV Dev, uint16_t index, uint8_t *pdata, uint32_t count); 545 | 546 | VL53L1X_ERROR VL53L1_I2CWrite(uint8_t dev, uint16_t index, uint8_t *data, uint16_t number_of_bytes); 547 | VL53L1X_ERROR VL53L1_I2CRead(uint8_t dev, uint16_t index, uint8_t *data, uint16_t number_of_bytes); 548 | VL53L1X_ERROR VL53L1_GetTickCount(uint32_t *ptick_count_ms); 549 | VL53L1X_ERROR VL53L1_WaitUs(VL53L1_Dev_t *pdev, int32_t wait_us); 550 | VL53L1X_ERROR VL53L1_WaitMs(VL53L1_Dev_t *pdev, int32_t wait_ms); 551 | 552 | VL53L1X_ERROR VL53L1_WaitValueMaskEx(VL53L1_Dev_t *pdev, uint32_t timeout_ms, uint16_t index, uint8_t value, uint8_t mask, uint32_t poll_delay_ms); 553 | 554 | 555 | 556 | public: 557 | 558 | /* IO Device */ 559 | TwoWire *dev_i2c; 560 | 561 | protected: 562 | 563 | /* Digital out pin */ 564 | int gpio0; 565 | int gpio1Int; 566 | /* Device data */ 567 | VL53L1_Dev_t MyDevice; 568 | VL53L1_DEV Device; 569 | }; 570 | 571 | 572 | #endif /* _VL53L1X_CLASS_H_ */ 573 | -------------------------------------------------------------------------------- /src/st_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 | #define ALGO__PART_TO_PART_RANGE_OFFSET_MM 0x001E 44 | #define MM_CONFIG__INNER_OFFSET_MM 0x0020 45 | #define MM_CONFIG__OUTER_OFFSET_MM 0x0022 46 | 47 | //#define DEBUG_MODE 48 | 49 | const uint8_t VL51L1X_DEFAULT_CONFIGURATION[] = { 50 | 0x00, /* 0x2d : set bit 2 and 5 to 1 for fast plus mode (1MHz I2C), else don't touch */ 51 | 0x01, /* 0x2e : bit 0 if I2C pulled up at 1.8V, else set bit 0 to 1 (pull up at AVDD) */ 52 | 0x01, /* 0x2f : bit 0 if GPIO pulled up at 1.8V, else set bit 0 to 1 (pull up at AVDD) */ 53 | 0x01, /* 0x30 : set bit 4 to 0 for active high interrupt and 1 for active low (bits 3:0 must be 0x1), use SetInterruptPolarity() */ 54 | 0x02, /* 0x31 : bit 1 = interrupt depending on the polarity, use CheckForDataReady() */ 55 | 0x00, /* 0x32 : not user-modifiable */ 56 | 0x02, /* 0x33 : not user-modifiable */ 57 | 0x08, /* 0x34 : not user-modifiable */ 58 | 0x00, /* 0x35 : not user-modifiable */ 59 | 0x08, /* 0x36 : not user-modifiable */ 60 | 0x10, /* 0x37 : not user-modifiable */ 61 | 0x01, /* 0x38 : not user-modifiable */ 62 | 0x01, /* 0x39 : not user-modifiable */ 63 | 0x00, /* 0x3a : not user-modifiable */ 64 | 0x00, /* 0x3b : not user-modifiable */ 65 | 0x00, /* 0x3c : not user-modifiable */ 66 | 0x00, /* 0x3d : not user-modifiable */ 67 | 0xff, /* 0x3e : not user-modifiable */ 68 | 0x00, /* 0x3f : not user-modifiable */ 69 | 0x0F, /* 0x40 : not user-modifiable */ 70 | 0x00, /* 0x41 : not user-modifiable */ 71 | 0x00, /* 0x42 : not user-modifiable */ 72 | 0x00, /* 0x43 : not user-modifiable */ 73 | 0x00, /* 0x44 : not user-modifiable */ 74 | 0x00, /* 0x45 : not user-modifiable */ 75 | 0x20, /* 0x46 : interrupt configuration 0->level low detection, 1-> level high, 2-> Out of window, 3->In window, 0x20-> New sample ready , TBC */ 76 | 0x0b, /* 0x47 : not user-modifiable */ 77 | 0x00, /* 0x48 : not user-modifiable */ 78 | 0x00, /* 0x49 : not user-modifiable */ 79 | 0x02, /* 0x4a : not user-modifiable */ 80 | 0x0a, /* 0x4b : not user-modifiable */ 81 | 0x21, /* 0x4c : not user-modifiable */ 82 | 0x00, /* 0x4d : not user-modifiable */ 83 | 0x00, /* 0x4e : not user-modifiable */ 84 | 0x05, /* 0x4f : not user-modifiable */ 85 | 0x00, /* 0x50 : not user-modifiable */ 86 | 0x00, /* 0x51 : not user-modifiable */ 87 | 0x00, /* 0x52 : not user-modifiable */ 88 | 0x00, /* 0x53 : not user-modifiable */ 89 | 0xc8, /* 0x54 : not user-modifiable */ 90 | 0x00, /* 0x55 : not user-modifiable */ 91 | 0x00, /* 0x56 : not user-modifiable */ 92 | 0x38, /* 0x57 : not user-modifiable */ 93 | 0xff, /* 0x58 : not user-modifiable */ 94 | 0x01, /* 0x59 : not user-modifiable */ 95 | 0x00, /* 0x5a : not user-modifiable */ 96 | 0x08, /* 0x5b : not user-modifiable */ 97 | 0x00, /* 0x5c : not user-modifiable */ 98 | 0x00, /* 0x5d : not user-modifiable */ 99 | 0x01, /* 0x5e : not user-modifiable */ 100 | 0xdb, /* 0x5f : not user-modifiable */ 101 | 0x0f, /* 0x60 : not user-modifiable */ 102 | 0x01, /* 0x61 : not user-modifiable */ 103 | 0xf1, /* 0x62 : not user-modifiable */ 104 | 0x0d, /* 0x63 : not user-modifiable */ 105 | 0x01, /* 0x64 : Sigma threshold MSB (mm in 14.2 format for MSB+LSB), use SetSigmaThreshold(), default value 90 mm */ 106 | 0x68, /* 0x65 : Sigma threshold LSB */ 107 | 0x00, /* 0x66 : Min count Rate MSB (MCPS in 9.7 format for MSB+LSB), use SetSignalThreshold() */ 108 | 0x80, /* 0x67 : Min count Rate LSB */ 109 | 0x08, /* 0x68 : not user-modifiable */ 110 | 0xb8, /* 0x69 : not user-modifiable */ 111 | 0x00, /* 0x6a : not user-modifiable */ 112 | 0x00, /* 0x6b : not user-modifiable */ 113 | 0x00, /* 0x6c : Intermeasurement period MSB, 32 bits register, use SetIntermeasurementInMs() */ 114 | 0x00, /* 0x6d : Intermeasurement period */ 115 | 0x0f, /* 0x6e : Intermeasurement period */ 116 | 0x89, /* 0x6f : Intermeasurement period LSB */ 117 | 0x00, /* 0x70 : not user-modifiable */ 118 | 0x00, /* 0x71 : not user-modifiable */ 119 | 0x00, /* 0x72 : distance threshold high MSB (in mm, MSB+LSB), use SetD:tanceThreshold() */ 120 | 0x00, /* 0x73 : distance threshold high LSB */ 121 | 0x00, /* 0x74 : distance threshold low MSB ( in mm, MSB+LSB), use SetD:tanceThreshold() */ 122 | 0x00, /* 0x75 : distance threshold low LSB */ 123 | 0x00, /* 0x76 : not user-modifiable */ 124 | 0x01, /* 0x77 : not user-modifiable */ 125 | 0x0f, /* 0x78 : not user-modifiable */ 126 | 0x0d, /* 0x79 : not user-modifiable */ 127 | 0x0e, /* 0x7a : not user-modifiable */ 128 | 0x0e, /* 0x7b : not user-modifiable */ 129 | 0x00, /* 0x7c : not user-modifiable */ 130 | 0x00, /* 0x7d : not user-modifiable */ 131 | 0x02, /* 0x7e : not user-modifiable */ 132 | 0xc7, /* 0x7f : ROI center, use SetROI() */ 133 | 0xff, /* 0x80 : XY ROI (X=Width, Y=Height), use SetROI() */ 134 | 0x9B, /* 0x81 : not user-modifiable */ 135 | 0x00, /* 0x82 : not user-modifiable */ 136 | 0x00, /* 0x83 : not user-modifiable */ 137 | 0x00, /* 0x84 : not user-modifiable */ 138 | 0x01, /* 0x85 : not user-modifiable */ 139 | 0x00, /* 0x86 : clear interrupt, use ClearInterrupt() */ 140 | 0x00 /* 0x87 : start ranging, use StartRanging() or StopRanging(), If you want an automatic start after VL53L1X_init() call, put 0x40 in location 0x87 */ 141 | }; 142 | 143 | /* VL53L1X_api.h functions */ 144 | 145 | VL53L1X_ERROR VL53L1X::VL53L1X_GetSWVersion(VL53L1X_Version_t *pVersion) 146 | { 147 | VL53L1X_ERROR Status = 0; 148 | 149 | pVersion->major = VL53L1X_IMPLEMENTATION_VER_MAJOR; 150 | pVersion->minor = VL53L1X_IMPLEMENTATION_VER_MINOR; 151 | pVersion->build = VL53L1X_IMPLEMENTATION_VER_SUB; 152 | pVersion->revision = VL53L1X_IMPLEMENTATION_VER_REVISION; 153 | return Status; 154 | } 155 | 156 | VL53L1X_ERROR VL53L1X::VL53L1X_SetI2CAddress(uint8_t new_address) 157 | { 158 | VL53L1X_ERROR status = 0; 159 | 160 | status = VL53L1_WrByte(Device, VL53L1_I2C_SLAVE__DEVICE_ADDRESS, new_address >> 1); 161 | Device->I2cDevAddr = new_address; 162 | 163 | return status; 164 | } 165 | 166 | VL53L1X_ERROR VL53L1X::VL53L1X_SensorInit() 167 | { 168 | VL53L1X_ERROR status = 0; 169 | uint8_t Addr = 0x00, dataReady = 0, timeout = 0; 170 | 171 | for (Addr = 0x2D; Addr <= 0x87; Addr++) 172 | { 173 | status = VL53L1_WrByte(Device, Addr, VL51L1X_DEFAULT_CONFIGURATION[Addr - 0x2D]); 174 | } 175 | status = VL53L1X_StartRanging(); 176 | 177 | //We need to wait at least the default intermeasurement period of 103ms before dataready will occur 178 | //But if a unit has already been powered and polling, it may happen much faster 179 | while (dataReady == 0) 180 | { 181 | status = VL53L1X_CheckForDataReady(&dataReady); 182 | if (timeout++ > 150) 183 | return VL53L1_ERROR_TIME_OUT; 184 | delay(1); 185 | } 186 | status = VL53L1X_ClearInterrupt(); 187 | status = VL53L1X_StopRanging(); 188 | status = VL53L1_WrByte(Device, VL53L1_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND, 0x09); /* two bounds VHV */ 189 | status = VL53L1_WrByte(Device, 0x0B, 0); /* start VHV from the previous temperature */ 190 | return status; 191 | } 192 | 193 | VL53L1X_ERROR VL53L1X::VL53L1X_ClearInterrupt() 194 | { 195 | VL53L1X_ERROR status = 0; 196 | 197 | status = VL53L1_WrByte(Device, SYSTEM__INTERRUPT_CLEAR, 0x01); 198 | return status; 199 | } 200 | 201 | VL53L1X_ERROR VL53L1X::VL53L1X_SetInterruptPolarity(uint8_t NewPolarity) 202 | { 203 | uint8_t Temp; 204 | VL53L1X_ERROR status = 0; 205 | 206 | status = VL53L1_RdByte(Device, GPIO_HV_MUX__CTRL, &Temp); 207 | Temp = Temp & 0xEF; 208 | status = VL53L1_WrByte(Device, GPIO_HV_MUX__CTRL, Temp | (!(NewPolarity & 1)) << 4); 209 | return status; 210 | } 211 | 212 | VL53L1X_ERROR VL53L1X::VL53L1X_GetInterruptPolarity(uint8_t *pInterruptPolarity) 213 | { 214 | uint8_t Temp; 215 | VL53L1X_ERROR status = 0; 216 | 217 | status = VL53L1_RdByte(Device, GPIO_HV_MUX__CTRL, &Temp); 218 | Temp = Temp & 0x10; 219 | *pInterruptPolarity = !(Temp >> 4); 220 | return status; 221 | } 222 | 223 | VL53L1X_ERROR VL53L1X::VL53L1X_StartRanging() 224 | { 225 | VL53L1X_ERROR status = 0; 226 | VL53L1_WrByte(Device, SYSTEM__INTERRUPT_CLEAR, 0x01); /* clear interrupt trigger */ 227 | status = VL53L1_WrByte(Device, SYSTEM__MODE_START, 0x40); /* Enable VL53L1X */ 228 | return status; 229 | } 230 | 231 | 232 | VL53L1X_ERROR VL53L1X::VL53L1X_StartOneshotRanging() 233 | { 234 | VL53L1X_ERROR status = 0; 235 | VL53L1_WrByte(Device, SYSTEM__INTERRUPT_CLEAR, 0x01); /* clear interrupt trigger */ 236 | status = VL53L1_WrByte(Device, SYSTEM__MODE_START, 0x10); /* Enable VL53L1X one-shot ranging */ 237 | return status; 238 | } 239 | 240 | 241 | VL53L1X_ERROR VL53L1X::VL53L1X_StopRanging() 242 | { 243 | VL53L1X_ERROR status = 0; 244 | 245 | status = VL53L1_WrByte(Device, SYSTEM__MODE_START, 0x00); /* Disable VL53L1X */ 246 | return status; 247 | } 248 | 249 | VL53L1X_ERROR VL53L1X::VL53L1X_CheckForDataReady(uint8_t *isDataReady) 250 | { 251 | uint8_t Temp; 252 | uint8_t IntPol; 253 | VL53L1X_ERROR status = 0; 254 | 255 | status = VL53L1X_GetInterruptPolarity(&IntPol); 256 | status = VL53L1_RdByte(Device, GPIO__TIO_HV_STATUS, &Temp); 257 | /* Read in the register to check if a new value is available */ 258 | if (status == 0) 259 | { 260 | if ((Temp & 1) == IntPol) 261 | *isDataReady = 1; 262 | else 263 | *isDataReady = 0; 264 | } 265 | return status; 266 | } 267 | 268 | VL53L1X_ERROR VL53L1X::VL53L1X_SetTimingBudgetInMs(uint16_t TimingBudgetInMs) 269 | { 270 | uint16_t DM; 271 | VL53L1X_ERROR status = 0; 272 | 273 | status = VL53L1X_GetDistanceMode(&DM); 274 | if (DM == 0) 275 | return 1; 276 | else if (DM == 1) 277 | { /* Short DistanceMode */ 278 | switch (TimingBudgetInMs) 279 | { 280 | case 15: /* only available in short distance mode */ 281 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 282 | 0x01D); 283 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 284 | 0x0027); 285 | break; 286 | case 20: 287 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 288 | 0x0051); 289 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 290 | 0x006E); 291 | break; 292 | case 33: 293 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 294 | 0x00D6); 295 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 296 | 0x006E); 297 | break; 298 | case 50: 299 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 300 | 0x1AE); 301 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 302 | 0x01E8); 303 | break; 304 | case 100: 305 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 306 | 0x02E1); 307 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 308 | 0x0388); 309 | break; 310 | case 200: 311 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 312 | 0x03E1); 313 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 314 | 0x0496); 315 | break; 316 | case 500: 317 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 318 | 0x0591); 319 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 320 | 0x05C1); 321 | break; 322 | default: 323 | status = 1; 324 | break; 325 | } 326 | } 327 | else 328 | { 329 | switch (TimingBudgetInMs) 330 | { 331 | case 20: 332 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 333 | 0x001E); 334 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 335 | 0x0022); 336 | break; 337 | case 33: 338 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 339 | 0x0060); 340 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 341 | 0x006E); 342 | break; 343 | case 50: 344 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 345 | 0x00AD); 346 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 347 | 0x00C6); 348 | break; 349 | case 100: 350 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 351 | 0x01CC); 352 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 353 | 0x01EA); 354 | break; 355 | case 200: 356 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 357 | 0x02D9); 358 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 359 | 0x02F8); 360 | break; 361 | case 500: 362 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, 363 | 0x048F); 364 | VL53L1_WrWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, 365 | 0x04A4); 366 | break; 367 | default: 368 | status = 1; 369 | break; 370 | } 371 | } 372 | return status; 373 | } 374 | 375 | VL53L1X_ERROR VL53L1X::VL53L1X_GetTimingBudgetInMs(uint16_t *pTimingBudget) 376 | { 377 | uint16_t Temp; 378 | VL53L1X_ERROR status = 0; 379 | 380 | status = VL53L1_RdWord(Device, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, &Temp); 381 | switch (Temp) 382 | { 383 | case 0x001D: 384 | *pTimingBudget = 15; 385 | break; 386 | case 0x0051: 387 | case 0x001E: 388 | *pTimingBudget = 20; 389 | break; 390 | case 0x00D6: 391 | case 0x0060: 392 | *pTimingBudget = 33; 393 | break; 394 | case 0x1AE: 395 | case 0x00AD: 396 | *pTimingBudget = 50; 397 | break; 398 | case 0x02E1: 399 | case 0x01CC: 400 | *pTimingBudget = 100; 401 | break; 402 | case 0x03E1: 403 | case 0x02D9: 404 | *pTimingBudget = 200; 405 | break; 406 | case 0x0591: 407 | case 0x048F: 408 | *pTimingBudget = 500; 409 | break; 410 | default: 411 | *pTimingBudget = 0; 412 | break; 413 | } 414 | return status; 415 | } 416 | 417 | VL53L1X_ERROR VL53L1X::VL53L1X_SetDistanceMode(uint16_t DM) 418 | { 419 | uint16_t TB; 420 | VL53L1X_ERROR status = 0; 421 | 422 | status = VL53L1X_GetTimingBudgetInMs(&TB); 423 | switch (DM) 424 | { 425 | case 1: 426 | status = VL53L1_WrByte(Device, PHASECAL_CONFIG__TIMEOUT_MACROP, 0x14); 427 | status = VL53L1_WrByte(Device, RANGE_CONFIG__VCSEL_PERIOD_A, 0x07); 428 | status = VL53L1_WrByte(Device, RANGE_CONFIG__VCSEL_PERIOD_B, 0x05); 429 | status = VL53L1_WrByte(Device, RANGE_CONFIG__VALID_PHASE_HIGH, 0x38); 430 | status = VL53L1_WrWord(Device, SD_CONFIG__WOI_SD0, 0x0705); 431 | status = VL53L1_WrWord(Device, SD_CONFIG__INITIAL_PHASE_SD0, 0x0606); 432 | break; 433 | case 2: 434 | status = VL53L1_WrByte(Device, PHASECAL_CONFIG__TIMEOUT_MACROP, 0x0A); 435 | status = VL53L1_WrByte(Device, RANGE_CONFIG__VCSEL_PERIOD_A, 0x0F); 436 | status = VL53L1_WrByte(Device, RANGE_CONFIG__VCSEL_PERIOD_B, 0x0D); 437 | status = VL53L1_WrByte(Device, RANGE_CONFIG__VALID_PHASE_HIGH, 0xB8); 438 | status = VL53L1_WrWord(Device, SD_CONFIG__WOI_SD0, 0x0F0D); 439 | status = VL53L1_WrWord(Device, SD_CONFIG__INITIAL_PHASE_SD0, 0x0E0E); 440 | break; 441 | default: 442 | break; 443 | } 444 | status = VL53L1X_SetTimingBudgetInMs(TB); 445 | return status; 446 | } 447 | 448 | VL53L1X_ERROR VL53L1X::VL53L1X_GetDistanceMode(uint16_t *DM) 449 | { 450 | uint8_t TempDM, status = 0; 451 | 452 | status = VL53L1_RdByte(Device, PHASECAL_CONFIG__TIMEOUT_MACROP, &TempDM); 453 | if (TempDM == 0x14) 454 | *DM = 1; 455 | if (TempDM == 0x0A) 456 | *DM = 2; 457 | return status; 458 | } 459 | 460 | VL53L1X_ERROR VL53L1X::VL53L1X_SetInterMeasurementInMs(uint16_t InterMeasMs) 461 | { 462 | uint16_t ClockPLL; 463 | VL53L1X_ERROR status = 0; 464 | 465 | status = VL53L1_RdWord(Device, VL53L1_RESULT__OSC_CALIBRATE_VAL, &ClockPLL); 466 | ClockPLL = ClockPLL & 0x3FF; 467 | VL53L1_WrDWord(Device, VL53L1_SYSTEM__INTERMEASUREMENT_PERIOD, 468 | (uint32_t)(ClockPLL * InterMeasMs * 1.075)); 469 | return status; 470 | } 471 | 472 | VL53L1X_ERROR VL53L1X::VL53L1X_GetInterMeasurementInMs(uint16_t *pIM) 473 | { 474 | uint16_t ClockPLL; 475 | VL53L1X_ERROR status = 0; 476 | uint32_t tmp; 477 | 478 | status = VL53L1_RdDWord(Device, VL53L1_SYSTEM__INTERMEASUREMENT_PERIOD, &tmp); 479 | *pIM = (uint16_t)tmp; 480 | status = VL53L1_RdWord(Device, VL53L1_RESULT__OSC_CALIBRATE_VAL, &ClockPLL); 481 | ClockPLL = ClockPLL & 0x3FF; 482 | *pIM = (uint16_t)(*pIM / (ClockPLL * 1.065)); 483 | return status; 484 | } 485 | 486 | VL53L1X_ERROR VL53L1X::VL53L1X_BootState(uint8_t *state) 487 | { 488 | VL53L1X_ERROR status = 0; 489 | uint8_t tmp = 0; 490 | 491 | status = VL53L1_RdByte(Device, VL53L1_FIRMWARE__SYSTEM_STATUS, &tmp); 492 | *state = tmp; 493 | return status; 494 | } 495 | 496 | VL53L1X_ERROR VL53L1X::VL53L1X_GetSensorId(uint16_t *sensorId) 497 | { 498 | VL53L1X_ERROR status = 0; 499 | uint16_t tmp = 0; 500 | 501 | status = VL53L1_RdWord(Device, VL53L1_IDENTIFICATION__MODEL_ID, &tmp); 502 | *sensorId = tmp; 503 | return status; 504 | } 505 | 506 | VL53L1X_ERROR VL53L1X::VL53L1X_GetDistance(uint16_t *distance) 507 | { 508 | VL53L1X_ERROR status = 0; 509 | uint16_t tmp; 510 | 511 | status = (VL53L1_RdWord(Device, 512 | VL53L1_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0, &tmp)); 513 | *distance = tmp; 514 | return status; 515 | } 516 | 517 | VL53L1X_ERROR VL53L1X::VL53L1X_GetSignalPerSpad(uint16_t *signalRate) 518 | { 519 | VL53L1X_ERROR status = 0; 520 | uint16_t SpNb = 1, signal; 521 | 522 | status = VL53L1_RdWord(Device, 523 | VL53L1_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0, &signal); 524 | status = VL53L1_RdWord(Device, 525 | VL53L1_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0, &SpNb); 526 | *signalRate = (uint16_t)(2000.0 * signal / SpNb); 527 | return status; 528 | } 529 | 530 | VL53L1X_ERROR VL53L1X::VL53L1X_GetAmbientPerSpad(uint16_t *ambPerSp) 531 | { 532 | VL53L1X_ERROR status = 0; 533 | uint16_t AmbientRate, SpNb = 1; 534 | 535 | status = VL53L1_RdWord(Device, RESULT__AMBIENT_COUNT_RATE_MCPS_SD, &AmbientRate); 536 | status = VL53L1_RdWord(Device, VL53L1_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0, &SpNb); 537 | *ambPerSp = (uint16_t)(2000.0 * AmbientRate / SpNb); 538 | return status; 539 | } 540 | 541 | VL53L1X_ERROR VL53L1X::VL53L1X_GetSignalRate(uint16_t *signal) 542 | { 543 | VL53L1X_ERROR status = 0; 544 | uint16_t tmp; 545 | 546 | status = VL53L1_RdWord(Device, 547 | VL53L1_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0, &tmp); 548 | *signal = tmp * 8; 549 | return status; 550 | } 551 | 552 | VL53L1X_ERROR VL53L1X::VL53L1X_GetSpadNb(uint16_t *spNb) 553 | { 554 | VL53L1X_ERROR status = 0; 555 | uint16_t tmp; 556 | 557 | status = VL53L1_RdWord(Device, 558 | VL53L1_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0, &tmp); 559 | *spNb = tmp >> 8; 560 | return status; 561 | } 562 | 563 | VL53L1X_ERROR VL53L1X::VL53L1X_GetAmbientRate(uint16_t *ambRate) 564 | { 565 | VL53L1X_ERROR status = 0; 566 | uint16_t tmp; 567 | 568 | status = VL53L1_RdWord(Device, RESULT__AMBIENT_COUNT_RATE_MCPS_SD, &tmp); 569 | *ambRate = tmp * 8; 570 | return status; 571 | } 572 | 573 | VL53L1X_ERROR VL53L1X::VL53L1X_GetRangeStatus(uint8_t *rangeStatus) 574 | { 575 | VL53L1X_ERROR status = 0; 576 | uint8_t RgSt; 577 | 578 | status = VL53L1_RdByte(Device, VL53L1_RESULT__RANGE_STATUS, &RgSt); 579 | RgSt = RgSt & 0x1F; 580 | switch (RgSt) 581 | { 582 | case 9: 583 | RgSt = 0; 584 | break; 585 | case 6: 586 | RgSt = 1; 587 | break; 588 | case 4: 589 | RgSt = 2; 590 | break; 591 | case 8: 592 | RgSt = 3; 593 | break; 594 | case 5: 595 | RgSt = 4; 596 | break; 597 | case 3: 598 | RgSt = 5; 599 | break; 600 | case 19: 601 | RgSt = 6; 602 | break; 603 | case 7: 604 | RgSt = 7; 605 | break; 606 | case 12: 607 | RgSt = 9; 608 | break; 609 | case 18: 610 | RgSt = 10; 611 | break; 612 | case 22: 613 | RgSt = 11; 614 | break; 615 | case 23: 616 | RgSt = 12; 617 | break; 618 | case 13: 619 | RgSt = 13; 620 | break; 621 | default: 622 | RgSt = 255; 623 | break; 624 | } 625 | *rangeStatus = RgSt; 626 | return status; 627 | } 628 | 629 | VL53L1X_ERROR VL53L1X::VL53L1X_SetOffset(int16_t OffsetValue) 630 | { 631 | VL53L1X_ERROR status = 0; 632 | int16_t Temp; 633 | 634 | Temp = (OffsetValue * 4); 635 | VL53L1_WrWord(Device, ALGO__PART_TO_PART_RANGE_OFFSET_MM, 636 | (uint16_t)Temp); 637 | VL53L1_WrWord(Device, MM_CONFIG__INNER_OFFSET_MM, 0x0); 638 | VL53L1_WrWord(Device, MM_CONFIG__OUTER_OFFSET_MM, 0x0); 639 | return status; 640 | } 641 | 642 | VL53L1X_ERROR VL53L1X::VL53L1X_GetOffset(int16_t *offset) 643 | { 644 | VL53L1X_ERROR status = 0; 645 | uint16_t Temp; 646 | 647 | status = VL53L1_RdWord(Device, ALGO__PART_TO_PART_RANGE_OFFSET_MM, &Temp); 648 | Temp = Temp << 3; 649 | Temp = Temp >> 5; 650 | *offset = (int16_t)(Temp); 651 | return status; 652 | } 653 | 654 | VL53L1X_ERROR VL53L1X::VL53L1X_SetXtalk(uint16_t XtalkValue) 655 | { 656 | /* XTalkValue in count per second to avoid float type */ 657 | VL53L1X_ERROR status = 0; 658 | 659 | status = VL53L1_WrWord(Device, 660 | ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS, 661 | 0x0000); 662 | status = VL53L1_WrWord(Device, ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS, 663 | 0x0000); 664 | status = VL53L1_WrWord(Device, ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS, 665 | (XtalkValue << 9) / 1000); /* * << 9 (7.9 format) and /1000 to convert cps to kpcs */ 666 | return status; 667 | } 668 | 669 | VL53L1X_ERROR VL53L1X::VL53L1X_GetXtalk(uint16_t *xtalk) 670 | { 671 | VL53L1X_ERROR status = 0; 672 | uint16_t tmp; 673 | 674 | status = VL53L1_RdWord(Device, ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS, &tmp); 675 | *xtalk = (tmp * 1000) >> 9; /* * 1000 to convert kcps to cps and >> 9 (7.9 format) */ 676 | return status; 677 | } 678 | 679 | VL53L1X_ERROR VL53L1X::VL53L1X_SetDistanceThreshold(uint16_t ThreshLow, 680 | uint16_t ThreshHigh, uint8_t Window, 681 | uint8_t IntOnNoTarget) 682 | { 683 | VL53L1X_ERROR status = 0; 684 | uint8_t Temp = 0; 685 | 686 | status = VL53L1_RdByte(Device, SYSTEM__INTERRUPT_CONFIG_GPIO, &Temp); 687 | Temp = Temp & 0x47; 688 | if (IntOnNoTarget == 0) 689 | { 690 | status = VL53L1_WrByte(Device, SYSTEM__INTERRUPT_CONFIG_GPIO, 691 | (Temp | (Window & 0x07))); 692 | } 693 | else 694 | { 695 | status = VL53L1_WrByte(Device, SYSTEM__INTERRUPT_CONFIG_GPIO, 696 | ((Temp | (Window & 0x07)) | 0x40)); 697 | } 698 | status = VL53L1_WrWord(Device, SYSTEM__THRESH_HIGH, ThreshHigh); 699 | status = VL53L1_WrWord(Device, SYSTEM__THRESH_LOW, ThreshLow); 700 | return status; 701 | } 702 | 703 | VL53L1X_ERROR VL53L1X::VL53L1X_GetDistanceThresholdWindow(uint16_t *window) 704 | { 705 | VL53L1X_ERROR status = 0; 706 | uint8_t tmp; 707 | status = VL53L1_RdByte(Device, SYSTEM__INTERRUPT_CONFIG_GPIO, &tmp); 708 | *window = (uint16_t)(tmp & 0x7); 709 | return status; 710 | } 711 | 712 | VL53L1X_ERROR VL53L1X::VL53L1X_GetDistanceThresholdLow(uint16_t *low) 713 | { 714 | VL53L1X_ERROR status = 0; 715 | uint16_t tmp; 716 | 717 | status = VL53L1_RdWord(Device, SYSTEM__THRESH_LOW, &tmp); 718 | *low = tmp; 719 | return status; 720 | } 721 | 722 | VL53L1X_ERROR VL53L1X::VL53L1X_GetDistanceThresholdHigh(uint16_t *high) 723 | { 724 | VL53L1X_ERROR status = 0; 725 | uint16_t tmp; 726 | 727 | status = VL53L1_RdWord(Device, SYSTEM__THRESH_HIGH, &tmp); 728 | *high = tmp; 729 | return status; 730 | } 731 | 732 | VL53L1X_ERROR VL53L1X::VL53L1X_SetROI(uint8_t X, uint8_t Y, uint8_t opticalCenter) 733 | { 734 | VL53L1X_ERROR status = 0; 735 | 736 | if (X > 16) 737 | X = 16; 738 | if (Y > 16) 739 | Y = 16; 740 | if (X > 10 || Y > 10) 741 | { 742 | opticalCenter = 199; 743 | } 744 | status = VL53L1_WrByte(Device, ROI_CONFIG__USER_ROI_CENTRE_SPAD, opticalCenter); 745 | status = VL53L1_WrByte(Device, ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE, 746 | (Y - 1) << 4 | (X - 1)); 747 | return status; 748 | } 749 | 750 | VL53L1X_ERROR VL53L1X::VL53L1X_GetROI_XY(uint16_t *ROI_X, uint16_t *ROI_Y) 751 | { 752 | VL53L1X_ERROR status = 0; 753 | uint8_t tmp; 754 | 755 | status = VL53L1_RdByte(Device, ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE, &tmp); 756 | *ROI_X = ((uint16_t)tmp & 0x0F) + 1; 757 | *ROI_Y = (((uint16_t)tmp & 0xF0) >> 4) + 1; 758 | return status; 759 | } 760 | 761 | VL53L1X_ERROR VL53L1X::VL53L1X_SetSignalThreshold(uint16_t Signal) 762 | { 763 | VL53L1X_ERROR status = 0; 764 | 765 | VL53L1_WrWord(Device, RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS, Signal >> 3); 766 | return status; 767 | } 768 | 769 | VL53L1X_ERROR VL53L1X::VL53L1X_GetSignalThreshold(uint16_t *signal) 770 | { 771 | VL53L1X_ERROR status = 0; 772 | uint16_t tmp; 773 | 774 | status = VL53L1_RdWord(Device, 775 | RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS, &tmp); 776 | *signal = tmp << 3; 777 | return status; 778 | } 779 | 780 | VL53L1X_ERROR VL53L1X::VL53L1X_SetSigmaThreshold(uint16_t Sigma) 781 | { 782 | VL53L1X_ERROR status = 0; 783 | 784 | if (Sigma > (0xFFFF >> 2)) 785 | { 786 | return 1; 787 | } 788 | /* 16 bits register 14.2 format */ 789 | status = VL53L1_WrWord(Device, RANGE_CONFIG__SIGMA_THRESH, Sigma << 2); 790 | return status; 791 | } 792 | 793 | VL53L1X_ERROR VL53L1X::VL53L1X_GetSigmaThreshold(uint16_t *sigma) 794 | { 795 | VL53L1X_ERROR status = 0; 796 | uint16_t tmp; 797 | 798 | status = VL53L1_RdWord(Device, RANGE_CONFIG__SIGMA_THRESH, &tmp); 799 | *sigma = tmp >> 2; 800 | return status; 801 | } 802 | 803 | VL53L1X_ERROR VL53L1X::VL53L1X_StartTemperatureUpdate() 804 | { 805 | VL53L1X_ERROR status = 0; 806 | uint8_t tmp = 0; 807 | 808 | status = VL53L1_WrByte(Device, VL53L1_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND, 0x81); /* full VHV */ 809 | status = VL53L1_WrByte(Device, 0x0B, 0x92); 810 | status = VL53L1X_StartRanging(); 811 | while (tmp == 0) 812 | { 813 | status = VL53L1X_CheckForDataReady(&tmp); 814 | } 815 | tmp = 0; 816 | status = VL53L1X_ClearInterrupt(); 817 | status = VL53L1X_StopRanging(); 818 | status = VL53L1_WrByte(Device, VL53L1_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND, 0x09); /* two bounds VHV */ 819 | status = VL53L1_WrByte(Device, 0x0B, 0); /* start VHV from the previous temperature */ 820 | return status; 821 | } 822 | 823 | /* VL53L1X_calibration.h functions */ 824 | 825 | int8_t VL53L1X::VL53L1X_CalibrateOffset(uint16_t TargetDistInMm, int16_t *offset) 826 | { 827 | uint8_t i = 0, tmp; 828 | int16_t AverageDistance = 0; 829 | uint16_t distance; 830 | VL53L1X_ERROR status = 0; 831 | 832 | status = VL53L1_WrWord(Device, ALGO__PART_TO_PART_RANGE_OFFSET_MM, 0x0); 833 | status = VL53L1_WrWord(Device, MM_CONFIG__INNER_OFFSET_MM, 0x0); 834 | status = VL53L1_WrWord(Device, MM_CONFIG__OUTER_OFFSET_MM, 0x0); 835 | status = VL53L1X_StartRanging(); /* Enable VL53L1X sensor */ 836 | for (i = 0; i < 50; i++) 837 | { 838 | while (tmp == 0) 839 | { 840 | status = VL53L1X_CheckForDataReady(&tmp); 841 | } 842 | tmp = 0; 843 | status = VL53L1X_GetDistance(&distance); 844 | status = VL53L1X_ClearInterrupt(); 845 | AverageDistance = AverageDistance + distance; 846 | } 847 | status = VL53L1X_StopRanging(); 848 | AverageDistance = AverageDistance / 50; 849 | *offset = TargetDistInMm - AverageDistance; 850 | status = VL53L1_WrWord(Device, ALGO__PART_TO_PART_RANGE_OFFSET_MM, *offset * 4); 851 | return status; 852 | } 853 | 854 | int8_t VL53L1X::VL53L1X_CalibrateXtalk(uint16_t TargetDistInMm, uint16_t *xtalk) 855 | { 856 | uint8_t i, tmp = 0; 857 | float AverageSignalRate = 0; 858 | float AverageDistance = 0; 859 | float AverageSpadNb = 0; 860 | uint16_t distance = 0, spadNum; 861 | uint16_t sr; 862 | VL53L1X_ERROR status = 0; 863 | 864 | status = VL53L1_WrWord(Device, 0x0016, 0); 865 | status = VL53L1X_StartRanging(); 866 | for (i = 0; i < 50; i++) 867 | { 868 | while (tmp == 0) 869 | { 870 | status = VL53L1X_CheckForDataReady(&tmp); 871 | } 872 | tmp = 0; 873 | status = VL53L1X_GetSignalRate(&sr); 874 | status = VL53L1X_GetDistance(&distance); 875 | status = VL53L1X_ClearInterrupt(); 876 | AverageDistance = AverageDistance + distance; 877 | status = VL53L1X_GetSpadNb(&spadNum); 878 | AverageSpadNb = AverageSpadNb + spadNum; 879 | AverageSignalRate = 880 | AverageSignalRate + sr; 881 | } 882 | status = VL53L1X_StopRanging(); 883 | AverageDistance = AverageDistance / 50; 884 | AverageSpadNb = AverageSpadNb / 50; 885 | AverageSignalRate = AverageSignalRate / 50; 886 | /* Calculate Xtalk value */ 887 | *xtalk = (uint16_t)(512 * (AverageSignalRate * (1 - (AverageDistance / TargetDistInMm))) / AverageSpadNb); 888 | status = VL53L1_WrWord(Device, 0x0016, *xtalk); 889 | return status; 890 | } 891 | 892 | /* Write and read functions from I2C */ 893 | 894 | VL53L1X_ERROR VL53L1X::VL53L1_WriteMulti(VL53L1_DEV Dev, uint16_t index, uint8_t *pdata, uint32_t count) 895 | { 896 | int status; 897 | 898 | status = VL53L1_I2CWrite(Dev->I2cDevAddr, index, pdata, (uint16_t)count); 899 | return status; 900 | } 901 | 902 | VL53L1X_ERROR VL53L1X::VL53L1_ReadMulti(VL53L1_DEV Dev, uint16_t index, uint8_t *pdata, uint32_t count) 903 | { 904 | int status; 905 | 906 | status = VL53L1_I2CRead(Dev->I2cDevAddr, index, pdata, (uint16_t)count); 907 | 908 | return status; 909 | } 910 | 911 | VL53L1X_ERROR VL53L1X::VL53L1_WrByte(VL53L1_DEV Dev, uint16_t index, uint8_t data) 912 | { 913 | int status; 914 | 915 | status = VL53L1_I2CWrite(Dev->I2cDevAddr, index, &data, 1); 916 | return status; 917 | } 918 | 919 | VL53L1X_ERROR VL53L1X::VL53L1_WrWord(VL53L1_DEV Dev, uint16_t index, uint16_t data) 920 | { 921 | int status; 922 | uint8_t buffer[2]; 923 | 924 | buffer[0] = data >> 8; 925 | buffer[1] = data & 0x00FF; 926 | status = VL53L1_I2CWrite(Dev->I2cDevAddr, index, (uint8_t *)buffer, 2); 927 | return status; 928 | } 929 | 930 | VL53L1X_ERROR VL53L1X::VL53L1_WrDWord(VL53L1_DEV Dev, uint16_t index, uint32_t data) 931 | { 932 | int status; 933 | uint8_t buffer[4]; 934 | 935 | buffer[0] = (data >> 24) & 0xFF; 936 | buffer[1] = (data >> 16) & 0xFF; 937 | buffer[2] = (data >> 8) & 0xFF; 938 | buffer[3] = (data >> 0) & 0xFF; 939 | status = VL53L1_I2CWrite(Dev->I2cDevAddr, index, (uint8_t *)buffer, 4); 940 | return status; 941 | } 942 | 943 | VL53L1X_ERROR VL53L1X::VL53L1_RdByte(VL53L1_DEV Dev, uint16_t index, uint8_t *data) 944 | { 945 | int status; 946 | 947 | status = VL53L1_I2CRead(Dev->I2cDevAddr, index, data, 1); 948 | 949 | if (status) 950 | return -1; 951 | 952 | return 0; 953 | } 954 | 955 | VL53L1X_ERROR VL53L1X::VL53L1_RdWord(VL53L1_DEV Dev, uint16_t index, uint16_t *data) 956 | { 957 | int status; 958 | uint8_t buffer[2] = {0, 0}; 959 | 960 | status = VL53L1_I2CRead(Dev->I2cDevAddr, index, buffer, 2); 961 | if (!status) 962 | { 963 | *data = (buffer[0] << 8) + buffer[1]; 964 | } 965 | return status; 966 | } 967 | 968 | VL53L1X_ERROR VL53L1X::VL53L1_RdDWord(VL53L1_DEV Dev, uint16_t index, uint32_t *data) 969 | { 970 | int status; 971 | uint8_t buffer[4] = {0, 0, 0, 0}; 972 | 973 | status = VL53L1_I2CRead(Dev->I2cDevAddr, index, buffer, 4); 974 | if (!status) 975 | { 976 | *data = (buffer[0] << 24) + (buffer[1] << 16U) + (buffer[2] << 8) + buffer[3]; 977 | } 978 | return status; 979 | } 980 | 981 | VL53L1X_ERROR VL53L1X::VL53L1_UpdateByte(VL53L1_DEV Dev, uint16_t index, uint8_t AndData, uint8_t OrData) 982 | { 983 | int status; 984 | uint8_t buffer = 0; 985 | 986 | /* read data direct onto buffer */ 987 | status = VL53L1_I2CRead(Dev->I2cDevAddr, index, &buffer, 1); 988 | if (!status) 989 | { 990 | buffer = (buffer & AndData) | OrData; 991 | status = VL53L1_I2CWrite(Dev->I2cDevAddr, index, &buffer, (uint16_t)1); 992 | } 993 | return status; 994 | } 995 | 996 | VL53L1X_ERROR VL53L1X::VL53L1_I2CWrite(uint8_t DeviceAddr, uint16_t RegisterAddr, uint8_t *pBuffer, uint16_t NumByteToWrite) 997 | { 998 | #ifdef DEBUG_MODE 999 | Serial.print("Beginning transmission to "); 1000 | Serial.println(((DeviceAddr) >> 1) & 0x7F); 1001 | #endif 1002 | dev_i2c->beginTransmission(((uint8_t)(((DeviceAddr) >> 1) & 0x7F))); 1003 | #ifdef DEBUG_MODE 1004 | Serial.print("Writing port number "); 1005 | Serial.println(RegisterAddr); 1006 | #endif 1007 | uint8_t buffer[2]; 1008 | buffer[0] = RegisterAddr >> 8; 1009 | buffer[1] = RegisterAddr & 0xFF; 1010 | dev_i2c->write(buffer, 2); 1011 | for (uint16_t i = 0; i < NumByteToWrite; i++) 1012 | dev_i2c->write(pBuffer[i]); 1013 | 1014 | dev_i2c->endTransmission(true); 1015 | return 0; 1016 | } 1017 | 1018 | VL53L1X_ERROR VL53L1X::VL53L1_I2CRead(uint8_t DeviceAddr, uint16_t RegisterAddr, uint8_t *pBuffer, uint16_t NumByteToRead) 1019 | { 1020 | int status = 0; 1021 | 1022 | //Loop until the port is transmitted correctly 1023 | uint8_t maxAttempts = 5; 1024 | for (uint8_t x = 0; x < maxAttempts; x++) 1025 | { 1026 | #ifdef DEBUG_MODE 1027 | Serial.print("Beginning transmission to "); 1028 | Serial.println(((DeviceAddr) >> 1) & 0x7F); 1029 | #endif 1030 | dev_i2c->beginTransmission(((uint8_t)(((DeviceAddr) >> 1) & 0x7F))); 1031 | #ifdef DEBUG_MODE 1032 | Serial.print("Writing port number "); 1033 | Serial.println(RegisterAddr); 1034 | #endif 1035 | uint8_t buffer[2]; 1036 | buffer[0] = RegisterAddr >> 8; 1037 | buffer[1] = RegisterAddr & 0xFF; 1038 | dev_i2c->write(buffer, 2); 1039 | status = dev_i2c->endTransmission(false); 1040 | 1041 | if (status == 0) 1042 | break; 1043 | 1044 | //Fix for some STM32 boards 1045 | //Reinitialize th i2c bus with the default parameters 1046 | #ifdef ARDUINO_ARCH_STM32 1047 | if (status) 1048 | { 1049 | dev_i2c->end(); 1050 | dev_i2c->begin(); 1051 | } 1052 | #endif 1053 | //End of fix 1054 | } 1055 | 1056 | dev_i2c->requestFrom(((uint8_t)(((DeviceAddr) >> 1) & 0x7F)), (byte)NumByteToRead); 1057 | 1058 | int i = 0; 1059 | while (dev_i2c->available()) 1060 | { 1061 | pBuffer[i] = dev_i2c->read(); 1062 | i++; 1063 | } 1064 | 1065 | return 0; 1066 | } 1067 | 1068 | VL53L1X_ERROR VL53L1X::VL53L1_GetTickCount( 1069 | uint32_t *ptick_count_ms) 1070 | { 1071 | 1072 | /* Returns current tick count in [ms] */ 1073 | 1074 | VL53L1X_ERROR status = VL53L1_ERROR_NONE; 1075 | 1076 | //*ptick_count_ms = timeGetTime(); 1077 | *ptick_count_ms = 0; 1078 | 1079 | return status; 1080 | } 1081 | 1082 | VL53L1X_ERROR VL53L1X::VL53L1_WaitUs(VL53L1_Dev_t *pdev, int32_t wait_us) 1083 | { 1084 | (void)pdev; 1085 | delay(wait_us / 1000); 1086 | return VL53L1_ERROR_NONE; 1087 | } 1088 | 1089 | VL53L1X_ERROR VL53L1X::VL53L1_WaitMs(VL53L1_Dev_t *pdev, int32_t wait_ms) 1090 | { 1091 | (void)pdev; 1092 | delay(wait_ms); 1093 | return VL53L1_ERROR_NONE; 1094 | } 1095 | 1096 | VL53L1X_ERROR VL53L1X::VL53L1_WaitValueMaskEx( 1097 | VL53L1_Dev_t *pdev, 1098 | uint32_t timeout_ms, 1099 | uint16_t index, 1100 | uint8_t value, 1101 | uint8_t mask, 1102 | uint32_t poll_delay_ms) 1103 | { 1104 | 1105 | /* 1106 | * Platform implementation of WaitValueMaskEx V2WReg script command 1107 | * 1108 | * WaitValueMaskEx( 1109 | * duration_ms, 1110 | * index, 1111 | * value, 1112 | * mask, 1113 | * poll_delay_ms); 1114 | */ 1115 | 1116 | VL53L1_Error status = VL53L1_ERROR_NONE; 1117 | uint32_t start_time_ms = 0; 1118 | uint32_t current_time_ms = 0; 1119 | uint32_t polling_time_ms = 0; 1120 | uint8_t byte_value = 0; 1121 | uint8_t found = 0; 1122 | 1123 | /* calculate time limit in absolute time */ 1124 | 1125 | VL53L1_GetTickCount(&start_time_ms); 1126 | 1127 | /* remember current trace functions and temporarily disable 1128 | * function logging 1129 | */ 1130 | 1131 | /* wait until value is found, timeout reached on error occurred */ 1132 | 1133 | while ((status == VL53L1_ERROR_NONE) && 1134 | (polling_time_ms < timeout_ms) && 1135 | (found == 0)) 1136 | { 1137 | 1138 | if (status == VL53L1_ERROR_NONE) 1139 | status = VL53L1_RdByte( 1140 | pdev, 1141 | index, 1142 | &byte_value); 1143 | 1144 | if ((byte_value & mask) == value) 1145 | found = 1; 1146 | 1147 | if (status == VL53L1_ERROR_NONE && 1148 | found == 0 && 1149 | poll_delay_ms > 0) 1150 | status = VL53L1_WaitMs( 1151 | pdev, 1152 | poll_delay_ms); 1153 | 1154 | /* Update polling time (Compare difference rather than absolute to 1155 | negate 32bit wrap around issue) */ 1156 | VL53L1_GetTickCount(¤t_time_ms); 1157 | polling_time_ms = current_time_ms - start_time_ms; 1158 | } 1159 | 1160 | if (found == 0 && status == VL53L1_ERROR_NONE) 1161 | status = VL53L1_ERROR_TIME_OUT; 1162 | 1163 | return status; 1164 | } 1165 | --------------------------------------------------------------------------------