Salve,
continuo ad avere problemi con questo sensore:
Fornisce letture molto casuali.
Ho provato sia con impostazione auto gain, che con impostazione LUX High gain, che con Lux low gain. Il risultato è sempre numeri molto discutibili non correlati ai cambiamenti luminosi.
io ho utilizzato il seguente codice per leggere il sensore.
Codice:
import sys
# Not needed here. Thanks to https://github.com/mackstann for highlighting this.
#import smbus
import time
#Adafruit_I2C from https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code/blob/master/Adafruit_I2C/Adafruit_I2C.py
from Adafruit_I2C import Adafruit_I2C
### Written for Python 2 <-!!!
### Big thanks to bryand, who wrote the code that I borrowed heavily from/was inspired by
### More thanks pandring who kind of kickstarted my work on the TSL2561 sensor
### A great big huge thanks to driverblock and the Adafruit team (Congrats on your many succeses
### Ladyada). Without you folks I would just be a guy sitting somewhere thinking about cool stuff
### Now I'm a guy building cool stuff.
### If any of this code proves useful, drop me a line at medicforlife.blogspot.com
# TODO: Strip out values into constants.
class TSL2561:
i2c = None
def __init__(self, address=0x39, debug=0, pause=0.8):
self.i2c = Adafruit_I2C(address)
self.address = address
self.pause = pause
self.debug = debug
self.gain = 0 # no gain preselected
self.i2c.write8(0x80, 0x03) # enable the device
def setGain(self,gain=1):
""" Set the gain """
if (gain != self.gain):
if (gain==1):
self.i2c.write8(0x81, 0x02) # set gain = 1X and timing = 402 mSec
if (self.debug):
print "Setting low gain"
else:
self.i2c.write8(0x81, 0x12) # set gain = 16X and timing = 402 mSec
if (self.debug):
print "Setting high gain"
self.gain=gain; # safe gain for calculation
time.sleep(self.pause) # pause for integration (self.pause must be bigger than integration time)
def readWord(self, reg):
"""Reads a word from the I2C device"""
try:
wordval = self.i2c.readU16(reg)
newval = self.i2c.reverseByteOrder(wordval)
if (self.debug):
print("I2C: Device 0x%02X returned 0x%04X from reg 0x%02X" % (self.address, wordval & 0xFFFF, reg))
return newval
except IOError:
print("Error accessing 0x%02X: Check your I2C address" % self.address)
return -1
def readFull(self, reg=0x8C):
"""Reads visible+IR diode from the I2C device"""
return self.readWord(reg);
def readIR(self, reg=0x8E):
"""Reads IR only diode from the I2C device"""
return self.readWord(reg);
def readLux(self, gain = 0):
"""Grabs a lux reading either with autoranging (gain=0) or with a specified gain (1, 16)"""
if (gain == 1 or gain == 16):
self.setGain(gain) # low/highGain
ambient = self.readFull()
IR = self.readIR()
elif (gain==0): # auto gain
self.setGain(16) # first try highGain
ambient = self.readFull()
if (ambient < 65535):
IR = self.readIR()
if (ambient >= 65535 or IR >= 65535): # value(s) exeed(s) datarange
self.setGain(1) # set lowGain
ambient = self.readFull()
IR = self.readIR()
if (self.gain==1):
ambient *= 16 # scale 1x to 16x
IR *= 16 # scale 1x to 16x
ratio = (IR / float(ambient)) # changed to make it run under python 2
if (self.debug):
print "IR Result", IR
print "Ambient Result", ambient
if ((ratio >= 0) & (ratio <= 0.52)):
lux = (0.0315 * ambient) - (0.0593 * ambient * (ratio**1.4))
elif (ratio <= 0.65):
lux = (0.0229 * ambient) - (0.0291 * IR)
elif (ratio <= 0.80):
lux = (0.0157 * ambient) - (0.018 * IR)
elif (ratio <= 1.3):
lux = (0.00338 * ambient) - (0.0026 * IR)
elif (ratio > 1.3):
lux = 0
return lux
if __name__ == "__main__":
tsl=TSL2561()
print tsl.readLux(16)
#print "LUX HIGH GAIN ", tsl.readLux(16)
#print "LUX LOW GAIN ", tsl.readLux(1)
#print "LUX AUTO GAIN ", tsl.readLux()
Allora ho pensato di usare un il seguente driver, ma mi dice che non posso importare "from Adafruit_GPIO import I2C"
Sapreste dirmi come fare?
Codice:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals
'''Driver for the TSL2561 digital luminosity (light) sensors.
Pick one up at http://www.adafruit.com/products/439
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Code ported from Adafruit Arduino library,
commit ced9f731da5095988cd66158562c2fde659e0510:
https://github.com/adafruit/Adafruit_TSL2561
'''
import time
from Adafruit_GPIO import I2C
from tsl2561.constants import * # pylint: disable=unused-wildcard-import
__author__ = 'Georges Toth <georges@trypill.org>'
__credits__ = ['K.Townsend (Adafruit Industries)', 'Yongwen Zhuang (zYeoman)', 'miko (mikostn)', 'Simon Gansen (theFork)']
__license__ = 'BSD'
__version__ = 'v3.0'
'''HISTORY
v3.1 - Fix import
v3.0 - Port to Python 3.x
v2.2 - Merge PR #4 regarding wrong use of integration time
v2.1 - Minor adaptations required by latest Adafruit pyton libraries
v2.0 - Rewrote driver for Adafruit_Sensor and Auto-Gain support, and
added lux clipping check (returns 0 lux on sensor saturation)
v1.0 - First release (previously TSL2561)
'''
class TSL2561(object):
'''Driver for the TSL2561 digital luminosity (light) sensors.'''
def __init__(self, address=None, busnum=None,
integration_time=TSL2561_INTEGRATIONTIME_402MS,
gain=TSL2561_GAIN_1X, autogain=False, debug=False):
# Set default address and bus number if not given
if address is not None:
self.address = address
else:
self.address = TSL2561_ADDR_FLOAT
if busnum is None:
self.busnum = 1
self.i2c = I2C.get_i2c_device(self.address, busnum=busnum)
self.debug = debug
self.integration_time = integration_time
self.gain = gain
self.autogain = autogain
if self.integration_time == TSL2561_INTEGRATIONTIME_402MS:
self.delay_time = TSL2561_DELAY_INTTIME_402MS
elif self.integration_time == TSL2561_INTEGRATIONTIME_101MS:
self.delay_time = TSL2561_DELAY_INTTIME_101MS
elif self.integration_time == TSL2561_INTEGRATIONTIME_13MS:
self.delay_time = TSL2561_DELAY_INTTIME_13MS
self._begin()
def _begin(self):
'''Initializes I2C and configures the sensor (call this function before
doing anything else)
'''
# Make sure we're actually connected
x = self.i2c.readU8(TSL2561_REGISTER_ID)
if not x & 0x0A:
raise Exception('TSL2561 not found!')
##########
# Set default integration time and gain
self.set_integration_time(self.integration_time)
self.set_gain(self.gain)
# Note: by default, the device is in power down mode on bootup
self.disable()
def enable(self):
'''Enable the device by setting the control bit to 0x03'''
self.i2c.write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL,
TSL2561_CONTROL_POWERON)
def disable(self):
'''Disables the device (putting it in lower power sleep mode)'''
self.i2c.write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL,
TSL2561_CONTROL_POWEROFF)
@staticmethod
def delay(value):
'''Delay times must be specified in milliseconds but as the python
sleep function only takes (float) seconds we need to convert the sleep
time first
'''
time.sleep(value / 1000.0)
def _get_data(self):
'''Private function to read luminosity on both channels'''
# Enable the device by setting the control bit to 0x03
self.enable()
# Wait x ms for ADC to complete
TSL2561.delay(self.delay_time)
# Reads a two byte value from channel 0 (visible + infrared)
broadband = self.i2c.readU16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT |
TSL2561_REGISTER_CHAN0_LOW)
# Reads a two byte value from channel 1 (infrared)
ir = self.i2c.readU16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT |
TSL2561_REGISTER_CHAN1_LOW)
# Turn the device off to save power
self.disable()
return (broadband, ir)
def set_integration_time(self, integration_time):
'''Sets the integration time for the TSL2561'''
# Enable the device by setting the control bit to 0x03
self.enable()
self.integration_time = integration_time
# Update the timing register
self.i2c.write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING,
self.integration_time | self.gain)
# Turn the device off to save power
self.disable()
def set_gain(self, gain):
'''Adjusts the gain on the TSL2561 (adjusts the sensitivity to light)
'''
# Enable the device by setting the control bit to 0x03
self.enable()
self.gain = gain
# Update the timing register
self.i2c.write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING,
self.integration_time | self.gain)
# Turn the device off to save power
self.disable()
def set_auto_range(self, value):
'''Enables or disables the auto-gain settings when reading
data from the sensor
'''
self.autogain = value
def _get_luminosity(self):
'''Gets the broadband (mixed lighting) and IR only values from
the TSL2561, adjusting gain if auto-gain is enabled
'''
valid = False
# If Auto gain disabled get a single reading and continue
if not self.autogain:
return self._get_data()
# Read data until we find a valid range
_agcCheck = False
broadband = 0
ir = 0
while not valid:
if self.integration_time == TSL2561_INTEGRATIONTIME_13MS:
_hi = TSL2561_AGC_THI_13MS
_lo = TSL2561_AGC_TLO_13MS
elif self.integration_time == TSL2561_INTEGRATIONTIME_101MS:
_hi = TSL2561_AGC_THI_101MS
_lo = TSL2561_AGC_TLO_101MS
else:
_hi = TSL2561_AGC_THI_402MS
_lo = TSL2561_AGC_TLO_402MS
_b, _ir = self._get_data()
# Run an auto-gain check if we haven't already done so ...
if not _agcCheck:
if _b < _lo and self.gain == TSL2561_GAIN_1X:
# Increase the gain and try again
self.set_gain(TSL2561_GAIN_16X)
# Drop the previous conversion results
_b, _ir = self._get_data()
# Set a flag to indicate we've adjusted the gain
_agcCheck = True
elif _b > _hi and self.gain == TSL2561_GAIN_16X:
# Drop gain to 1x and try again
self.set_gain(TSL2561_GAIN_1X)
# Drop the previous conversion results
_b, _ir = self._get_data()
# Set a flag to indicate we've adjusted the gain
_agcCheck = True
else:
# Nothing to look at here, keep moving ....
# Reading is either valid, or we're already at the chips
# limits
broadband = _b
ir = _ir
valid = True
else:
# If we've already adjusted the gain once, just return the new
# results.
# This avoids endless loops where a value is at one extreme
# pre-gain, and the the other extreme post-gain
broadband = _b
ir = _ir
valid = True
return (broadband, ir)
def _calculate_lux(self, broadband, ir):
'''Converts the raw sensor values to the standard SI lux equivalent.
Returns 0 if the sensor is saturated and the values are unreliable.
'''
# Make sure the sensor isn't saturated!
if self.integration_time == TSL2561_INTEGRATIONTIME_13MS:
clipThreshold = TSL2561_CLIPPING_13MS
elif self.integration_time == TSL2561_INTEGRATIONTIME_101MS:
clipThreshold = TSL2561_CLIPPING_101MS
else:
clipThreshold = TSL2561_CLIPPING_402MS
# Return 0 lux if the sensor is saturated
if broadband > clipThreshold or ir > clipThreshold:
raise Exception('Sensor is saturated')
# Get the correct scale depending on the integration time
if self.integration_time == TSL2561_INTEGRATIONTIME_13MS:
chScale = TSL2561_LUX_CHSCALE_TINT0
elif self.integration_time == TSL2561_INTEGRATIONTIME_101MS:
chScale = TSL2561_LUX_CHSCALE_TINT1
else:
chScale = 1 << TSL2561_LUX_CHSCALE
# Scale for gain (1x or 16x)
if not self.gain:
chScale = chScale << 4
# Scale the channel values
channel0 = (broadband * chScale) >> TSL2561_LUX_CHSCALE
channel1 = (ir * chScale) >> TSL2561_LUX_CHSCALE
# Find the ratio of the channel values (Channel1/Channel0)
ratio1 = 0
if channel0 != 0:
ratio1 = (channel1 << (TSL2561_LUX_RATIOSCALE + 1)) / channel0
# round the ratio value
ratio = (int(ratio1) + 1) >> 1
b = 0
m = 0
if ratio >= 0 and ratio <= TSL2561_LUX_K1T:
b = TSL2561_LUX_B1T
m = TSL2561_LUX_M1T
elif ratio <= TSL2561_LUX_K2T:
b = TSL2561_LUX_B2T
m = TSL2561_LUX_M2T
elif ratio <= TSL2561_LUX_K3T:
b = TSL2561_LUX_B3T
m = TSL2561_LUX_M3T
elif ratio <= TSL2561_LUX_K4T:
b = TSL2561_LUX_B4T
m = TSL2561_LUX_M4T
elif ratio <= TSL2561_LUX_K5T:
b = TSL2561_LUX_B5T
m = TSL2561_LUX_M5T
elif ratio <= TSL2561_LUX_K6T:
b = TSL2561_LUX_B6T
m = TSL2561_LUX_M6T
elif ratio <= TSL2561_LUX_K7T:
b = TSL2561_LUX_B7T
m = TSL2561_LUX_M7T
elif ratio > TSL2561_LUX_K8T:
b = TSL2561_LUX_B8T
m = TSL2561_LUX_M8T
temp = (channel0 * b) - (channel1 * m)
# Do not allow negative lux value
if temp < 0:
temp = 0
# Round lsb (2^(LUX_SCALE-1))
temp += 1 << (TSL2561_LUX_LUXSCALE - 1)
# Strip off fractional portion
lux = temp >> TSL2561_LUX_LUXSCALE
# Signal I2C had no errors
return lux
def lux(self):
'''Read sensor data, convert it to LUX and return it'''
broadband, ir = self._get_luminosity()
return self._calculate_lux(broadband, ir)
if __name__ == "__main__":
tsl = TSL2561(debug=True)
print(tsl.lux())
Grazie per tutto
Saluti
LaPa