Skip to content

Feature Request: Support **Adafruit LTR-390 UV/Lux STEMMA QT** sensor as a Mycodo Input #1432

@cajun1689

Description

@cajun1689

Link to hardware
https://www.adafruit.com/product/4831 (LTR-390 UV Light and Lux Sensor – STEMMA QT I2C)


🗒️ Summary

Add a new Input driver that enables Mycodo to read UVA, UVB, UV Index, and ambient‑light (lux) data from the Adafruit LTR‑390 breakout over I2C.
The sensor is inexpensive, STEMMA QT / Qwiic‑compatible, and ideal for horticulture, UV‑exposure logging, and environmental monitoring—use‑cases already popular among Mycodo users.


📐 Technical Spec

Property Value
I2C address 0x53 (fixed)
Supply voltage 3 V–5 V
Bus I2C @ 400 kHz max
Measurements • UVA raw/counts
• UVB raw/counts
UV Index (compensated)
Ambient Light (lux)
Library adafruit-circuitpython-ltr390 (MIT)
Python import import adafruit_ltr390
Typical update rate 100 ms – 2 s (configurable gain/resolution)

🏗️ Proposed Driver (mycodo/inputs/ltr390.py)

"""Input: LTR-390 UV / Light Sensor (I2C 0x53)
Dependencies: adafruit-circuitpython-ltr390
Channels:
  0 – UV Index          (float)
  1 – Ambient Lux       (float)
  2 – UVA (raw counts)  (int)
  3 – UVB (raw counts)  (int)
"""

from adafruit_ltr390 import LTR390
import board, busio
from mycodo.inputs.base_input import AbstractInput

class InputLTR390(AbstractInput):
    def __init__(self, input_dev, **kwargs):
        super().__init__(input_dev, **kwargs)
        self.i2c = busio.I2C(board.SCL, board.SDA)
        self.sensor = LTR390(self.i2c)

    def read(self):
        """Return dict {channel: value}"""
        data = {
            0: round(self.sensor.uvi, 3),       # UV Index
            1: round(self.sensor.lux, 1),       # Lux
            2: self.sensor.uva,                 # Raw counts
            3: self.sensor.uvb,                 # Raw counts
        }
        return data

Adjust channel IDs/names to match core conventions. Driver follows the standard AbstractInput pattern.

Dependencies

Add to setup.py / requirements.txt:

adafruit-circuitpython-ltr390>=1.1.0

Input configuration defaults

name: LTR-390 UV/Lux
address: 0x53
bus: I2C
channels:
  - { id: 0, label: "UV Index", unit: "", precision: 3 }
  - { id: 1, label: "Lux", unit: "lx", precision: 1 }
  - { id: 2, label: "UVA Raw", unit: "counts", precision: 0 }
  - { id: 3, label: "UVB Raw", unit: "counts", precision: 0 }
settings:
  gain: "AUTO"          # 1×–18×  (optional)
  resolution: 18        # 13-18 bit (optional)
update_interval: 10     # seconds (sane default)

Gain/resolution options can be exposed in the GUI later.


🔨 Tasks

  • Add dependency to pip requirements.
  • Implement driver inputs/ltr390.py (see stub above).
  • Register in inputs/__init__.py and the Input selection menu.
  • Create migrations to add default channels/units.
  • Docs: Add to “Supported Inputs” wiki page with wiring diagram and example config.
  • Unit tests: Mock I2C bus; verify channel keys and that read() raises no exceptions.

✅ Acceptance Criteria

  1. LTR‑390 appears in the Input dropdown.
  2. After adding and activating, live data for UV Index & Lux update at the chosen interval.
  3. No regressions to existing I2C inputs.
  4. Unit tests pass on CI.

Motivation

UV exposure, plant‑grow lights, and photobiology experiments are frequent topics in the Mycodo
community Slack/Telegram. Supporting this <$10 sensor lowers the barrier for accurate,
real‑time UV + lux monitoring.

Thanks for considering—happy to submit a PR if guidance is needed!

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions