Skip to content

Commit 7bfb633

Browse files
authored
Merge pull request #2 from BlitzCityDIY/main
new fork for PR
2 parents 951e640 + 0962a50 commit 7bfb633

File tree

5 files changed

+302
-34
lines changed

5 files changed

+302
-34
lines changed

README.rst

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,10 @@ This is easily achieved by downloading
3838
or individual libraries can be installed using
3939
`circup <https://github.com/adafruit/circup>`_.
4040

41-
42-
43-
.. todo:: Describe the Adafruit product this library works with. For PCBs, you can also add the
44-
image from the assets folder in the PCB's GitHub repo.
45-
4641
`Purchase one from the Adafruit shop <http://www.adafruit.com/products/5810>`_
4742

4843
Installing from PyPI
4944
=====================
50-
.. note:: This library is not available on PyPI yet. Install documentation is included
51-
as a standard element. Stay tuned for PyPI availability!
52-
53-
.. todo:: Remove the above note if PyPI version is/will be available at time of release.
5445

5546
On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from
5647
PyPI <https://pypi.org/project/adafruit-circuitpython-vcnl4020/>`_.
@@ -101,8 +92,21 @@ Or the following command to update an existing version:
10192
Usage Example
10293
=============
10394

104-
.. todo:: Add a quick, simple example. It and other examples should live in the
105-
examples folder and be included in docs/examples.rst.
95+
.. code-block:: python
96+
97+
import time
98+
import board
99+
import adafruit_vcnl4020
100+
101+
i2c = board.I2C()
102+
103+
# Initialize VCNL4020
104+
sensor = adafruit_vcnl4020.Adafruit_VCNL4020(i2c)
105+
106+
while True:
107+
print(f"Proximity is: {sensor.proximity}")
108+
print(f"Ambient is: {sensor.lux}")
109+
time.sleep(0.1)
106110
107111
Documentation
108112
=============

adafruit_vcnl4020.py

Lines changed: 256 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
21
# SPDX-FileCopyrightText: Copyright (c) 2023 Liz Clark for Adafruit Industries
32
#
43
# SPDX-License-Identifier: MIT
4+
5+
# Written by Liz Clark (Adafruit Industries) with OpenAI ChatGPT v4 September 25, 2023 build
6+
# https://help.openai.com/en/articles/6825453-chatgpt-release-notes
7+
8+
# https://chat.openai.com/share/f4f94c37-66a1-42d9-879b-9624c13f3e26
59
"""
610
`adafruit_vcnl4020`
711
================================================================================
@@ -16,22 +20,265 @@
1620
1721
**Hardware:**
1822
19-
.. todo:: Add links to any specific hardware product page(s), or category page(s).
20-
Use unordered list & hyperlink rST inline format: "* `Link Text <url>`_"
23+
* Adafruit VCNL4020 Proximity and Light Sensor <https://www.adafruit.com/product/5810>
2124
2225
**Software and Dependencies:**
2326
2427
* Adafruit CircuitPython firmware for the supported boards:
2528
https://circuitpython.org/downloads
2629
27-
.. todo:: Uncomment or remove the Bus Device and/or the Register library dependencies
28-
based on the library's use of either.
29-
30-
# * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
31-
# * Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register
30+
* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
31+
* Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register
3232
"""
3333

34-
# imports
34+
from micropython import const
35+
from adafruit_bus_device.i2c_device import I2CDevice
36+
from adafruit_register.i2c_struct import Struct, ROUnaryStruct
37+
from adafruit_register.i2c_bit import ROBit, RWBit
38+
from adafruit_register.i2c_bits import RWBits
39+
40+
try:
41+
import typing # pylint: disable=unused-import
42+
from busio import I2C
43+
except ImportError:
44+
pass
3545

