Skip to content

Commit

Permalink
Merge pull request #2 from BlitzCityDIY/main
Browse files Browse the repository at this point in the history
new fork for PR
  • Loading branch information
tannewt committed Oct 31, 2023
2 parents 951e640 + 0962a50 commit 7bfb633
Show file tree
Hide file tree
Showing 5 changed files with 302 additions and 34 deletions.
26 changes: 15 additions & 11 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,10 @@ This is easily achieved by downloading
or individual libraries can be installed using
`circup <https://github.com/adafruit/circup>`_.



.. todo:: Describe the Adafruit product this library works with. For PCBs, you can also add the
image from the assets folder in the PCB's GitHub repo.

`Purchase one from the Adafruit shop <http://www.adafruit.com/products/5810>`_

Installing from PyPI
=====================
.. note:: This library is not available on PyPI yet. Install documentation is included
as a standard element. Stay tuned for PyPI availability!

.. todo:: Remove the above note if PyPI version is/will be available at time of release.

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

.. todo:: Add a quick, simple example. It and other examples should live in the
examples folder and be included in docs/examples.rst.
.. code-block:: python
import time
import board
import adafruit_vcnl4020
i2c = board.I2C()
# Initialize VCNL4020
sensor = adafruit_vcnl4020.Adafruit_VCNL4020(i2c)
while True:
print(f"Proximity is: {sensor.proximity}")
print(f"Ambient is: {sensor.lux}")
time.sleep(0.1)
Documentation
=============
Expand Down
265 changes: 256 additions & 9 deletions adafruit_vcnl4020.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
# SPDX-FileCopyrightText: Copyright (c) 2023 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: MIT

# Written by Liz Clark (Adafruit Industries) with OpenAI ChatGPT v4 September 25, 2023 build
# https://help.openai.com/en/articles/6825453-chatgpt-release-notes

# https://chat.openai.com/share/f4f94c37-66a1-42d9-879b-9624c13f3e26
"""
`adafruit_vcnl4020`
================================================================================
Expand All @@ -16,22 +20,265 @@
**Hardware:**
.. todo:: Add links to any specific hardware product page(s), or category page(s).
Use unordered list & hyperlink rST inline format: "* `Link Text <url>`_"
* Adafruit VCNL4020 Proximity and Light Sensor <https://www.adafruit.com/product/5810>
**Software and Dependencies:**
* Adafruit CircuitPython firmware for the supported boards:
https://circuitpython.org/downloads
.. todo:: Uncomment or remove the Bus Device and/or the Register library dependencies
based on the library's use of either.
# * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
# * Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register
* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
* Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register
"""

# imports
from micropython import const
from adafruit_bus_device.i2c_device import I2CDevice
from adafruit_register.i2c_struct import Struct, ROUnaryStruct
from adafruit_register.i2c_bit import ROBit, RWBit
from adafruit_register.i2c_bits import RWBits

try:
import typing # pylint: disable=unused-import
from busio import I2C
except ImportError:
pass

__version__ = "0.0.0+auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_VCNL4020.git"

_I2C_ADDRESS = const(0x13)
_REG_COMMAND = const(0x80)
_REG_PRODUCT_ID = const(0x81)
_REG_PROX_RATE = const(0x82)
_REG_IR_LED_CURRENT = const(0x83)
_REG_AMBIENT_PARAM = const(0x84)
_REG_AMBIENT_RESULT_HIGH = const(0x85)
_REG_AMBIENT_RESULT_LOW = const(0x86)
_REG_PROX_RESULT_HIGH = const(0x87)
_REG_PROX_RESULT_LOW = const(0x88)
_REG_INT_CTRL = const(0x89)
_REG_LOW_THRES_HIGH = const(0x8A)
_REG_LOW_THRES_LOW = const(0x8B)
_REG_HIGH_THRES_HIGH = const(0x8C)
_REG_HIGH_THRES_LOW = const(0x8D)
_REG_INT_STATUS = const(0x8E)
_REG_PROX_ADJUST = const(0x8F)
_INT_TH_HI = const(0x01)
_INT_TH_LOW = const(0x02)
_INT_ALS_READY = const(0x04)
_INT_PROX_READY = const(0x08)


# pylint: disable=too-many-instance-attributes
class Adafruit_VCNL4020:
"""Adafruit VCNL4020 Proximity/Ambient Light sensor driver"""

