Skip to content

Conversation

@dmarman
Copy link
Contributor

@dmarman dmarman commented May 23, 2025

This PR fixes #5980 and gives full support at the firmware level for reading UV and Lux values with the sensor LTR390UV.
The hardware sensor has been tested and the values compared with online weather stations in sunny Barcelona.

The different UI clients must update to show the UV reading. Currently with Android app, UV values will not show up however Lux readings do appear.

Due to the nature of the sensor. Lux and UV readings must be done in two passes. So for the clients, UV and Lux values are updated every two minutes.

🤝 Attestations

  • I have tested that my proposed changes behave as described.
  • I have tested that my proposed changes do not cause any obvious regressions on the following devices:
    • Heltec (Lora32) V3
    • LilyGo T-Deck
    • LilyGo T-Beam
    • RAK WisBlock 4631
    • Seeed Studio T-1000E tracker card
    • Other (please specify below)

@CLAassistant
Copy link

CLAassistant commented May 23, 2025

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
2 out of 3 committers have signed the CLA.

✅ thebentern
✅ dmarman
❌ Domingo


Domingo seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

Copy link
Member

@caveman99 caveman99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please review the logic flow as detailed.


bool LTR390UVSensor::getMetrics(meshtastic_Telemetry *measurement)
{
measurement->variant.environment_metrics.has_lux = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getMetrics is only called Once per interval. Since you are adding an IF statement you will get either the lux or the UV value. Not both. You either need to add a loop to this function or make sure you only transmit the valid part of the payload and not set both. Also constantly changing the parameters seems expensive to me. is this really neccessary? at least the resolution seems to stay the same.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll remove the resolution settings as it does not change. The problem with this sensor is that it needs different gain settings for the UV and the Lux readings (based on sunlight testing). And those readings cannot be done simultaneously.

Also, the UV reading with the characterized settings on the datasheet takes 400ms and Lux 25ms. So doing those readings in a single interval will take longer than 425ms, which I thought it is too much but maybe it is ok?
If doing like in the PR, those 425ms are not expended in the function call, but in between the 60 second interval. The sensor ADC stores the value in its register and then we can read every time a fresh new reading without waiting.

I had to set both values because if we don't do that, the app will not show both readings at the same time.

Another option is to lower the measurement rate and resolution to get measurements of 2 * 25ms = 50ms on each interval call, maybe that's also too expensive? We should consider that those faster settings are not characterized in the datasheet, and we will have to come up with a magic number without knowing if we are loosing precision.

A secondsoption is to only read UV and forget about Lux as this is the only UV sensor compatible...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggst adding caching for the 'other' value and always populate both. Then alternate reading the values every 60 seconds. Network transmits are not every 60 seconds, but much less frequently anyway, so we can make sure these go out with the 2 most current values.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also remember if your phone is not connected, these 60 seconds reads are not happening.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could alternatively implement asynchronous sampling onf the values like we do for the BME680.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggst adding caching for the 'other' value and always populate both. Then alternate reading the values every 60 seconds.

So like implemented right? I cache the readings on

float lastLuxReading = 0;
float lastUVReading = 0;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks most excellent to me now. And by the way, ignore the remaining Copilot stuff... he's a bit of a Monk...

@caveman99
Copy link
Member

Also could you sign the CLA?

@caveman99 caveman99 requested a review from Copilot May 23, 2025 13:33
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces full firmware-level support for the LTR390UV sensor to measure both UV index and Lux, fixing issue #5980.

  • Added a new LTR390UVSensor class for two-pass readings of UV and Lux.
  • Integrated the sensor into the telemetry run loop and metrics aggregation.
  • Updated project dependencies to include the Adafruit LTR390 library.

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
src/modules/Telemetry/Sensor/LTR390UVSensor.h Declared the new sensor class and its interface.
src/modules/Telemetry/Sensor/LTR390UVSensor.cpp Implemented initialization, two-pass reading logic, and metric reporting.
src/modules/Telemetry/EnvironmentTelemetry.cpp Hooked the new sensor into the environment telemetry workflow.
platformio.ini Added the Adafruit LTR390 Library to lib_deps.
Comments suppressed due to low confidence (1)

src/modules/Telemetry/Sensor/LTR390UVSensor.cpp:30

  • There are no unit tests covering the two-pass UV and Lux logic in this new sensor class. Adding tests for both modes would help ensure future changes don’t break measurement accuracy.
bool LTR390UVSensor::getMetrics(meshtastic_Telemetry *measurement)

@dmarman
Copy link
Contributor Author

dmarman commented May 23, 2025

Guys sorry I don't know what the hell I am doing with git that I am messing everything up. I signed the CLA but my email is not showing up in the commit I don't know why. I followed the vague instructions from the CLA comment, but it didn't work.

@caveman99
Copy link
Member

Guys sorry I don't know what the hell I am doing with git that I am messing everything up. I signed the CLA but my email is not showing up in the commit I don't know why. I followed the vague instructions from the CLA comment, but it didn't work.

It's fine, one of the nicks signed, that's enogh. thanks :-)

@caveman99
Copy link
Member

Though it looks like your latest commit added some dupes, if that's not intentional.

@thebentern thebentern requested review from caveman99 and Copilot May 23, 2025 14:39
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Adds firmware-level support for the LTR390UV sensor to report both UV and Lux readings in two alternating passes.

  • Introduces LTR390UVSensor with dual-mode measurement and conversion logic.
  • Integrates the new sensor into EnvironmentTelemetryModule for data collection and admin messaging.
  • Updates platformio.ini to include the Adafruit LTR390 library and bumps the PM25 AQI Sensor dependency.

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
src/modules/Telemetry/Sensor/LTR390UVSensor.h New header defining the LTR390UVSensor class
src/modules/Telemetry/Sensor/LTR390UVSensor.cpp Implementation of two-pass UV/Lux reading and conversion routines
src/modules/Telemetry/EnvironmentTelemetry.cpp Hooks LTR390UVSensor into runOnce, getEnvironmentTelemetry, and admin message handling
platformio.ini Adds adafruit/Adafruit LTR390 Library and updates PM25 AQI Sensor to v2.0.0
Comments suppressed due to low confidence (3)

src/modules/Telemetry/Sensor/LTR390UVSensor.cpp:49

  • [nitpick] The divisor 2300.f is a magic number based on datasheet characterisation. Define a constant like UVS_SENSITIVITY_FACTOR and reference the datasheet for clarity.
lastUVReading = ltr390uv.readUVS() / 2300.f;

src/modules/Telemetry/Sensor/LTR390UVSensor.cpp:12

  • [nitpick] There are no unit or integration tests covering LTR390UVSensor. Consider adding tests for the alternating UV/Lux read logic and the conversion calculations to ensure correctness.
int32_t LTR390UVSensor::runOnce()

platformio.ini:135

  • [nitpick] Upgrading to a major version (2.0.0) can introduce breaking changes. Please verify compatibility or consider pinning a minor/patch version to prevent unexpected issues.
adafruit/Adafruit PM25 AQI [email protected]

Copy link
Member

@caveman99 caveman99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

finish line here :-)

@dmarman dmarman requested a review from caveman99 May 24, 2025 09:45
@thebentern thebentern self-requested a review May 24, 2025 10:56
@thebentern thebentern merged commit cb9429e into meshtastic:master May 29, 2025
20 of 21 checks passed
@ArgoNavi
Copy link
Contributor

Bit late but would it be possible to detect if another light sensor is connected and use that for lux instead of the LTR390UV?

I plan to use both a LTR390UV and TSL2591 for sun measurements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: The LTR390V sensor is not identified

5 participants