Skip to content

Commit 33758f8

Browse files
authored
Merge pull request #22 from tekktrik/feature/add-manual-offset
Add offset setting, add type hints
2 parents feb10e4 + 4fa94ae commit 33758f8

File tree

3 files changed

+70
-9
lines changed

3 files changed

+70
-9
lines changed

adafruit_vl6180x.py

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,17 @@
2525
https://github.com/adafruit/circuitpython/releases
2626
* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
2727
"""
28+
import struct
2829
from micropython import const
2930

3031
from adafruit_bus_device import i2c_device
3132

33+
try:
34+
import typing # pylint: disable=unused-import
35+
from busio import I2C
36+
except ImportError:
37+
pass
38+
3239

3340
__version__ = "0.0.0-auto.0"
3441
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_VL6180X.git"
@@ -49,6 +56,7 @@
4956
_VL6180X_REG_RESULT_RANGE_VAL = const(0x062)
5057
_VL6180X_REG_RESULT_RANGE_STATUS = const(0x04D)
5158
_VL6180X_REG_RESULT_INTERRUPT_STATUS_GPIO = const(0x04F)
59+
_VL6180X_REG_SYSRANGE_PART_TO_PART_RANGE_OFFSET = const(0x024)
5260

5361
# User-facing constants:
5462
ALS_GAIN_1 = const(0x06)
@@ -85,15 +93,18 @@ class VL6180X:
8593
default value will be assumed.
8694
"""
8795

88-
def __init__(self, i2c, address=_VL6180X_DEFAULT_I2C_ADDR):
96+
def __init__(
97+
self, i2c: I2C, address: int = _VL6180X_DEFAULT_I2C_ADDR, offset: int = 0
98+
) -> None:
8999
self._device = i2c_device.I2CDevice(i2c, address)
90100
if self._read_8(_VL6180X_REG_IDENTIFICATION_MODEL_ID) != 0xB4:
91101
raise RuntimeError("Could not find VL6180X, is it connected and powered?")
92102
self._load_settings()
93103
self._write_8(_VL6180X_REG_SYSTEM_FRESH_OUT_OF_RESET, 0x00)
104+
self.offset = offset
94105

95106
@property
96-
def range(self):
107+
def range(self) -> int:
97108
"""Read the range of an object in front of sensor and return it in mm."""
98109
# wait for device to be ready for range measurement
99110
while not self._read_8(_VL6180X_REG_RESULT_RANGE_STATUS) & 0x01:
@@ -109,7 +120,19 @@ def range(self):
109120
self._write_8(_VL6180X_REG_SYSTEM_INTERRUPT_CLEAR, 0x07)
110121
return range_
111122

112-
def read_lux(self, gain):
123+
@property
124+
def offset(self) -> int:
125+
"""Read and sets the manual offset for the sensor, in millimeters"""
126+
return self._offset
127+
128+
@offset.setter
129+
def offset(self, offset: int) -> None:
130+
self._write_8(
131+
_VL6180X_REG_SYSRANGE_PART_TO_PART_RANGE_OFFSET, struct.pack("b", offset)[0]
132+
)
133+
self._offset = offset
134+
135+
def read_lux(self, gain: int) -> float:
113136
"""Read the lux (light value) from the sensor and return it. Must
114137
specify the gain value to use for the lux reading:
115138
- ALS_GAIN_1 = 1x
@@ -164,7 +187,7 @@ def read_lux(self, gain):
164187
return lux
165188

166189
@property
167-
def range_status(self):
190+
def range_status(self) -> int:
168191
"""Retrieve the status/error from a previous range read. This will
169192
return a constant value such as:
170193
@@ -182,7 +205,7 @@ def range_status(self):
182205
"""
183206
return self._read_8(_VL6180X_REG_RESULT_RANGE_STATUS) >> 4
184207

185-
def _load_settings(self):
208+
def _load_settings(self) -> None:
186209
# private settings from page 24 of app note
187210
self._write_8(0x0207, 0x01)
188211
self._write_8(0x0208, 0x01)
@@ -238,12 +261,12 @@ def _load_settings(self):
238261
self._write_8(0x0014, 0x24) # Configures interrupt on 'New Sample
239262
# Ready threshold event'
240263

241-
def _write_8(self, address, data):
264+
def _write_8(self, address: int, data: int) -> None:
242265
# Write 1 byte of data from the specified 16-bit register address.
243266
with self._device:
244267
self._device.write(bytes([(address >> 8) & 0xFF, address & 0xFF, data]))
245268

246-
def _write_16(self, address, data):
269+
def _write_16(self, address: int, data: int) -> None:
247270
# Write a 16-bit big endian value to the specified 16-bit register
248271
# address.
249272
with self._device as i2c:
@@ -258,15 +281,15 @@ def _write_16(self, address, data):
258281
)
259282
)
260283

261-
def _read_8(self, address):
284+
def _read_8(self, address: int) -> int:
262285
# Read and return a byte from the specified 16-bit register address.
263286
with self._device as i2c:
264287
result = bytearray(1)
265288
i2c.write(bytes([(address >> 8) & 0xFF, address & 0xFF]))
266289
i2c.readinto(result)
267290
return result[0]
268291

269-
def _read_16(self, address):
292+
def _read_16(self, address: int) -> int:
270293
# Read and return a 16-bit unsigned big endian value read from the
271294
# specified 16-bit register address.
272295
with self._device as i2c:

examples/vl6180x_calibrationtest.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# SPDX-FileCopyrightText: 2018 Tony DiCola for Adafruit Industries
2+
# SPDX-License-Identifier: MIT
3+
4+
# Demo of calibrating the part to part range offset per Application Note 4545
5+
# for the VL6180X sensor
6+
7+
import time
8+
9+
import board
10+
import busio
11+
12+
import adafruit_vl6180x
13+
14+
15+
# Create I2C bus.
16+
i2c = busio.I2C(board.SCL, board.SDA)
17+
18+
# Create sensor instance, with explicit offset of 0 to clear the system offset
19+
sensor = adafruit_vl6180x.VL6180X(i2c, offset=0)
20+
21+
# Place a target at 50mm away from VL6180X Collect a number of range measurements
22+
# with the target in place and calculate mean of the range reseults. For a
23+
# reliable measurement, take at least 10 measurements.
24+
measurements = []
25+
for msmt in range(10):
26+
range_mm = sensor.range
27+
measurements.append(range_mm)
28+
time.sleep(1.0)
29+
average_msmt = sum(measurements) / 10
30+
31+
# Calculate the offset required:
32+
calibration_offset = 50 - average_msmt
33+
34+
# Apply offset
35+
sensor.offset = calibration_offset

examples/vl6180x_simpletest.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717

1818
# Create sensor instance.
1919
sensor = adafruit_vl6180x.VL6180X(i2c)
20+
# You can add an offset to distance measurements here (e.g. calibration)
21+
# Swapping for the following would add a +10 millimeter offset to measurements:
22+
# sensor = adafruit_vl6180x.VL6180X(i2c, offset=10)
2023

2124
# Main loop prints the range and lux every second:
2225
while True:

0 commit comments

Comments
 (0)