3646
__version__ = "0.0.0+auto.0"
3747
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_VCNL4020.git"
48+
49+
_I2C_ADDRESS = const(0x13)
50+
_REG_COMMAND = const(0x80)
51+
_REG_PRODUCT_ID = const(0x81)
52+
_REG_PROX_RATE = const(0x82)
53+
_REG_IR_LED_CURRENT = const(0x83)
54+
_REG_AMBIENT_PARAM = const(0x84)
55+
_REG_AMBIENT_RESULT_HIGH = const(0x85)
56+
_REG_AMBIENT_RESULT_LOW = const(0x86)
57+
_REG_PROX_RESULT_HIGH = const(0x87)
58+
_REG_PROX_RESULT_LOW = const(0x88)
59+
_REG_INT_CTRL = const(0x89)
60+
_REG_LOW_THRES_HIGH = const(0x8A)
61+
_REG_LOW_THRES_LOW = const(0x8B)
62+
_REG_HIGH_THRES_HIGH = const(0x8C)
63+
_REG_HIGH_THRES_LOW = const(0x8D)
64+
_REG_INT_STATUS = const(0x8E)
65+
_REG_PROX_ADJUST = const(0x8F)
66+
_INT_TH_HI = const(0x01)
67+
_INT_TH_LOW = const(0x02)
68+
_INT_ALS_READY = const(0x04)
69+
_INT_PROX_READY = const(0x08)
70+
71+
72+
# pylint: disable=too-many-instance-attributes
73+
class Adafruit_VCNL4020:
74+
"""Adafruit VCNL4020 Proximity/Ambient Light sensor driver"""
75+
76+
auto_offset_comp = RWBit(_REG_AMBIENT_PARAM, 3)
77+
"""Auto offset compensation for ambient light measurement."""
78+
_command_reg = RWBits(8, _REG_COMMAND, 0)
79+
continuous_conversion = RWBit(_REG_AMBIENT_PARAM, 7)
80+
"""Continuous conversion mode for ambient light measurement."""
81+
_int_ctrl_reg = RWBits(8, _REG_INT_CTRL, 0)
82+
_int_status_reg = RWBits(3, _REG_INT_STATUS, 0)
83+
_led_current = RWBits(6, _REG_IR_LED_CURRENT, 0)
84+
_product_revision = ROUnaryStruct(_REG_PRODUCT_ID, "<B")
85+
lux = ROUnaryStruct(_REG_AMBIENT_RESULT_HIGH, ">H")
86+
"""Reads the ambient light/lux sensor (ALS) measurement result"""
87+
_lux_averaging = RWBits(3, _REG_AMBIENT_PARAM, 0)
88+
lux_enabled = RWBit(_REG_COMMAND, 2)
89+
"""Enable/disable lux sensor"""
90+
lux_on_demand = RWBit(_REG_COMMAND, 4)
91+
"""On-demand setting for lux measurements"""
92+
_lux_rate = RWBits(3, _REG_AMBIENT_PARAM, 4)
93+
lux_ready = ROBit(_REG_COMMAND, 6)
94+
"""Status of ambient light data"""
95+
proximity = ROUnaryStruct(_REG_PROX_RESULT_HIGH, ">H")
96+
"""Reads the proximity measurement result"""
97+
proximity_enabled = RWBit(_REG_COMMAND, 1)
98+
"""Enable/disable proximity sensor"""
99+
_proximity_frequency = RWBits(2, _REG_PROX_ADJUST, 3)
100+
promixity_on_demand = RWBit(_REG_COMMAND, 3)
101+
"""On-demand setting for proximity measurements"""
102+
_proximity_rate = RWBits(3, _REG_PROX_RATE, 0)
103+
proximity_ready = ROBit(_REG_COMMAND, 5)
104+
"""Status of proximity data."""
105+
low_threshold = Struct(_REG_LOW_THRES_HIGH, ">H")
106+
"""Sets the low threshold for proximity measurement"""
107+
high_threshold = Struct(_REG_HIGH_THRES_HIGH, ">H")
108+
"""Sets the high threshold for proximity measurement."""
109+
_interrupt_count = RWBits(3, _REG_INT_CTRL, 5)
110+
proximity_interrupt = RWBit(_REG_INT_CTRL, 3)
111+
"""Enable/disable proximity interrupt"""
112+
lux_interrupt = RWBit(_REG_INT_CTRL, 2)
113+
"""Enable/disable lux interrupt"""
114+
high_threshold_interrupt = RWBit(_REG_INT_CTRL, 1)
115+
"""Enable/disable proximity high threshold interrupt"""
116+
low_threshold_interrupt = RWBit(_REG_INT_CTRL, 0)
117+
"""Enable/disable proximity low threshold interrupt"""
118+
selftimed_enabled = RWBit(_REG_COMMAND, 0)
119+
"""Enable/disable selftimed reading"""
120+
121+
_proximity_rates = [1.95, 3.9, 7.8, 16.6, 31.2, 62.5, 125, 250]
122+
_lux_rates = [1, 2, 3, 4, 5, 6, 8, 10]
123+
_avg_samples = [1, 2, 4, 8, 16, 32, 64, 128]
124+
_int_counts = [1, 2, 4, 8, 16, 32, 64, 128]
125+
_proximity_frequencies = [390.625, 781.25, 1.5625, 3.125]
126+
127+
def __init__(self, i2c: I2C, addr: int = _I2C_ADDRESS) -> None:
128+
"""
129+
Initializes the VCNL4020 sensor and checks for a valid Product ID Revision.
130+
:param i2c: The I2C interface to use
131+
:param addr: The I2C address of the VCNL4020, defaults to _I2C_ADDRESS
132+
"""
133+
self.i2c_device = I2CDevice(i2c, addr)
134+
135+
# Check the Product ID Revision
136+
if self._product_revision != 0x21:
137+
raise RuntimeError(f"Invalid Product ID Revision {self._product_revision}")
138+
try:
139+
# Configuration settings
140+
self.proximity_rate = 250
141+
self.led_current = 200
142+
self.lux_rate = 10
143+
self.lux_averaging = 1
144+
except Exception as error:
145+
raise RuntimeError(f"Failed to initialize: {error}") from error
146+
147+
@property
148+
def _enable(self) -> bool:
149+
return self.lux_enabled and self.proximity_enabled and self.selftimed_enabled
150+
151+
@_enable.setter
152+
def _enable(self, value: bool) -> None:
153+
self.lux_enabled = value
154+
self.proximity_enabled = value
155+
self.selftimed_enabled = value
156+
157+
@property
158+
def clear_interrupts(self) -> None:
159+
"""
160+
Clears the interrupt flags.
161+
162+
:param value: True to clear all interrupt flags.
163+
"""
164+
clear_bits = 0
165+
clear_bits |= _INT_PROX_READY
166+
clear_bits |= _INT_ALS_READY
167+
clear_bits |= _INT_TH_LOW
168+
clear_bits |= _INT_TH_HI
169+
self._int_status_reg |= clear_bits
170+
171+
@property
172+
def interrupt_count(self) -> int:
173+
"""
174+
Interrupt count setting
175+
176+
:rtype: int
177+
"""
178+
return self._int_counts[self._interrupt_count]
179+
180+
@interrupt_count.setter
181+
def interrupt_count(self, value: int) -> None:
182+
self._enable = False
183+
if value not in self._int_counts:
184+
raise ValueError(
185+
f"Invalid interrupt count: {value}. Available counts: {self._int_counts}"
186+
)
187+
count = self._int_counts.index(value)
188+
self._interrupt_count = count
189+
self._enable = True
190+
191+
@property
192+
def led_current(self) -> int:
193+
"""
194+
The LED current for proximity mode in mA.
195+
196+
:return: The LED current in mA.
197+
"""
198+
return self._led_current * 10
199+
200+
@led_current.setter
201+
def led_current(self, value: int) -> None:
202+
self._enable = False
203+
self._led_current = value // 10
204+
self._enable = True
205+
206+
@property
207+
def lux_averaging(self) -> int:
208+
"""
209+
Ambient averaging sample rate
210+
211+
:rtype: int
212+
"""
213+
return self._avg_samples[self._lux_averaging]
214+
215+
@lux_averaging.setter
216+
def lux_averaging(self, value: int) -> None:
217+
self._enable = False
218+
if value not in self._avg_samples:
219+
raise ValueError(
220+
f"Invalid sample rate: {value}. Available sample rates: {self._avg_samples}"
221+
)
222+
sample_rate = self._avg_samples.index(value)
223+
self._lux_averaging = sample_rate
224+
self._enable = True
225+
226+
@property
227+
def lux_rate(self) -> int:
228+
"""
229+
Ambient light measurement rate
230+
231+
:rtype: int
232+
"""
233+
return self._lux_rates[self._lux_rate]
234+
235+
@lux_rate.setter
236+
def lux_rate(self, value: int) -> None:
237+
self._enable = False
238+
if value not in self._lux_rates:
239+
raise ValueError(
240+
f"Invalid ambient rate: {value}. Available rates: {self._lux_rates}"
241+
)
242+
rate = self._lux_rates.index(value)
243+
self._lux_rate = rate
244+
self._enable = True
245+
246+
@property
247+
def proximity_frequency(self) -> int:
248+
"""
249+
Proximity frequency setting
250+
251+
:rtype: int
252+
"""
253+
return self._proximity_frequencies[self._proximity_frequency]
254+
255+
@proximity_frequency.setter
256+
def proximity_frequency(self, value: int) -> None:
257+
self._enable = False
258+
if value not in self._proximity_frequencies:
259+
raise ValueError(
260+
f"Invalid frequency: {value}. Available frequencies: {self._proximity_frequencies}"
261+
)
262+
freq = self._proximity_frequencies.index(value)
263+
self._proximity_frequency = freq
264+
self._enable = True
265+
266+
@property
267+
def proximity_rate(self) -> int:
268+
"""
269+
Proximity measurement rate
270+
271+
:rtype: int
272+
"""
273+
return self._proximity_rates[self._proximity_rate]
274+
275+
@proximity_rate.setter
276+
def proximity_rate(self, value: int) -> None:
277+
self._enable = False
278+
if value not in self._proximity_rates:
279+
raise ValueError(
280+
f"Invalid proximity rate: {value}. Available rates: {self._proximity_rates}"
281+
)
282+
rate = self._proximity_rates.index(value)
283+
self._proximity_rate = rate
284+
self._enable = True

