| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- # tsl2591 lux sensor interface
- import time
- VISIBLE = 2
- INFRARED = 1
- FULLSPECTRUM = 0
- ADDR = 0x29
- READBIT = 0x01
- COMMAND_BIT = 0xA0
- CLEAR_BIT = 0x40
- WORD_BIT = 0x20
- BLOCK_BIT = 0x10
- ENABLE_POWERON = 0x01
- ENABLE_POWEROFF = 0x00
- ENABLE_AEN = 0x02
- ENABLE_AIEN = 0x10
- CONTROL_RESET = 0x80
- LUX_DF = 408.0
- LUX_COEFB = 1.64
- LUX_COEFC = 0.59
- LUX_COEFD = 0.86
- REGISTER_ENABLE = 0x00
- REGISTER_CONTROL = 0x01
- REGISTER_THRESHHOLDL_LOW = 0x02
- REGISTER_THRESHHOLDL_HIGH = 0x03
- REGISTER_THRESHHOLDH_LOW = 0x04
- REGISTER_THRESHHOLDH_HIGH = 0x05
- REGISTER_INTERRUPT = 0x06
- REGISTER_CRC = 0x08
- REGISTER_ID = 0x0A
- REGISTER_CHAN0_LOW = 0x14
- REGISTER_CHAN0_HIGH = 0x15
- REGISTER_CHAN1_LOW = 0x16
- REGISTER_CHAN1_HIGH = 0x17
- INTEGRATIONTIME_100MS = 0x00
- INTEGRATIONTIME_200MS = 0x01
- INTEGRATIONTIME_300MS = 0x02
- INTEGRATIONTIME_400MS = 0x03
- INTEGRATIONTIME_500MS = 0x04
- INTEGRATIONTIME_600MS = 0x05
- GAIN_LOW = 0x00
- GAIN_MED = 0x10
- GAIN_HIGH = 0x20
- GAIN_MAX = 0x30
- def _bytes_to_int(data):
- return data[0] + (data[1]<<8)
- from machine import I2C, Pin
- class SMBusEmulator:
- __slots__ = ('i2c',)
- def __init__(self, scl_pinno=5, sda_pinno=4):
- self.i2c = I2C(scl=Pin(scl_pinno, Pin.IN),
- sda=Pin(sda_pinno, Pin.IN))
- def write_byte_data(self, addr, cmd, val):
- buf = bytes([cmd, val])
- self.i2c.writeto(addr, buf)
- def read_word_data(self, addr, cmd):
- assert cmd < 256
- buf = bytes([cmd])
- self.i2c.writeto(addr, buf)
- data = self.i2c.readfrom(addr, 4)
- return _bytes_to_int(data)
- SENSOR_ADDRESS=0x29
- class Tsl2591:
- def __init__(
- self,
- sensor_id='tsl2591',
- integration=INTEGRATIONTIME_100MS,
- gain=GAIN_LOW
- ):
- self.sensor_id = sensor_id
- self.bus = SMBusEmulator()
- self.integration_time = integration
- self.gain = gain
- self.set_timing(self.integration_time)
- self.set_gain(self.gain)
- self.disable()
- def get_i2c(self):
- return self.bus.i2c
- def set_timing(self, integration):
- self.enable()
- self.integration_time = integration
- self.bus.write_byte_data(
- SENSOR_ADDRESS,
- COMMAND_BIT | REGISTER_CONTROL,
- self.integration_time | self.gain
- )
- self.disable()
- def set_gain(self, gain):
- self.enable()
- self.gain = gain
- self.bus.write_byte_data(
- SENSOR_ADDRESS,
- COMMAND_BIT | REGISTER_CONTROL,
- self.integration_time | self.gain
- )
- self.disable()
- def calculate_lux(self, full, ir):
- if (full == 0xFFFF) | (ir == 0xFFFF):
- return 0
-
- case_integ = {
- INTEGRATIONTIME_100MS: 100.,
- INTEGRATIONTIME_200MS: 200.,
- INTEGRATIONTIME_300MS: 300.,
- INTEGRATIONTIME_400MS: 400.,
- INTEGRATIONTIME_500MS: 500.,
- INTEGRATIONTIME_600MS: 600.,
- }
- if self.integration_time in case_integ.keys():
- atime = case_integ[self.integration_time]
- else:
- atime = 100.
- case_gain = {
- GAIN_LOW: 1.,
- GAIN_MED: 25.,
- GAIN_HIGH: 428.,
- GAIN_MAX: 9876.,
- }
- if self.gain in case_gain.keys():
- again = case_gain[self.gain]
- else:
- again = 1.
- cpl = (atime * again) / LUX_DF
- lux1 = (full - (LUX_COEFB * ir)) / cpl
- lux2 = ((LUX_COEFC * full) - (LUX_COEFD * ir)) / cpl
- return max([lux1, lux2])
- def enable(self):
- self.bus.write_byte_data(
- SENSOR_ADDRESS,
- COMMAND_BIT | REGISTER_ENABLE,
- ENABLE_POWERON | ENABLE_AEN | ENABLE_AIEN
- )
- def disable(self):
- self.bus.write_byte_data(
- SENSOR_ADDRESS,
- COMMAND_BIT | REGISTER_ENABLE,
- ENABLE_POWEROFF
- )
- def get_full_luminosity(self):
- self.enable()
- time.sleep(0.120*self.integration_time+1)
- full = self.bus.read_word_data(
- SENSOR_ADDRESS, COMMAND_BIT | REGISTER_CHAN0_LOW
- )
- ir = self.bus.read_word_data(
- SENSOR_ADDRESS, COMMAND_BIT | REGISTER_CHAN1_LOW
- )
- self.disable()
- return full, ir
- def get_luminosity(self, channel):
- full, ir = self.get_full_luminosity()
- if channel == FULLSPECTRUM:
- return full
- elif channel == INFRARED:
- return ir
- elif channel == VISIBLE:
- return full - ir
- else:
- return 0
- def sample(self):
- full, ir = self.get_full_luminosity()
- return self.calculate_lux(full, ir)
|