adafruit / Adafruit_CircuitPython_LTR390

CircuitPython library for the LTR390 ambient light and UV sensor
MIT License
7 stars 2 forks source link

What are the Units of Measure? #2

Closed DonBower closed 3 years ago

DonBower commented 3 years ago

The examples refer to ltr.uvs and ltr.light, but I am having difficulty expressing these values. Are they in milliwatts per square centimeter (mW/cm2), or millijoules per square centimeter (mJ/cm2), or some other factor. It is apparent from the Update uv_index to uvs commit, the .uvs was thought to be a UV Index, but I cannot find what the new unit of measurement is. In Short, what do these two numbers represent?

ladyada commented 3 years ago

nope, they are unitless 'counts' - some sensors give lux or uvi - these do not. they just measure 'how much light the sensors got' which can then be calibrated against a known source if you want.

@jedgarpark did you come up with a rough count-to-UVI metric?

jedgarpark commented 3 years ago

@ladyada @DonBower The CircuitPython library defaults the board to 3x gain, 16-bit values where a count of 95 is one UVI. This doesn't include the cloud, window, or altitude factors. And, it'll be different if you set to a different gain/bit-depth. @CedarGroveStudios said he may be looking into adding the conversion to the library.

CedarGroveStudios commented 3 years ago

@ladyada @DonBower @jedgarpark The datasheet indicates a linear relationship between the factors that JP mentioned. I had planned to suggest a UVI getter for the library but don't have a sensor on-hand to test. JP: can I send you a modified library for testing? ... sometime this evening. I have quite a few drifts of fresh snow to clear today.

jedgarpark commented 3 years ago

@CedarGroveStudios that sounds great, happy to test. No hurry -- beware the ice weasels

DonBower commented 3 years ago

I’ll be happy to share results from an end user perspective.

CedarGroveStudios commented 3 years ago

After further reading, there may be an issue with the library's 100ms integration time default versus the 25ms acquisition time for 16-bit data. Since I'm anticipating a few troubleshooting steps, it'll be a more efficient use of time if I have one in-hand. They're currently out-of-stock. I'll place an order when they become available.

I'm thinking that the rule of thumb of 1 UVI = 95 counts @ 16-bit, x3 gain, 100ms integration is okay for now since the relationship between the count value, irradiation level (uW/cm^2), and UVI is purported to be linear. JP's empirical tests using that factor showed that the count values were approximately within range.

No ice weasel surprises today.

DonBower commented 3 years ago

@ladyada @jedgarpark @CedarGroveStudios From what I can glean from the code, and I am somewhat speculating here because I don't have experience in writing drivers, it appears that I have all the defaults you mentioned above set for my sensor:

>>> print(ltr.gain)
1
>>> print(ltr.resolution)
4
>>> print(ltr.measurement_delay)
2

So to check for understanding, with these settings, the ltr.uvs value is expressed in uW/cm^2, and if I divide that by 95, i can get a UV Index number. Do I have that correct?

