未验证 提交 7dc26413 编写于 作者: S sichelz1 提交者: GitHub

Implementation of VL53L1X sensor including sample and documentation (#1923)

* Implementation of VL53L1X sensor including sample and documentation

* Added missing links to VL53l1X device

* Removed links from md files
Removed gpiocontroller from vl53l1x class
Passing I2cdevice to constructor
Switched from functions to properties

* Now using UnitsNet for all distances.
Small code cosmetics

* Added additional comments and range checks
上级 402cda01
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace Iot.Device.Vl53L1X
{
/// <summary>
/// The boot state of the device
/// </summary>
public enum BootState : byte
{
/// <summary>
/// The device is not booted yet.
/// </summary>
NotBooted = 0,
/// <summary>
/// The device is booted.
/// </summary>
Booted = 1
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace Iot.Device.Vl53L1X
{
/// <summary>
/// The distance mode of the device
/// </summary>
public enum Precision : byte
{
/// <summary>
/// Short distance. Maximum distance is limited to 1.3m but results in a better ambient immunity.
/// </summary>
Short = 1,
/// <summary>
/// Long distance. Can range up to 4 m in the dark with a timing budget of200 ms.
/// </summary>
Long = 2,
/// <summary>
/// Unknown distance mode or the distance mode is not configured.
/// </summary>
Unknown = 3
}
}
# VL53L1X - distance sensor
The VL53L1X is a state-of-the-art, Time-of-Flight (ToF), laser-ranging sensor. It is the fastest miniature ToF sensor on the market with accurate ranging up to 4 m and fast ranging frequency up to 50 Hz housed in a miniature and reflowable package, it integrates a SPAD receiving array, a 940 nm invisible Class1 laser emitter, physical infrared filters, and optics to achieve the best ranging performance in various ambient lighting conditions with a range of cover window options.
Unlike conventional IR sensors, the VL53L1X uses ST’s latest generation ToF technology which allows absolute distance measurement whatever the target color and reflectance.
It is also possible to program the size of the ROI on the receiving array, allowing the sensor FoV to be reduced
## Documentation
**VL53L1X** [datasheet](https://www.st.com/en/embedded-software/stsw-img007.html)
You will find this device for example as ["Adafruit VL53L1X Time of Flight Distance Sensor - ~30 to 4000mm"](https://www.adafruit.com/product/3967)
## Board
![VL53L1X](./VL53L1X.jpg)
## Usage
All calibration and all setup of the sensor is done fully transparently for you. Just create a class and start reading the distance.
Make sure you have turned the device on via the xShut pin.
```csharp
using Vl53L1X vl53L1X = new(I2cDevice.Create(new I2cConnectionSettings(1, Vl53L1X.DefaultI2cAddress)));
Console.WriteLine($"SensorID: {vl53L1X.SensorId:X}");
vl53L1X.Precision = Precision.Short;
while (!Console.KeyAvailable)
{
try
{
Console.WriteLine($"Distance: {vl53L1X.Distance.Millimeters}");
Console.WriteLine($"RangeStatus {vl53L1X.RangeStatus}");
}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex.Message}");
}
Thread.Sleep(500);
}
```
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace Iot.Device.Vl53L1X
{
/// <summary>
/// The range status of the device.
/// There are five range statuses: 0, 1, 2, 4, and 7. When the range status is 0, there is no error.
/// Range status 1 and 2 are error warnings while range status 4 and 7 are errors.
/// </summary>
public enum RangeStatus : byte
{
/// <summary>
/// No error has occured.
/// </summary>
NoError = 0,
/// <summary>
/// SigmaFailure.
/// This means that the repeatability or standard deviation of the measurement is bad due to a decreasing signal noise ratio.
/// Increasing the timing budget can improve the standard deviation and avoid a range status 1.
/// </summary>
SigmaFailure = 1,
/// <summary>
/// SignalFailure.
/// This means that the return signal is too week to return a good answer.
/// The reason is because the target is too far, or the target is not reflective enough, or the target is too small.
/// Increasing the timing budget might help, but there may simply be no target available.
/// </summary>
SignalFailure = 2,
/// <summary>
/// OutOfBounds.
/// This means that the sensor is ranging in a "non-appropriated" zone and the measured result may be inconsistent.
/// This status is considered as a warning but, in general, it happens when a target is at the maximum distance possible from the sensor, i.e. around 5 m.
/// However, this is only for very bright targets.
/// </summary>
OutOfBounds = 4,
/// <summary>
/// WrapAround.
/// This situation may occur when the target is very reflective and the distance to the target/sensor is longer than the physical limited distance measurable by the sensor.
/// Such distances include approximately 5 m when the senor is in Long distance mode and approximately 1.3 m when the sensor is in Short distance mode.
/// </summary>
WrapAround = 7,
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace Iot.Device.Vl53L1X
{
internal enum Registers : ushort
{
VL53L1X_I2C_SLAVE__DEVICE_ADDRESS = 0x0001,
VL53L1X_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND = 0x0008,
ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS = 0x0016,
ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS = 0x0018,
ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS = 0x001A,
ALGO__PART_TO_PART_RANGE_OFFSET_MM = 0x001E,
MM_CONFIG__INNER_OFFSET_MM = 0x0020,
MM_CONFIG__OUTER_OFFSET_MM = 0x0022,
GPIO_HV_MUX__CTRL = 0x0030,
GPIO__TIO_HV_STATUS = 0x0031,
SYSTEM__INTERRUPT_CONFIG_GPIO = 0x0046,
PHASECAL_CONFIG__TIMEOUT_MACROP = 0x004B,
RANGE_CONFIG__TIMEOUT_MACROP_A_HI = 0x005E,
RANGE_CONFIG__VCSEL_PERIOD_A = 0x0060,
RANGE_CONFIG__VCSEL_PERIOD_B = 0x0063,
RANGE_CONFIG__TIMEOUT_MACROP_B_HI = 0x0061,
RANGE_CONFIG__TIMEOUT_MACROP_B_LO = 0x0062,
RANGE_CONFIG__SIGMA_THRESH = 0x0064,
RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS = 0x0066,
RANGE_CONFIG__VALID_PHASE_HIGH = 0x0069,
VL53L1X_SYSTEM__INTERMEASUREMENT_PERIOD = 0x006C,
SYSTEM__THRESH_HIGH = 0x0072,
SYSTEM__THRESH_LOW = 0x0074,
SD_CONFIG__WOI_SD0 = 0x0078,
SD_CONFIG__INITIAL_PHASE_SD0 = 0x007A,
ROI_CONFIG__USER_ROI_CENTRE_SPAD = 0x007F,
ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE = 0x0080,
SYSTEM__SEQUENCE_CONFIG = 0x0081,
VL53L1X_SYSTEM__GROUPED_PARAMETER_HOLD = 0x0082,
SYSTEM__INTERRUPT_CLEAR = 0x0086,
SYSTEM__MODE_START = 0x0087,
VL53L1X_RESULT__RANGE_STATUS = 0x0089,
VL53L1X_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0 = 0x008C,
RESULT__AMBIENT_COUNT_RATE_MCPS_SD = 0x0090,
VL53L1X_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 = 0x0096,
VL53L1X_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0 = 0x0098,
VL53L1X_RESULT__OSC_CALIBRATE_VAL = 0x00DE,
VL53L1X_FIRMWARE__SYSTEM_STATUS = 0x00E5,
VL53L1X_IDENTIFICATION__MODEL_ID = 0x010F,
VL53L1X_ROI_CONFIG__MODE_ROI_CENTRE_SPAD = 0x013E,
VL53L1X_DEFAULT_DEVICE_ADDRESS = 0x29
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
namespace Iot.Device.Vl53L1X
{
/// <summary>
/// Holds the ROI information of the device
/// </summary>
public class Roi
{
/// <summary>
/// Width of the ROI
/// </summary>
public ushort Width { get; }
/// <summary>
/// Height of the ROI
/// </summary>
public ushort Height { get; }
/// <summary>
/// Constructor.
/// </summary>
/// <param name="width">Width of the ROI. Must be between 4 and 16.</param>
/// <param name="height">Height of the ROI. Must be between 4 and 16.</param>
public Roi(ushort width, ushort height)
{
if (width < 4 || width > 16)
{
throw new ArgumentOutOfRangeException(nameof(width), "Must be between 4 and 16.");
}
if (height < 4 || height > 16)
{
throw new ArgumentOutOfRangeException(nameof(height), "Must be between 4 and 16.");
}
Width = width;
Height = height;
}
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace Iot.Device.Vl53L1X
{
/// <summary>
/// The timing budget for the device
/// </summary>
public enum TimingBudget : ushort
{
/// <summary>
/// Unknown budget or the budget is not configured
/// </summary>
BudgetUnknown = 0,
/// <summary>
/// Budget of 15 ms
/// </summary>
Budget15 = 15,
/// <summary>
/// Budget of 20 ms
/// </summary>
Budget20 = 20,
/// <summary>
/// Budget of 33 ms
/// </summary>
Budget33 = 33,
/// <summary>
/// Budget of 50 ms
/// </summary>
Budget50 = 50,
/// <summary>
/// Budget of 100 ms
/// </summary>
Budget100 = 100,
/// <summary>
/// Budget of 200 ms
/// </summary>
Budget200 = 200,
/// <summary>
/// Budget of 500 ms
/// </summary>
Budget500 = 500,
}
}
此差异已折叠。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(DefaultBindingTfms)</TargetFrameworks>
<!--Disabling default items so samples source won't get build by the main library-->
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
<ItemGroup>
<Compile Include="*.cs" />
</ItemGroup>
<ItemGroup>
<None Include="README.md" />
</ItemGroup>
</Project>

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.2.32602.215
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vl53L1X", "Vl53L1X.csproj", "{A2D9026A-789C-4D53-9784-F66B37FB0247}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vl53L1X.sample", "samples\Vl53L1X.sample.csproj", "{E76A0A77-29AD-4011-9383-1D3EA85C1357}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A2D9026A-789C-4D53-9784-F66B37FB0247}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A2D9026A-789C-4D53-9784-F66B37FB0247}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A2D9026A-789C-4D53-9784-F66B37FB0247}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A2D9026A-789C-4D53-9784-F66B37FB0247}.Release|Any CPU.Build.0 = Release|Any CPU
{E76A0A77-29AD-4011-9383-1D3EA85C1357}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E76A0A77-29AD-4011-9383-1D3EA85C1357}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E76A0A77-29AD-4011-9383-1D3EA85C1357}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E76A0A77-29AD-4011-9383-1D3EA85C1357}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D6AC624A-1068-4830-B81E-501EDE9C0AD6}
EndGlobalSection
EndGlobal
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace Iot.Device.Vl53L1X
{
/// <summary>
/// The window detection mode.
/// </summary>
public enum WindowDetectionMode : byte
{
/// <summary>
/// Object under a certain distance.
/// </summary>
Below = 0,
/// <summary>
/// Object beyond a certain distance.
/// </summary>
Above = 1,
/// <summary>
/// Object out of a window limited by a near and far threshold.
/// </summary>
Out = 2,
/// <summary>
/// Object within a window limited by a near and far threshold.
/// </summary>
In = 3
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Device.Gpio;
using System.Device.I2c;
using System.Threading;
using Iot.Device.Vl53L1X;
const int xShutPinNo = 23;
const int newI2CAddress = 0x30;
Console.WriteLine("Hello VL53L1X!");
// Turn the on device.
var gpioController = new GpioController();
gpioController.OpenPin(xShutPinNo, PinMode.Output);
gpioController.Write(xShutPinNo, PinValue.High);
using var defaultI2CDevice = I2cDevice.Create(new I2cConnectionSettings(1, Vl53L1X.DefaultI2cAddress));
Vl53L1X.ChangeI2CAddress(defaultI2CDevice, newI2CAddress);
using Vl53L1X vl53L1X = new(I2cDevice.Create(new I2cConnectionSettings(1, newI2CAddress)));
Console.WriteLine($"SensorID: {vl53L1X.SensorId:X}");
vl53L1X.Precision = Precision.Short;
while (!Console.KeyAvailable)
{
try
{
Console.WriteLine($"Distance: {vl53L1X.Distance.Millimeters}");
Console.WriteLine($"RangeStatus {vl53L1X.RangeStatus}");
}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex.Message}");
}
Thread.Sleep(500);
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>$(DefaultSampleTfms)</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Vl53L1X.csproj" />
</ItemGroup>
</Project>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册