-
-
Notifications
You must be signed in to change notification settings - Fork 111
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
824 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Reflection; | ||
using System.Runtime.CompilerServices; | ||
using System.Runtime.InteropServices; | ||
|
||
[assembly: AssemblyTitle("Iot.Device.Vl6180X")] | ||
[assembly: AssemblyCompany("nanoFramework Contributors")] | ||
[assembly: AssemblyCopyright("Copyright(c).NET Foundation and Contributors")] | ||
|
||
[assembly: ComVisible(false)] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Vl6180X - distance sensor | ||
|
||
The Vl6180X sensor is a Time-to-Flight sensor measuring precisely distances. The sensor allows you to get precise short distance measurement (from 5 millimeters to 2 meters) as well as long distance measurement (up to 8 meters but with a decreased precision). This sensor is a laser ranging sensor. It is using laser pulses to measure the distances. | ||
|
||
## Documentation | ||
|
||
**Vl6180X** [datasheet](https://www.st.com/resource/en/datasheet/vl6180x.pdf) | ||
|
||
|
||
## Usage | ||
|
||
**Important**: make sure you properly setup the I2C pins especially for ESP32 before creating the `I2cDevice`, make sure you install the `nanoFramework.Hardware.ESP32 nuget`: | ||
|
||
```csharp | ||
// when connecting to an ESP32 device, need to configure the I2C GPIOs used for the bus | ||
Configuration.SetPinFunction(11, DeviceFunction.I2C1_DATA); | ||
Configuration.SetPinFunction(10, DeviceFunction.I2C1_CLOCK); | ||
|
||
using VL6180X sensor = new(I2cDevice.Create(new I2cConnectionSettings(1, VL6180X.DefaultI2cAddress))); | ||
sensor.Init(); | ||
while (true) | ||
{ | ||
var distance = sensor.ReadRange(); | ||
Console.WriteLine($"Distance: {distance.Centimeters} cm."); | ||
Thread.Sleep(500); | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// 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.VL6180X | ||
{ | ||
internal enum RegisterAddresses : ushort | ||
{ | ||
IDENTIFICATION__MODEL_ID = 0x000, | ||
IDENTIFICATION__MODEL_REV_MAJOR = 0x001, | ||
IDENTIFICATION__MODEL_REV_MINOR = 0x002, | ||
IDENTIFICATION__MODULE_REV_MAJOR = 0x003, | ||
IDENTIFICATION__MODULE_REV_MINOR = 0x004, | ||
IDENTIFICATION__DATE_HI = 0x006, | ||
IDENTIFICATION__DATE_LO = 0x007, | ||
IDENTIFICATION__TIME = 0x008, // 16-bit | ||
SYSTEM__MODE_GPIO0 = 0x010, | ||
SYSTEM__MODE_GPIO1 = 0x011, | ||
SYSTEM__HISTORY_CTRL = 0x012, | ||
SYSTEM__INTERRUPT_CONFIG_GPIO = 0x014, | ||
SYSTEM__INTERRUPT_CLEAR = 0x015, | ||
SYSTEM__FRESH_OUT_OF_RESET = 0x016, | ||
SYSTEM__GROUPED_PARAMETER_HOLD = 0x017, | ||
SYSRANGE__START = 0x018, | ||
SYSRANGE__THRESH_HIGH = 0x019, | ||
SYSRANGE__THRESH_LOW = 0x01A, | ||
SYSRANGE__INTERMEASUREMENT_PERIOD = 0x01B, | ||
SYSRANGE__MAX_CONVERGENCE_TIME = 0x01C, | ||
SYSRANGE__CROSSTALK_COMPENSATION_RATE = 0x01E, // 16-bit | ||
SYSRANGE__CROSSTALK_VALID_HEIGHT = 0x021, | ||
SYSRANGE__EARLY_CONVERGENCE_ESTIMATE = 0x022, // 16-bit | ||
SYSRANGE__PART_TO_PART_RANGE_OFFSET = 0x024, | ||
SYSRANGE__RANGE_IGNORE_VALID_HEIGHT = 0x025, | ||
SYSRANGE__RANGE_IGNORE_THRESHOLD = 0x026, // 16-bit | ||
SYSRANGE__MAX_AMBIENT_LEVEL_MULT = 0x02C, | ||
SYSRANGE__RANGE_CHECK_ENABLES = 0x02D, | ||
SYSRANGE__VHV_RECALIBRATE = 0x02E, | ||
SYSRANGE__VHV_REPEAT_RATE = 0x031, | ||
SYSALS__START = 0x038, | ||
SYSALS__THRESH_HIGH = 0x03A, | ||
SYSALS__THRESH_LOW = 0x03C, | ||
SYSALS__INTERMEASUREMENT_PERIOD = 0x03E, | ||
SYSALS__ANALOGUE_GAIN = 0x03F, | ||
SYSALS__INTEGRATION_PERIOD = 0x040, | ||
RESULT__RANGE_STATUS = 0x04D, | ||
RESULT__ALS_STATUS = 0x04E, | ||
RESULT__INTERRUPT_STATUS_GPIO = 0x04F, | ||
RESULT__ALS_VAL = 0x050, // 16-bit | ||
RESULT__HISTORY_BUFFER_0 = 0x052, // 16-bit | ||
RESULT__HISTORY_BUFFER_1 = 0x054, // 16-bit | ||
RESULT__HISTORY_BUFFER_2 = 0x056, // 16-bit | ||
RESULT__HISTORY_BUFFER_3 = 0x058, // 16-bit | ||
RESULT__HISTORY_BUFFER_4 = 0x05A, // 16-bit | ||
RESULT__HISTORY_BUFFER_5 = 0x05C, // 16-bit | ||
RESULT__HISTORY_BUFFER_6 = 0x05E, // 16-bit | ||
RESULT__HISTORY_BUFFER_7 = 0x060, // 16-bit | ||
RESULT__RANGE_VAL = 0x062, | ||
RESULT__RANGE_RAW = 0x064, | ||
RESULT__RANGE_RETURN_RATE = 0x066, // 16-bit | ||
RESULT__RANGE_REFERENCE_RATE = 0x068, // 16-bit | ||
RESULT__RANGE_RETURN_SIGNAL_COUNT = 0x06C, // 32-bit | ||
RESULT__RANGE_REFERENCE_SIGNAL_COUNT = 0x070, // 32-bit | ||
RESULT__RANGE_RETURN_AMB_COUNT = 0x074, // 32-bit | ||
RESULT__RANGE_REFERENCE_AMB_COUNT = 0x078, // 32-bit | ||
RESULT__RANGE_RETURN_CONV_TIME = 0x07C, // 32-bit | ||
RESULT__RANGE_REFERENCE_CONV_TIME = 0x080, // 32-bit | ||
RANGE_SCALER = 0x096, // 16-bit - see STSW-IMG003 core/inc/vl6180x_def.h | ||
READOUT__AVERAGING_SAMPLE_PERIOD = 0x10A, | ||
FIRMWARE__BOOTUP = 0x119, | ||
FIRMWARE__RESULT_SCALER = 0x120, | ||
I2C_SLAVE__DEVICE_ADDRESS = 0x212, | ||
INTERLEAVED_MODE__ENABLE = 0x2A3, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
<StyleCopSettings Version="105"> | ||
<Analyzers> | ||
<Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules"> | ||
<Rules> | ||
<Rule Name="FileHeaderMustContainFileName"> | ||
<RuleSettings> | ||
<BooleanProperty Name="Enabled">False</BooleanProperty> | ||
</RuleSettings> | ||
</Rule> | ||
<Rule Name="FileHeaderMustHaveValidCompanyText"> | ||
<RuleSettings> | ||
<BooleanProperty Name="Enabled">False</BooleanProperty> | ||
</RuleSettings> | ||
</Rule> | ||
<Rule Name="FileHeaderFileNameDocumentationMustMatchTypeName"> | ||
<RuleSettings> | ||
<BooleanProperty Name="Enabled">False</BooleanProperty> | ||
</RuleSettings> | ||
</Rule> | ||
<Rule Name="PropertyDocumentationMustHaveValueText"> | ||
<RuleSettings> | ||
<BooleanProperty Name="Enabled">True</BooleanProperty> | ||
</RuleSettings> | ||
</Rule> | ||
<Rule Name="DocumentationTextMustBeginWithACapitalLetter"> | ||
<RuleSettings> | ||
<BooleanProperty Name="Enabled">True</BooleanProperty> | ||
</RuleSettings> | ||
</Rule> | ||
<Rule Name="DocumentationTextMustEndWithAPeriod"> | ||
<RuleSettings> | ||
<BooleanProperty Name="Enabled">True</BooleanProperty> | ||
</RuleSettings> | ||
</Rule> | ||
<Rule Name="FileHeaderMustShowCopyright"> | ||
<RuleSettings> | ||
<BooleanProperty Name="Enabled">False</BooleanProperty> | ||
</RuleSettings> | ||
</Rule> | ||
<Rule Name="FileHeaderMustHaveCopyrightText"> | ||
<RuleSettings> | ||
<BooleanProperty Name="Enabled">False</BooleanProperty> | ||
</RuleSettings> | ||
</Rule> | ||
<Rule Name="ElementDocumentationMustBeSpelledCorrectly"> | ||
<RuleSettings> | ||
<BooleanProperty Name="Enabled">False</BooleanProperty> | ||
</RuleSettings> | ||
</Rule> | ||
<Rule Name="DocumentationTextMustContainWhitespace"> | ||
<RuleSettings> | ||
<BooleanProperty Name="Enabled">False</BooleanProperty> | ||
</RuleSettings> | ||
</Rule> | ||
</Rules> | ||
<AnalyzerSettings> | ||
<BooleanProperty Name="IgnorePrivates">True</BooleanProperty> | ||
<BooleanProperty Name="IgnoreInternals">True</BooleanProperty> | ||
</AnalyzerSettings> | ||
</Analyzer> | ||
<Analyzer AnalyzerId="StyleCop.CSharp.ReadabilityRules"> | ||
<Rules> | ||
<Rule Name="PrefixLocalCallsWithThis"> | ||
<RuleSettings> | ||
<BooleanProperty Name="Enabled">False</BooleanProperty> | ||
</RuleSettings> | ||
</Rule> | ||
<Rule Name="PrefixCallsCorrectly"> | ||
<RuleSettings> | ||
<BooleanProperty Name="Enabled">False</BooleanProperty> | ||
</RuleSettings> | ||
</Rule> | ||
</Rules> | ||
<AnalyzerSettings /> | ||
</Analyzer> | ||
<Analyzer AnalyzerId="StyleCop.CSharp.OrderingRules"> | ||
<Rules> | ||
<Rule Name="UsingDirectivesMustBePlacedWithinNamespace"> | ||
<RuleSettings> | ||
<BooleanProperty Name="Enabled">False</BooleanProperty> | ||
</RuleSettings> | ||
</Rule> | ||
<Rule Name="ElementsMustAppearInTheCorrectOrder"> | ||
<RuleSettings> | ||
<BooleanProperty Name="Enabled">False</BooleanProperty> | ||
</RuleSettings> | ||
</Rule> | ||
<Rule Name="ElementsMustBeOrderedByAccess"> | ||
<RuleSettings> | ||
<BooleanProperty Name="Enabled">False</BooleanProperty> | ||
</RuleSettings> | ||
</Rule> | ||
</Rules> | ||
<AnalyzerSettings /> | ||
</Analyzer> | ||
<Analyzer AnalyzerId="StyleCop.CSharp.NamingRules"> | ||
<Rules> | ||
<Rule Name="FieldNamesMustNotBeginWithUnderscore"> | ||
<RuleSettings> | ||
<BooleanProperty Name="Enabled">False</BooleanProperty> | ||
</RuleSettings> | ||
</Rule> | ||
<Rule Name="FieldNamesMustNotUseHungarianNotation"> | ||
<RuleSettings> | ||
<BooleanProperty Name="Enabled">False</BooleanProperty> | ||
</RuleSettings> | ||
</Rule> | ||
</Rules> | ||
<AnalyzerSettings /> | ||
</Analyzer> | ||
</Analyzers> | ||
</StyleCopSettings> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
// 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.Buffers.Binary; | ||
using System.Device.I2c; | ||
using System.Diagnostics; | ||
using UnitsNet; | ||
|
||
namespace Iot.Device.VL6180X | ||
{ | ||
/// <summary> | ||
/// Represents VL6180X. | ||
/// </summary> | ||
public sealed class VL6180X : IDisposable | ||
{ | ||
/// <summary> | ||
/// The default I2C Address. | ||
/// </summary> | ||
public const byte DefaultI2cAddress = 0x29; | ||
|
||
private readonly bool _shouldDispose; | ||
private I2cDevice _i2cDevice; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="VL6180X" /> class. | ||
/// </summary> | ||
/// <param name="i2cDevice">The I2C Device.</param> | ||
/// <param name="shouldDispose">True to dispose the I2C Device at dispose.</param> | ||
public VL6180X(I2cDevice i2cDevice, bool shouldDispose = true) | ||
{ | ||
_i2cDevice = i2cDevice ?? throw new ArgumentNullException(nameof(i2cDevice)); | ||
_shouldDispose = shouldDispose; | ||
} | ||
|
||
/// <summary> | ||
/// Initialization of the sensor, include a long sequence of writing | ||
/// which is coming from the offical API with no more information on the | ||
/// registers and their functions. Few can be reversed engineer based on | ||
/// other functions but not all. | ||
/// </summary> | ||
public void Init() | ||
{ | ||
var alreadyInitialized = ReadRegister(RegisterAddresses.SYSTEM__FRESH_OUT_OF_RESET); | ||
if (alreadyInitialized != 1) | ||
{ | ||
return; | ||
} | ||
|
||
WriteRegister(0x207, 0x01); | ||
WriteRegister(0x208, 0x01); | ||
WriteRegister(0x096, 0x00); | ||
WriteRegister(0x097, 0xFD); // RANGE_SCALER = 253 | ||
WriteRegister(0x0E3, 0x01); | ||
WriteRegister(0x0E4, 0x03); | ||
WriteRegister(0x0E5, 0x02); | ||
WriteRegister(0x0E6, 0x01); | ||
WriteRegister(0x0E7, 0x03); | ||
WriteRegister(0x0F5, 0x02); | ||
WriteRegister(0x0D9, 0x05); | ||
WriteRegister(0x0DB, 0xCE); | ||
WriteRegister(0x0DC, 0x03); | ||
WriteRegister(0x0DD, 0xF8); | ||
WriteRegister(0x09F, 0x00); | ||
WriteRegister(0x0A3, 0x3C); | ||
WriteRegister(0x0B7, 0x00); | ||
WriteRegister(0x0BB, 0x3C); | ||
WriteRegister(0x0B2, 0x09); | ||
WriteRegister(0x0CA, 0x09); | ||
WriteRegister(0x198, 0x01); | ||
WriteRegister(0x1B0, 0x17); | ||
WriteRegister(0x1AD, 0x00); | ||
WriteRegister(0x0FF, 0x05); | ||
WriteRegister(0x100, 0x05); | ||
WriteRegister(0x199, 0x05); | ||
WriteRegister(0x1A6, 0x1B); | ||
WriteRegister(0x1AC, 0x3E); | ||
WriteRegister(0x1A7, 0x1F); | ||
WriteRegister(0x030, 0x00); | ||
WriteRegister(RegisterAddresses.SYSTEM__FRESH_OUT_OF_RESET, 0); | ||
} | ||
|
||
/// <summary> | ||
/// Reads the range measurement value from the sensor. | ||
/// </summary> | ||
/// <returns>The measured range value.</returns> | ||
public Length ReadRange() | ||
{ | ||
WriteRegister(RegisterAddresses.SYSRANGE__START, 0x01); | ||
var range = ReadRegister(RegisterAddresses.RESULT__RANGE_VAL); | ||
WriteRegister(RegisterAddresses.SYSTEM__INTERRUPT_CLEAR, 0x01); | ||
return Length.FromMillimeters(range); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public void Dispose() | ||
{ | ||
if (_shouldDispose) | ||
{ | ||
_i2cDevice?.Dispose(); | ||
_i2cDevice = null; | ||
} | ||
} | ||
|
||
private void WriteRegister(RegisterAddresses reg, byte param) | ||
{ | ||
WriteRegister((ushort)reg, param); | ||
} | ||
|
||
private void WriteRegister(ushort reg, byte param) | ||
{ | ||
var buffer = new byte[3]; | ||
BinaryPrimitives.WriteUInt16BigEndian(buffer, reg); | ||
buffer[2] = param; | ||
Debug.WriteLine($"Writing to register 0x{reg:X4}: 0x{param:X2}"); | ||
|
||
var result = _i2cDevice.Write(buffer); | ||
if (result.Status != I2cTransferStatus.FullTransfer) | ||
{ | ||
throw new InvalidOperationException("I2C write failed"); | ||
} | ||
} | ||
|
||
private byte ReadRegister(RegisterAddresses reg) | ||
{ | ||
var writeBuffer = new byte[2]; | ||
var readBuffer = new byte[1]; | ||
BinaryPrimitives.WriteUInt16BigEndian(writeBuffer, (ushort)reg); | ||
Debug.WriteLine($"Writing register address: 0x{writeBuffer[0]:X2} 0x{writeBuffer[1]:X2}"); | ||
|
||
var result = _i2cDevice.WriteRead(writeBuffer, readBuffer); | ||
if (result.Status != I2cTransferStatus.FullTransfer) | ||
{ | ||
throw new InvalidOperationException("I2C write failed while setting register address"); | ||
} | ||
|
||
Debug.WriteLine($"Read data from register 0x{reg:X4}: 0x{readBuffer[0]:X2}"); | ||
return readBuffer[0]; | ||
} | ||
} | ||
} |
Oops, something went wrong.