Grove - Digital Light Sensor
Version från den 4 februari 2021 kl. 07.25 av Christian (diskussion | bidrag)
Denna modul är baserad på I2C ljus-till-digital-omvandlaren TSL2561 för att omvandla ljusintensitet till en digital signal. Olika traditionella analogljussensorer, som Grove-Light Sensor, har denna digitala modul ett valbart ljusspektrumområde på grund av dess dubbla ljuskänsliga dioder: infraröd och fullt spektrum. Vi kan växla mellan tre detekteringslägen för att ta dina avläsningar. De är infrarödläge, fullt spektrum och mänskligt synligt läge.
Innehåll
Kompatibilitet
- Arduino
- Raspberry Pi
Port
- I2C
Bibliotek
Till Arduino IDE: https://github.com/Seeed-Studio/Grove_Digital_Light_Sensor/archive/master.zip
Exempelkod
Arduino
#include <Wire.h>
#include <Digital_Light_TSL2561.h>
void setup()
{
Wire.begin();
Serial.begin(9600);
TSL2561.init();
}
void loop()
{
Serial.print("The Light value is: ");
Serial.println(TSL2561.readVisibleLux());
delay(1000);
}
Raspberry Pi
from time import sleep
import smbus
from Adafruit_I2C import Adafruit_I2C
import RPi.GPIO as GPIO
from smbus import SMBus
TSL2561_Control = 0x80
TSL2561_Timing = 0x81
TSL2561_Interrupt = 0x86
TSL2561_Channel0L = 0x8C
TSL2561_Channel0H = 0x8D
TSL2561_Channel1L = 0x8E
TSL2561_Channel1H = 0x8F
TSL2561_Address = 0x29 #device address
LUX_SCALE = 14 # scale by 2^14
RATIO_SCALE = 9 # scale ratio by 2^9
CH_SCALE = 10 # scale channel values by 2^10
CHSCALE_TINT0 = 0x7517 # 322/11 * 2^CH_SCALE
CHSCALE_TINT1 = 0x0fe7 # 322/81 * 2^CH_SCALE
K1T = 0x0040 # 0.125 * 2^RATIO_SCALE
B1T = 0x01f2 # 0.0304 * 2^LUX_SCALE
M1T = 0x01be # 0.0272 * 2^LUX_SCALE
K2T = 0x0080 # 0.250 * 2^RATIO_SCA
B2T = 0x0214 # 0.0325 * 2^LUX_SCALE
M2T = 0x02d1 # 0.0440 * 2^LUX_SCALE
K3T = 0x00c0 # 0.375 * 2^RATIO_SCALE
B3T = 0x023f # 0.0351 * 2^LUX_SCALE
M3T = 0x037b # 0.0544 * 2^LUX_SCALE
K4T = 0x0100 # 0.50 * 2^RATIO_SCALE
B4T = 0x0270 # 0.0381 * 2^LUX_SCALE
M4T = 0x03fe # 0.0624 * 2^LUX_SCALE
K5T = 0x0138 # 0.61 * 2^RATIO_SCALE
B5T = 0x016f # 0.0224 * 2^LUX_SCALE
M5T = 0x01fc # 0.0310 * 2^LUX_SCALE
K6T = 0x019a # 0.80 * 2^RATIO_SCALE
B6T = 0x00d2 # 0.0128 * 2^LUX_SCALE
M6T = 0x00fb # 0.0153 * 2^LUX_SCALE
K7T = 0x029a # 1.3 * 2^RATIO_SCALE
B7T = 0x0018 # 0.00146 * 2^LUX_SCALE
M7T = 0x0012 # 0.00112 * 2^LUX_SCALE
K8T = 0x029a # 1.3 * 2^RATIO_SCALE
B8T = 0x0000 # 0.000 * 2^LUX_SCALE
M8T = 0x0000 # 0.000 * 2^LUX_SCALE
K1C = 0x0043 # 0.130 * 2^RATIO_SCALE
B1C = 0x0204 # 0.0315 * 2^LUX_SCALE
M1C = 0x01ad # 0.0262 * 2^LUX_SCALE
K2C = 0x0085 # 0.260 * 2^RATIO_SCALE
B2C = 0x0228 # 0.0337 * 2^LUX_SCALE
M2C = 0x02c1 # 0.0430 * 2^LUX_SCALE
K3C = 0x00c8 # 0.390 * 2^RATIO_SCALE
B3C = 0x0253 # 0.0363 * 2^LUX_SCALE
M3C = 0x0363 # 0.0529 * 2^LUX_SCALE
K4C = 0x010a # 0.520 * 2^RATIO_SCALE
B4C = 0x0282 # 0.0392 * 2^LUX_SCALE
M4C = 0x03df # 0.0605 * 2^LUX_SCALE
K5C = 0x014d # 0.65 * 2^RATIO_SCALE
B5C = 0x0177 # 0.0229 * 2^LUX_SCALE
M5C = 0x01dd # 0.0291 * 2^LUX_SCALE
K6C = 0x019a # 0.80 * 2^RATIO_SCALE
B6C = 0x0101 # 0.0157 * 2^LUX_SCALE
M6C = 0x0127 # 0.0180 * 2^LUX_SCALE
K7C = 0x029a # 1.3 * 2^RATIO_SCALE
B7C = 0x0037 # 0.00338 * 2^LUX_SCALE
M7C = 0x002b # 0.00260 * 2^LUX_SCALE
K8C = 0x029a # 1.3 * 2^RATIO_SCALE
B8C = 0x0000 # 0.000 * 2^LUX_SCALE
M8C = 0x0000 # 0.000 * 2^LUX_SCALE
# bus parameters
rev = GPIO.RPI_REVISION
if rev == 2 or rev == 3:
bus = smbus.SMBus(1)
else:
bus = smbus.SMBus(0)
i2c = Adafruit_I2C(TSL2561_Address)
debug = False
cooldown_time = 0.005 # measured in seconds
packageType = 0 # 0=T package, 1=CS package
gain = 0 # current gain: 0=1x, 1=16x [dynamically selected]
gain_m = 1 # current gain, as multiplier
timing = 2 # current integration time: 0=13.7ms, 1=101ms, 2=402ms [dynamically selected]
timing_ms = 0 # current integration time, in ms
channel0 = 0 # raw current value of visible+ir sensor
channel1 = 0 # raw current value of ir sensor
schannel0 = 0 # normalized current value of visible+ir sensor
schannel1 = 0 # normalized current value of ir sensor
def readRegister(address):
try:
byteval = i2c.readU8(address)
sleep(cooldown_time)
if (debug):
print("TSL2561.readRegister: returned 0x%02X from reg 0x%02X" % (byteval, address))
return byteval
except IOError:
print("TSL2561.readRegister: error reading byte from reg 0x%02X" % address)
return -1
def writeRegister(address, val):
try:
i2c.write8(address, val)
sleep(cooldown_time)
if (debug):
print("TSL2561.writeRegister: wrote 0x%02X to reg 0x%02X" % (val, address))
except IOError:
sleep(cooldown_time)
print("TSL2561.writeRegister: error writing byte to reg 0x%02X" % address)
return -1
def powerUp():
writeRegister(TSL2561_Control, 0x03)
def powerDown():
writeRegister(TSL2561_Control, 0x00)
def setTintAndGain():
global gain_m, timing_ms
if gain == 0:
gain_m = 1
else:
gain_m = 16
if timing == 0:
timing_ms = 13.7
elif timing == 1:
timing_ms = 101
else:
timing_ms = 402
writeRegister(TSL2561_Timing, timing | gain << 4)
def readLux():
sleep(float(timing_ms + 1) / 1000)
ch0_low = readRegister(TSL2561_Channel0L)
ch0_high = readRegister(TSL2561_Channel0H)
ch1_low = readRegister(TSL2561_Channel1L)
ch1_high = readRegister(TSL2561_Channel1H)
global channel0, channel1
channel0 = (ch0_high<<8) | ch0_low
channel1 = (ch1_high<<8) | ch1_low
sleep(cooldown_time)
if debug:
print("TSL2561.readVisibleLux: channel 0 = %i, channel 1 = %i [gain=%ix, timing=%ims]" % (channel0, channel1, gain_m, timing_ms))
def readVisibleLux():
global timing, gain
powerUp()
readLux()
if channel0 < 500 and timing == 0:
timing = 1
sleep(cooldown_time)
if debug:
print("TSL2561.readVisibleLux: too dark. Increasing integration time from 13.7ms to 101ms")
setTintAndGain()
readLux()
if channel0 < 500 and timing == 1:
timing = 2
sleep(cooldown_time)
if debug:
print("TSL2561.readVisibleLux: too dark. Increasing integration time from 101ms to 402ms")
setTintAndGain()
readLux()
if channel0 < 500 and timing == 2 and gain == 0:
gain = 1
sleep(cooldown_time)
if debug:
print("TSL2561.readVisibleLux: too dark. Setting high gain")
setTintAndGain()
readLux()
if (channel0 > 20000 or channel1 > 20000) and timing == 2 and gain == 1:
gain = 0
sleep(cooldown_time)
if debug:
print("TSL2561.readVisibleLux: enough light. Setting low gain")
setTintAndGain()
readLux()
if (channel0 > 20000 or channel1 > 20000) and timing == 2:
timing = 1
sleep(cooldown_time)
if debug:
print("TSL2561.readVisibleLux: enough light. Reducing integration time from 402ms to 101ms")
setTintAndGain()
readLux()
if (channel0 > 10000 or channel1 > 10000) and timing == 1:
timing = 0
sleep(cooldown_time)
if debug:
print("TSL2561.readVisibleLux: enough light. Reducing integration time from 101ms to 13.7ms")
setTintAndGain()
readLux()
powerDown()
if (timing == 0 and (channel0 > 5000 or channel1 > 5000)) or (timing == 1 and (channel0 > 37000 or channel1 > 37000)) or (timing == 2 and (channel0 > 65000 or channel1 > 65000)):
# overflow
return -1
return calculateLux(channel0, channel1)
def calculateLux(ch0, ch1):
chScale = 0
if timing == 0: # 13.7 msec
chScale = CHSCALE_TINT0
elif timing == 1: # 101 msec
chScale = CHSCALE_TINT1;
else: # assume no scaling
chScale = (1 << CH_SCALE)
if gain == 0:
chScale = chScale << 4 # scale 1X to 16X
# scale the channel values
global schannel0, schannel1
schannel0 = (ch0 * chScale) >> CH_SCALE
schannel1 = (ch1 * chScale) >> CH_SCALE
ratio = 0
if schannel0 != 0:
ratio = (schannel1 << (RATIO_SCALE+1)) / schannel0
ratio = (ratio + 1) >> 1
if packageType == 0: # T package
if ((ratio >= 0) and (ratio <= K1T)):
b=B1T; m=M1T;
elif (ratio <= K2T):
b=B2T; m=M2T;
elif (ratio <= K3T):
b=B3T; m=M3T;
elif (ratio <= K4T):
b=B4T; m=M4T;
elif (ratio <= K5T):
b=B5T; m=M5T;
elif (ratio <= K6T):
b=B6T; m=M6T;
elif (ratio <= K7T):
b=B7T; m=M7T;
elif (ratio > K8T):
b=B8T; m=M8T;
elif packageType == 1: # CS package
if ((ratio >= 0) and (ratio <= K1C)):
b=B1C; m=M1C;
elif (ratio <= K2C):
b=B2C; m=M2C;
elif (ratio <= K3C):
b=B3C; m=M3C;
elif (ratio <= K4C):
b=B4C; m=M4C;
elif (ratio <= K5C):
b=B5C; m=M5C;
elif (ratio <= K6C):
b=B6C; m=M6C;
elif (ratio <= K7C):
b=B7C; m=M7C;
temp = ((schannel0*b)-(schannel1*m))
if temp < 0:
temp = 0;
temp += (1<<(LUX_SCALE-1))
# strip off fractional portion
lux = temp>>LUX_SCALE
sleep(cooldown_time)
if debug:
print("TSL2561.calculateLux: %i" % lux)
return lux
def init():
powerUp()
setTintAndGain()
writeRegister(TSL2561_Interrupt, 0x00)
powerDown()
def main():
init()
while (True):
print("Lux: %i [Vis+IR=%i, IR=%i @ Gain=%ix, Timing=%.1fms]" % (readVisibleLux(), channel0, channel1, gain_m, timing_ms))
sleep(1)
if __name__ == "__main__":
main()