auto_offset_comp = RWBit(_REG_AMBIENT_PARAM, 3)
"""Auto offset compensation for ambient light measurement."""
_command_reg = RWBits(8, _REG_COMMAND, 0)
continuous_conversion = RWBit(_REG_AMBIENT_PARAM, 7)
"""Continuous conversion mode for ambient light measurement."""
_int_ctrl_reg = RWBits(8, _REG_INT_CTRL, 0)
_int_status_reg = RWBits(3, _REG_INT_STATUS, 0)
_led_current = RWBits(6, _REG_IR_LED_CURRENT, 0)
_product_revision = ROUnaryStruct(_REG_PRODUCT_ID, "<B")
lux = ROUnaryStruct(_REG_AMBIENT_RESULT_HIGH, ">H")
"""Reads the ambient light/lux sensor (ALS) measurement result"""
_lux_averaging = RWBits(3, _REG_AMBIENT_PARAM, 0)
lux_enabled = RWBit(_REG_COMMAND, 2)
"""Enable/disable lux sensor"""
lux_on_demand = RWBit(_REG_COMMAND, 4)
"""On-demand setting for lux measurements"""
_lux_rate = RWBits(3, _REG_AMBIENT_PARAM, 4)
lux_ready = ROBit(_REG_COMMAND, 6)
"""Status of ambient light data"""
proximity = ROUnaryStruct(_REG_PROX_RESULT_HIGH, ">H")
"""Reads the proximity measurement result"""
proximity_enabled = RWBit(_REG_COMMAND, 1)
"""Enable/disable proximity sensor"""
_proximity_frequency = RWBits(2, _REG_PROX_ADJUST, 3)
promixity_on_demand = RWBit(_REG_COMMAND, 3)
"""On-demand setting for proximity measurements"""
_proximity_rate = RWBits(3, _REG_PROX_RATE, 0)
proximity_ready = ROBit(_REG_COMMAND, 5)
"""Status of proximity data."""
low_threshold = Struct(_REG_LOW_THRES_HIGH, ">H")
"""Sets the low threshold for proximity measurement"""
high_threshold = Struct(_REG_HIGH_THRES_HIGH, ">H")
"""Sets the high threshold for proximity measurement."""
_interrupt_count = RWBits(3, _REG_INT_CTRL, 5)
proximity_interrupt = RWBit(_REG_INT_CTRL, 3)
"""Enable/disable proximity interrupt"""
lux_interrupt = RWBit(_REG_INT_CTRL, 2)
"""Enable/disable lux interrupt"""
high_threshold_interrupt = RWBit(_REG_INT_CTRL, 1)
"""Enable/disable proximity high threshold interrupt"""
low_threshold_interrupt = RWBit(_REG_INT_CTRL, 0)
"""Enable/disable proximity low threshold interrupt"""
selftimed_enabled = RWBit(_REG_COMMAND, 0)
"""Enable/disable selftimed reading"""

_proximity_rates = [1.95, 3.9, 7.8, 16.6, 31.2, 62.5, 125, 250]
_lux_rates = [1, 2, 3, 4, 5, 6, 8, 10]
_avg_samples = [1, 2, 4, 8, 16, 32, 64, 128]
_int_counts = [1, 2, 4, 8, 16, 32, 64, 128]
_proximity_frequencies = [390.625, 781.25, 1.5625, 3.125]

def __init__(self, i2c: I2C, addr: int = _I2C_ADDRESS) -> None:
"""
Initializes the VCNL4020 sensor and checks for a valid Product ID Revision.
:param i2c: The I2C interface to use
:param addr: The I2C address of the VCNL4020, defaults to _I2C_ADDRESS
"""
self.i2c_device = I2CDevice(i2c, addr)

# Check the Product ID Revision
if self._product_revision != 0x21:
raise RuntimeError(f"Invalid Product ID Revision {self._product_revision}")
try:
# Configuration settings
self.proximity_rate = 250
self.led_current = 200
self.lux_rate = 10
self.lux_averaging = 1
except Exception as error:
raise RuntimeError(f"Failed to initialize: {error}") from error

@property
def _enable(self) -> bool:
return self.lux_enabled and self.proximity_enabled and self.selftimed_enabled

@_enable.setter
def _enable(self, value: bool) -> None:
self.lux_enabled = value
self.proximity_enabled = value
self.selftimed_enabled = value

@property
def clear_interrupts(self) -> None:
"""
Clears the interrupt flags.
:param value: True to clear all interrupt flags.
"""
clear_bits = 0
clear_bits |= _INT_PROX_READY
clear_bits |= _INT_ALS_READY
clear_bits |= _INT_TH_LOW
clear_bits |= _INT_TH_HI
self._int_status_reg |= clear_bits