docs/conf.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,19 @@
2323
"sphinx.ext.todo",
2424
]
2525

26-
# TODO: Please Read!
27-
# Uncomment the below if you use native CircuitPython modules such as
28-
# digitalio, micropython and busio. List the modules you use. Without it, the
29-
# autodoc module docs will fail to generate with a warning.
30-
# autodoc_mock_imports = ["digitalio", "busio"]
26+
autodoc_mock_imports = [
27+
"micropython",
28+
"busio",
29+
"adafruit_bus_device",
30+
"adafruit_register",
31+
]
3132

3233
autodoc_preserve_defaults = True
3334

3435

3536
intersphinx_mapping = {
36-
"python": ("https://docs.python.org/3", None),"BusDevice": ("https://docs.circuitpython.org/projects/busdevice/en/latest/", None),
37+
"python": ("https://docs.python.org/3", None),
38+
"BusDevice": ("https://docs.circuitpython.org/projects/busdevice/en/latest/", None),
3739
"Register": ("https://docs.circuitpython.org/projects/register/en/latest/", None),
3840
"CircuitPython": ("https://docs.circuitpython.org/en/latest/", None),
3941
}

docs/index.rst

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,12 @@ Table of Contents
2424
.. toctree::
2525
:caption: Tutorials
2626

