I’ve got an enviro weather set up and was looking to add on some additional qwiic connected i2c sensors, one of which would be the LTR390 (from adafruit) for uv and light. Unfortunately I did not realize adafruit had gone completely over to their own circuitpython libraries. Is anyone using the ltr390 in their own projects with micropython and can share some of the code?
The only mention I can find on the forums is an old post from @Tonygo2 mentioning he is using it so I am hoping its still possible.
This is the code I was using. It came with Waveshare Enviromental Sensor.
# WS Sensor UV 1 Sept 2021 Working
import utime
import math
from machine import Pin, I2C
# ========= Start LTR390 UV sensor driver =============
ADDR = (0X53)
LTR390_MAIN_CTRL = (0x00) # Main control register
LTR390_MEAS_RATE = (0x04) # Resolution and data rate
LTR390_GAIN = (0x05) # ALS and UVS gain range
LTR390_PART_ID = (0x06) # Part id/revision register
LTR390_MAIN_STATUS = (0x07) # Main status register
LTR390_ALSDATA = (0x0D) # ALS data lowest byte, 3 byte
LTR390_UVSDATA = (0x10) # UVS data lowest byte, 3 byte
LTR390_INT_CFG = (0x19) # Interrupt configuration
LTR390_INT_PST = (0x1A) # Interrupt persistance config
LTR390_THRESH_UP = (0x21) # Upper threshold, low byte, 3 byte
LTR390_THRESH_LOW = (0x24) # Lower threshold, low byte, 3 byte
#ALS/UVS measurement resolution, Gain setting, measurement rate
RESOLUTION_20BIT_utime400MS = (0X00)
RESOLUTION_19BIT_utime200MS = (0X10)
RESOLUTION_18BIT_utime100MS = (0X20)#default
RESOLUTION_17BIT_utime50MS = (0x3)
RESOLUTION_16BIT_utime25MS = (0x40)
RESOLUTION_13BIT_utime12_5MS = (0x50)
RATE_25MS = (0x0)
RATE_50MS = (0x1)
RATE_100MS = (0x2)# default
RATE_200MS = (0x3)
RATE_500MS = (0x4)
RATE_1000MS = (0x5)
RATE_2000MS = (0x6)
# measurement Gain Range.
GAIN_1 = (0x0)
GAIN_3 = (0x1)# default
GAIN_6 = (0x2)
GAIN_9 = (0x3)
GAIN_18 = (0x4)
class LTR390:
def __init__(self, address=ADDR):
self.i2c = I2C(0, scl=Pin(21), sda=Pin(20), freq=100000)
self.address = address
self.ID = self.Read_Byte(LTR390_PART_ID)
# print("ID = %#x" %self.ID)
if(self.ID != 0xB2):
print("read ID error!,Check the hardware...")
return
self.Write_Byte(LTR390_MAIN_CTRL, 0x0A) # UVS in Active Mode
self.Write_Byte(LTR390_MEAS_RATE, RESOLUTION_20BIT_utime400MS | RATE_2000MS) # Resolution=18bits, Meas Rate = 100ms
self.Write_Byte(LTR390_GAIN, GAIN_3) # Gain Range=3.
# self.Write_Byte(LTR390_INT_CFG, 0x34) # UVS_INT_EN=1, Command=0x34
# self.Write_Byte(LTR390_GAIN, GAIN_3) # Resolution=18bits, Meas Rate = 100ms
def Read_Byte(self, cmd):
rdate = self.i2c.readfrom_mem(int(self.address), int(cmd), 1)
return rdate[0]
def Write_Byte(self, cmd, val):
self.i2c.writeto_mem(int(self.address), int(cmd), bytes([int(val)]))
def UVS(self):
# self.Write_Byte(LTR390_MAIN_CTRL, 0x0A) # UVS in Active Mode
Data1 = self.Read_Byte(LTR390_UVSDATA)
Data2 = self.Read_Byte(LTR390_UVSDATA + 1)
Data3 = self.Read_Byte(LTR390_UVSDATA + 2)
uv = (Data3 << 16)| (Data2 << 8) | Data1
# UVS = Data3*65536+Data2*256+Data1
# print("UVS = ", UVS)
return uv
# ========= End LTR390 UV sensor driver =============
if __name__ == '__main__':
sensor = LTR390()
utime.sleep(1)
try:
while True:
UVS = sensor.UVS()
print("UVS: %d" %UVS)
utime.sleep(0.5)
except KeyboardInterrupt:
# sensor.Disable()
exit()
The full workout is here:
Hope you get it working.
Much appreciated! I actually found that Waveshare board and code a few hours after opening this thread lol.
Its working great! Thanks again for the initial code @Tonygo2 . I’ve added in the function for reading the light value as well instead of just uv.
Here’s the code and steps in case anyone else find this in the future
Create a new file in the enviro folder called ltr390.py
# WaveShare Sensor UV 1 Sept 2021 Working
# https://optoelectronics.liteon.com/upload/download/DS86-2015-0004/LTR-390UV_Final_%20DS_V1%201.pdf
import math
import enviro #only needed if this code is in its own file
from machine import Pin, I2C
ADDR = (0X53)
LTR390_MAIN_CTRL = (0x00) # Main control register
LTR390_MEAS_RATE = (0x04) # Resolution and data rate
LTR390_GAIN = (0x05) # ALS and UVS gain range
LTR390_PART_ID = (0x06) # Part id/revision register
LTR390_MAIN_STATUS = (0x07) # Main status register
LTR390_ALSDATA = (0x0D) # ALS data lowest byte, 3 byte
LTR390_UVSDATA = (0x10) # UVS data lowest byte, 3 byte
LTR390_INT_CFG = (0x19) # Interrupt configuration
LTR390_INT_PST = (0x1A) # Interrupt persistance config
LTR390_THRESH_UP = (0x21) # Upper threshold, low byte, 3 byte
LTR390_THRESH_LOW = (0x24) # Lower threshold, low byte, 3 byte
#ALS/UVS measurement resolution, Gain setting, measurement rate
RESOLUTION_20BIT_utime400MS = (0X00)
RESOLUTION_19BIT_utime200MS = (0X10)
RESOLUTION_18BIT_utime100MS = (0X20)#default
RESOLUTION_17BIT_utime50MS = (0x3)
RESOLUTION_16BIT_utime25MS = (0x40)
RESOLUTION_13BIT_utime12_5MS = (0x50)
RATE_25MS = (0x0)
RATE_50MS = (0x1)
RATE_100MS = (0x2)# default
RATE_200MS = (0x3)
RATE_500MS = (0x4)
RATE_1000MS = (0x5)
RATE_2000MS = (0x6)
# measurement Gain Range.
GAIN_1 = (0x0)
GAIN_3 = (0x1)# default
GAIN_6 = (0x2)
GAIN_9 = (0x3)
GAIN_18 = (0x4)
class LTR390:
def __init__(self, address=ADDR):
self.i2c = enviro.i2c
self.address = address
self.ID = self.Read_Byte(LTR390_PART_ID)
if(self.ID != 0xB2):
print("read ID error!,Check the hardware...")
return
self.Write_Byte(LTR390_MAIN_CTRL, 0x0A) # Set mode to UVS and Enabled
self.Write_Byte(LTR390_MEAS_RATE, RESOLUTION_20BIT_utime400MS | RATE_2000MS) # Resolution=18bits, Meas Rate = 100ms
self.Write_Byte(LTR390_GAIN, GAIN_3) # Gain Range=3.
def Read_Byte(self, cmd):
rdate = self.i2c.readfrom_mem(int(self.address), int(cmd), 1)
return rdate[0]
def Write_Byte(self, cmd, val):
self.i2c.writeto_mem(int(self.address), int(cmd), bytes([int(val)]))
def UVS(self):
self.Write_Byte(LTR390_MAIN_CTRL, 0x0A) # UVS in Active Mode
Data1 = self.Read_Byte(LTR390_UVSDATA)
Data2 = self.Read_Byte(LTR390_UVSDATA + 1)
Data3 = self.Read_Byte(LTR390_UVSDATA + 2)
uv = (Data3 << 16)| (Data2 << 8) | Data1
return uv
def ALS(self):
self.Write_Byte(LTR390_MAIN_CTRL, 0x02) # ALS in Active Mode
Data1 = self.Read_Byte(LTR390_ALSDATA)
Data2 = self.Read_Byte(LTR390_ALSDATA + 1)
Data3 = self.Read_Byte(LTR390_ALSDATA + 2)
als = (Data3 << 16)| (Data2 << 8) | Data1
return als
Add these to your main.py
#Adding LTR390 UV sensor
from enviro.ltr390 import * #ltr driver code is in a file called ltr390 in the enviro folder
#add below line 56 "reading = enviro.get_sensor_readings()"
#LTR390 readings
ltr = LTR390()
reading["uvs"] = ltr.UVS()
reading["als"] = ltr.ALS()
Well the ltr390 stops reading anything while on battery power (though the status light does turn on)
Turns out on battery it just did not have enough time to “wake” the sensor and take a reading. heres the updated code (now should also report uv index but I don’t have a calibrated light so I can’t confirm accuracy)
changed the methods in ltr390.py
def setUVS(self):
self.Write_Byte(LTR390_GAIN, GAIN_18) # Gain Range=18, default 3. has to be 18 for uvi calc
self.Write_Byte(LTR390_MAIN_CTRL, 0x0A) # UVS in Active Mode
def UVS(self):
#self.Write_Byte(LTR390_GAIN, GAIN_18) # Gain Range=18, default 3. has to be 18 for uvi calc
#self.Write_Byte(LTR390_MAIN_CTRL, 0x0A) # UVS in Active Mode
Data1 = self.Read_Byte(LTR390_UVSDATA)
Data2 = self.Read_Byte(LTR390_UVSDATA + 1)
Data3 = self.Read_Byte(LTR390_UVSDATA + 2)
uv = (Data3 << 16)| (Data2 << 8) | Data1
return uv
def setALS(self):
self.Write_Byte(LTR390_GAIN, GAIN_3)
self.Write_Byte(LTR390_MAIN_CTRL, 0x02) # ALS in Active Mode
def ALS(self):
#self.Write_Byte(LTR390_GAIN, GAIN_3)
#self.Write_Byte(LTR390_MAIN_CTRL, 0x02) # ALS in Active Mode
Data1 = self.Read_Byte(LTR390_ALSDATA)
Data2 = self.Read_Byte(LTR390_ALSDATA + 1)
Data3 = self.Read_Byte(LTR390_ALSDATA + 2)
als = (Data3 << 16)| (Data2 << 8) | Data1
return als
def reset(self):
self.Write_Byte(LTR390_MAIN_CTRL, 0x00) # turn off als/uvs before enviro cuts power while sleeping
changed in main.py
try:
logging.info(f"> trying to start ltr readings")
#LTR390 readings
ltr = LTR390()
ltr.setUVS()
utime.sleep(0.5) # may be able to decrease delay but have not tried
uvsData = ltr.UVS()
reading["uvs"] = uvsData
#1 UVI per 2300 counts at 18X gain factor and 20-bit resolution. uvi = (uvs / 2300)
reading["uvi"] = uvsData/2300
#logging.info(f"> uvi/als readings - uvs: {uvsData}")
ltr.setALS()
utime.sleep(0.5)
alsData = ltr.ALS()
reading["als"] = alsData
#logging.info(f"> uvi/als readings - als: {alsData}")
ltr.reset()
except Exception as exc:
enviro.exception(exc)