@property
def interrupt_count(self) -> int:
"""
Interrupt count setting
:rtype: int
"""
return self._int_counts[self._interrupt_count]

@interrupt_count.setter
def interrupt_count(self, value: int) -> None:
self._enable = False
if value not in self._int_counts:
raise ValueError(
f"Invalid interrupt count: {value}. Available counts: {self._int_counts}"
)
count = self._int_counts.index(value)
self._interrupt_count = count
self._enable = True

@property
def led_current(self) -> int:
"""
The LED current for proximity mode in mA.
:return: The LED current in mA.
"""
return self._led_current * 10

@led_current.setter
def led_current(self, value: int) -> None:
self._enable = False
self._led_current = value // 10
self._enable = True

@property
def lux_averaging(self) -> int:
"""
Ambient averaging sample rate
:rtype: int
"""
return self._avg_samples[self._lux_averaging]

@lux_averaging.setter
def lux_averaging(self, value: int) -> None:
self._enable = False
if value not in self._avg_samples:
raise ValueError(
f"Invalid sample rate: {value}. Available sample rates: {self._avg_samples}"
)
sample_rate = self._avg_samples.index(value)
self._lux_averaging = sample_rate
self._enable = True

@property
def lux_rate(self) -> int:
"""
Ambient light measurement rate
:rtype: int
"""
return self._lux_rates[self._lux_rate]

@lux_rate.setter
def lux_rate(self, value: int) -> None:
self._enable = False
if value not in self._lux_rates:
raise ValueError(
f"Invalid ambient rate: {value}. Available rates: {self._lux_rates}"
)
rate = self._lux_rates.index(value)
self._lux_rate = rate
self._enable = True

@property
def proximity_frequency(self) -> int:
"""
Proximity frequency setting
:rtype: int
"""
return self._proximity_frequencies[self._proximity_frequency]

@proximity_frequency.setter
def proximity_frequency(self, value: int) -> None:
self._enable = False
if value not in self._proximity_frequencies:
raise ValueError(
f"Invalid frequency: {value}. Available frequencies: {self._proximity_frequencies}"
)
freq = self._proximity_frequencies.index(value)
self._proximity_frequency = freq
self._enable = True

@property
def proximity_rate(self) -> int:
"""
Proximity measurement rate
:rtype: int
"""
return self._proximity_rates[self._proximity_rate]

@proximity_rate.setter
def proximity_rate(self, value: int) -> None:
self._enable = False
if value not in self._proximity_rates:
raise ValueError(
f"Invalid proximity rate: {value}. Available rates: {self._proximity_rates}"
)
rate = self._proximity_rates.index(value)
self._proximity_rate = rate
self._enable = True
14 changes: 8 additions & 6 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,19 @@
"sphinx.ext.todo",
]

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

autodoc_preserve_defaults = True


intersphinx_mapping = {
"python": ("https://docs.python.org/3", None),"BusDevice": ("https://docs.circuitpython.org/projects/busdevice/en/latest/", None),
"python": ("https://docs.python.org/3", None),
"BusDevice": ("https://docs.circuitpython.org/projects/busdevice/en/latest/", None),
"Register": ("https://docs.circuitpython.org/projects/register/en/latest/", None),
"CircuitPython": ("https://docs.circuitpython.org/en/latest/", None),
}
Expand Down
6 changes: 2 additions & 4 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,12 @@ Table of Contents
.. toctree::
:caption: Tutorials

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

.. toctree::
:caption: Related Products

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

.. toctree::
:caption: Other Links
Expand Down
25 changes: 21 additions & 4 deletions examples/vcnl4020_simpletest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
# SPDX-FileCopyrightText: Copyright (c) 2023 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
# SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries
# SPDX-License-Identifier: MIT

# Simple demo to read ambient light/lux
# and proximity data from VCNL4020 over I2C

import time
import board
import adafruit_vcnl4020

i2c = board.I2C()

# Initialize VCNL4020
sensor = adafruit_vcnl4020.Adafruit_VCNL4020(i2c)

while True:
print(f"Proximity is: {sensor.proximity}")
print(f"Ambient is: {sensor.lux}")
# uncomment print statement below to log to Mu plotter
# print((sensor.proximity, sensor.lux,))
time.sleep(0.1)

0 comments on commit 7bfb633

Please sign in to comment.