27-
.. todo:: Add any Learn guide links here. If there are none, then simply delete this todo and leave
28-
the toctree above for use later.
27+
Adafruit VCNL4020 Breakout Board Learn Guide <https://learn.adafruit.com/adafruit-vcnl4020-proximity-and-light-sensor>
2928

3029
.. toctree::
3130
:caption: Related Products
3231

33-
.. todo:: Add any product links here. If there are none, then simply delete this todo and leave
34-
the toctree above for use later.
32+
Adafruit VCNL4020 Proximity and Light Sensor <https://www.adafruit.com/product/5810>
3533

3634
.. toctree::
3735
:caption: Other Links

examples/vcnl4020_simpletest.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,21 @@
1-
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
2-
# SPDX-FileCopyrightText: Copyright (c) 2023 Liz Clark for Adafruit Industries
3-
#
4-
# SPDX-License-Identifier: Unlicense
1+
# SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries
2+
# SPDX-License-Identifier: MIT
3+
4+
# Simple demo to read ambient light/lux
5+
# and proximity data from VCNL4020 over I2C
6+
7+
import time
8+
import board
9+
import adafruit_vcnl4020
10+
11+
i2c = board.I2C()
12+
13+
# Initialize VCNL4020
14+
sensor = adafruit_vcnl4020.Adafruit_VCNL4020(i2c)
15+
16+
while True:
17+
print(f"Proximity is: {sensor.proximity}")
18+
print(f"Ambient is: {sensor.lux}")
19+
# uncomment print statement below to log to Mu plotter
20+
# print((sensor.proximity, sensor.lux,))
21+
time.sleep(0.1)

0 commit comments

Comments
 (0)