FYI, in the EPAs guide to the UV Index, document page 5, it states One UV Index unit is equivalent to 25 milliWatts per square meter. 25mW/m^2 (isn't this 2.5uw/cm^2?)

CedarGroveStudios commented 3 years ago

@DonBower @ladyada @jedgarpark: Yes, you discovered the values used to set the internal registers to the driver library defaults. The "decoder rings" for the classes Gain, Resolution, and Measurement_Delay look like this:

Gain    Register_Value
 1X     0
 3X     1  (library default)
 6X     2
 9X     3
18X     4

Resolution    Register_Value
20-bit        0
19-bit        1
18-bit        2
17-bit        3
16-bit        4  (library default)
13-bit        5

Measurement_Delay  Register Value
   25ms            0
   50ms            1
  100ms            2  (library default)
  200ms            3
  500ms            4
 1000ms            5
 2000ms            6

The default Measurement_Delay of 100ms (the manufacturer instead calls this Measurement Rate as well as Integration Time) is 4 times longer than the measurement rate needed for 16-bit resolution. I don't know if that factor has an effect on the accumulation of "counts" when reading UV irradiance.

And yes, I also found in various sources that a UV Index of 1.0 is equivalent to the irradiance level of 25mW/m^2 which indeed is equal to 2.5uW/cm^2 as you noted. For the LTR-390UV running at 18X/20-bit/400ms, that's a count value of about 25 (using Fig. 4.5), quite a bit different than the 2300 counts/UVI sensitivity listed in Fig 4.6 and Table 4.5 for 1 UVI at 18X/20-bit. Hence my confusion.

I think with some sleuthing and a stable UV light source, it will be possible to determine an approach to calculating the UV Index equivalent within the driver library.

CedarGroveStudios commented 3 years ago

@DonBower @ladyada @jedgarpark: Just completed an update of the library to include UVI and Lux. The revision also includes a window_factor parameter to accommodate window transmission light loss (defaults to 1.0 = clear or no glass).

The UVI and Lux calculations were taken directly from the data sheet. I assume that the sensor is factory calibrated, but I don't have a calibrated UV or Lux source to use to verify. Please test the new library in your environment and let me know if the results are reasonable.

To read UVI and Lux using the sensor's default 3x gain and 16-bit resolution default:

import busio
import board
import adafruit_ltr390

i2c = busio.I2C(board.SCL, board.SDA)
ltr = adafruit_ltr390.LTR390(i2c)

print("UVI: ", ltr.uvi, "Lux: ", ltr.lux)

To set the window transmission factor to other than the default 1.0:

ltr.window_factor = 1.1

The updated library can be found in my fork: https://github.com/CedarGroveStudios/Adafruit_CircuitPython_LTR390

ladyada commented 3 years ago

@CedarGroveStudios ooh can ya submit a PR?

CedarGroveStudios commented 3 years ago

@ladyada yes. done.

Bryan's code challenged my thinking a little -- well, a lot actually. It was a very worthwhile opportunity.

CedarGroveStudios commented 3 years ago

@ladyada Would you like me to update the LTR390 learning guide to include the new parameters or work it through Bryan?

ladyada commented 3 years ago

@CedarGroveStudios if you're up for it, it would be greatly appreciated we added you as a guide contributor!

CedarGroveStudios commented 3 years ago

Happy to do so. I'll work on it late tonight.

CedarGroveStudios commented 3 years ago

@ladyada Completed. Had a little time during lunch to update the guide.

I just noticed that the most recent bundle doesn't include the updated LTR390 library so the guide will be out-of-sync until that happens. Can it be easily expedited?

ladyada commented 3 years ago

it'll take a day - thats normal and OK :)

jposada202020 commented 3 years ago

@DonBower I think this was resolved in release 1.1.0 :). Let me know if that is not the case. Thanks https://github.com/adafruit/Adafruit_CircuitPython_LTR390/releases/tag/1.1.0

DonBower commented 3 years ago

@jposada202020 yes, I have adjusted my code:

def printLight():
    if hasTSL:
        thisIR       = tsl.infrared
        thisVis      = tsl.visible/1000
    else:
        thisIR       = 0
        thisVis      = 0
    if hasLTR:
        thisUV       = ltr.uvs
        thisUVi      = ltr.uvi
        if thisVis == 0:
            thisVis  = ltr.lux * 1000
    if hasTSL and hasLTR:
        print(f'IR/Visable/UVI.....: {thisIR:1,d} / {thisVis:1,.0f} / {thisUV:1,d}                   '[:40])
    elif hasLTR:
        print(f'Visable/UVI........: {thisVis:1,.0f} / {thisUV:1,d}                   '[:40])
    elif hasTSL:
        print(f'IR/Visable.........: {thisIR:1,d} / {thisVis:1,.0f}                   '[:40])

This looks like I have the right multiplcation. You can see the whole project here: https://github.com/DonBower/HamGoBox

jposada202020 commented 3 years ago

Interesting project, do you use ham radio as a weather station? another question you mention in the readme the sensor installation, is for these particular set of sensors or in general? Thanks for the info, if nobody has any other comment I think we could close the issue. Thanks :)

DonBower commented 3 years ago

The radio and the weather station are not connected, but because the radio is used in remote locations, I want to be able to monitor conditions. Thanks!