Source code for micropython_tcs3430.tcs3430

# SPDX-FileCopyrightText: Copyright (c) 2023 Jose D. Montoya
#
# SPDX-License-Identifier: MIT
"""
`tcs3430`
================================================================================

MicroPython driver for the AMS TCS3430 Color and ALS sensor


* Author(s): Jose D. Montoya


"""

from micropython import const
from micropython_tcs3430.i2c_helpers import CBits, RegisterStruct

__version__ = "0.0.0+auto.0"
__repo__ = "https://github.com/jposada202020/MicroPython_TCS3430.git"

_REG_WHOAMI = const(0x92)
_ENABLE_REGISTER = const(0x80)
_TIME = const(0x81)
_WTIME = const(0x82)
_CFG0 = const(0x8D)
_CFG1 = const(0x90)
_DATA = const(0x94)

DISABLED = const(0b00)
ENABLED = const(0b11)
operation_mode_values = (DISABLED, ENABLED)

ALS_GAIN1 = const(0b00)
ALS_GAIN4 = const(0b01)
ALS_GAIN16 = const(0b10)
ALS_GAIN64 = const(0b11)
als_gain_values = (ALS_GAIN1, ALS_GAIN4, ALS_GAIN16, ALS_GAIN64)


[docs] class TCS3430: """Driver for the TCS3430 Sensor connected over I2C. Ambient Light Sensing (ALS) and CIE 1931 Tristimulus Color Sensing (XYZ). These measurements can be used to calculate chromaticity, :param ~machine.I2C i2c: The I2C bus the TCS3430 is connected to. :param int address: The I2C device address. Defaults to :const:`0x39` :raises RuntimeError: if the sensor is not found **Quickstart: Importing and using the device** Here is an example of using the :class:`TCS3430` class. First you will need to import the libraries to use the sensor .. code-block:: python from machine import Pin, I2C from micropython_tcs3430 import tcs3430 Once this is done you can define your `machine.I2C` object and define your sensor object .. code-block:: python i2c = I2C(1, sda=Pin(2), scl=Pin(3)) tcs = tcs3430.TCS3430(i2c) Now you have access to the attributes .. code-block:: python tcs = tcs.measurements """ _device_id = RegisterStruct(_REG_WHOAMI, "B") info_needed = RegisterStruct(_ENABLE_REGISTER, "B") _operation_mode = CBits(2, _ENABLE_REGISTER, 0) _integration_time = RegisterStruct(_TIME, "B") _als_wait_time = RegisterStruct(_WTIME, "B") _wait_long = CBits(1, _CFG0, 2) _als_gain = CBits(2, _CFG1, 0) _raw_data = RegisterStruct(_DATA, ">HHHH") _waiting_times = {0: 2.78, 1: 33.4} def __init__(self, i2c, address: int = 0x39) -> None: self._i2c = i2c self._address = address if self._device_id != 0xDC: raise RuntimeError("Failed to find TCS3430") self._operation_mode = ENABLED @property def operation_mode(self) -> str: """ Sensor operation_mode +------------------------------+------------------+ | Mode | Value | +==============================+==================+ | :py:const:`tcs3430.DISABLED` | :py:const:`0b00` | +------------------------------+------------------+ | :py:const:`tcs3430.ENABLED` | :py:const:`0b11` | +------------------------------+------------------+ """ values = ("DISABLED", "ENABLED") return values[self._operation_mode] @operation_mode.setter def operation_mode(self, value: int) -> None: if value not in operation_mode_values: raise ValueError("Value must be a valid operation_mode setting") self._operation_mode = value @property def integration_time(self) -> float: """ Integration time in 2.78ms intervals. 0x00 indicates 2.78ms, 0x01 indicates 5.56ms. The maximum ALS value depends on the integration time. For every 2.78ms, the maximum value increases by 1024. This means that to be able to reach ALS full scale, the integration time has to be at least 64*2.78ms. """ return self._integration_time * 2.78 @integration_time.setter def integration_time(self, value: float) -> None: if value > 711 or value < 2.78: raise ValueError("Value must be a valid integration_time setting") self._integration_time = int(value / 2.78) @property def als_wait_time(self) -> float: """ The wait timer is implemented with a down counter with 0x00 as the terminal count. Loading 0x00 will generate a 2.78ms wait time, loading 0x01 will generate a 5.56ms wait time, and so forth; By asserting wlong, in register 0x8D the wait time is given in multiples of 33.4ms (12x) """ return self._als_wait_time * self._waiting_times[self._wait_long] @als_wait_time.setter def als_wait_time(self, value: float) -> None: if self._wait_long: if value > 711 or value < 2.78: raise ValueError("Value must be a valid als_wait_time setting") else: if value > 23747 or value < 33.4: raise ValueError("Value must be a valid als_wait_time setting") self._als_wait_time = int(value / self._waiting_times[self._wait_long]) @property def als_gain(self) -> str: """ Sensor als_gain +--------------------------------+------------------+ | Mode | Value | +================================+==================+ | :py:const:`tcs3430.ALS_GAIN1` | :py:const:`0b00` | +--------------------------------+------------------+ | :py:const:`tcs3430.ALS_GAIN4` | :py:const:`0b01` | +--------------------------------+------------------+ | :py:const:`tcs3430.ALS_GAIN16` | :py:const:`0b10` | +--------------------------------+------------------+ | :py:const:`tcs3430.ALS_GAIN64` | :py:const:`0b11` | +--------------------------------+------------------+ """ values = ("ALS_GAIN1", "ALS_GAIN4", "ALS_GAIN16", "ALS_GAIN64") return values[self._als_gain] @als_gain.setter def als_gain(self, value: int) -> None: if value not in als_gain_values: raise ValueError("Value must be a valid als_gain setting") self._als_gain = value @property def measurements(self): """ Return ALS values """ als_z, als_y, ir1_value, als_x = self._raw_data return als_z, als_y, als_x, ir1_value