first commit
This commit is contained in:
commit
a5a0434432
1126 changed files with 439481 additions and 0 deletions
161
Software/Python/grove_i2c_digital_light_sensor/Adafruit_I2C.py
Normal file
161
Software/Python/grove_i2c_digital_light_sensor/Adafruit_I2C.py
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
#!/usr/bin/python
|
||||
import re
|
||||
import smbus
|
||||
|
||||
# ===========================================================================
|
||||
# Adafruit_I2C Class
|
||||
# ===========================================================================
|
||||
|
||||
class Adafruit_I2C(object):
|
||||
|
||||
@staticmethod
|
||||
def getPiRevision():
|
||||
"Gets the version number of the Raspberry Pi board"
|
||||
# Revision list available at: http://elinux.org/RPi_HardwareHistory#Board_Revision_History
|
||||
try:
|
||||
with open('/proc/cpuinfo', 'r') as infile:
|
||||
for line in infile:
|
||||
# Match a line of the form "Revision : 0002" while ignoring extra
|
||||
# info in front of the revsion (like 1000 when the Pi was over-volted).
|
||||
match = re.match('Revision\s+:\s+.*(\w{4})$', line)
|
||||
if match and match.group(1) in ['0000', '0002', '0003']:
|
||||
# Return revision 1 if revision ends with 0000, 0002 or 0003.
|
||||
return 1
|
||||
elif match:
|
||||
# Assume revision 2 if revision ends with any other 4 chars.
|
||||
return 2
|
||||
# Couldn't find the revision, assume revision 0 like older code for compatibility.
|
||||
return 0
|
||||
except:
|
||||
return 0
|
||||
|
||||
@staticmethod
|
||||
def getPiI2CBusNumber():
|
||||
# Gets the I2C bus number /dev/i2c#
|
||||
return 1 if Adafruit_I2C.getPiRevision() > 1 else 0
|
||||
|
||||
def __init__(self, address, busnum=-1, debug=False):
|
||||
self.address = address
|
||||
# By default, the correct I2C bus is auto-detected using /proc/cpuinfo
|
||||
# Alternatively, you can hard-code the bus version below:
|
||||
# self.bus = smbus.SMBus(0); # Force I2C0 (early 256MB Pi's)
|
||||
# self.bus = smbus.SMBus(1); # Force I2C1 (512MB Pi's)
|
||||
self.bus = smbus.SMBus(busnum if busnum >= 0 else Adafruit_I2C.getPiI2CBusNumber())
|
||||
self.debug = debug
|
||||
|
||||
def reverseByteOrder(self, data):
|
||||
"Reverses the byte order of an int (16-bit) or long (32-bit) value"
|
||||
# Courtesy Vishal Sapre
|
||||
byteCount = len(hex(data)[2:].replace('L','')[::2])
|
||||
val = 0
|
||||
for i in range(byteCount):
|
||||
val = (val << 8) | (data & 0xff)
|
||||
data >>= 8
|
||||
return val
|
||||
|
||||
def errMsg(self):
|
||||
print("Error accessing 0x%02X: Check your I2C address" % self.address)
|
||||
return -1
|
||||
|
||||
def write8(self, reg, value):
|
||||
"Writes an 8-bit value to the specified register/address"
|
||||
try:
|
||||
self.bus.write_byte_data(self.address, reg, value)
|
||||
if self.debug:
|
||||
print("I2C: Wrote 0x%02X to register 0x%02X" % (value, reg))
|
||||
except IOError as err:
|
||||
return self.errMsg()
|
||||
|
||||
def write16(self, reg, value):
|
||||
"Writes a 16-bit value to the specified register/address pair"
|
||||
try:
|
||||
self.bus.write_word_data(self.address, reg, value)
|
||||
if self.debug:
|
||||
print("I2C: Wrote 0x%02X to register pair 0x%02X,0x%02X" %
|
||||
(value, reg, reg+1))
|
||||
except IOError as err:
|
||||
return self.errMsg()
|
||||
|
||||
def writeRaw8(self, value):
|
||||
"Writes an 8-bit value on the bus"
|
||||
try:
|
||||
self.bus.write_byte(self.address, value)
|
||||
if self.debug:
|
||||
print("I2C: Wrote 0x%02X" % value)
|
||||
except IOError as err:
|
||||
return self.errMsg()
|
||||
|
||||
def writeList(self, reg, list):
|
||||
"Writes an array of bytes using I2C format"
|
||||
try:
|
||||
if self.debug:
|
||||
print("I2C: Writing list to register 0x%02X:" % reg)
|
||||
print(list)
|
||||
self.bus.write_i2c_block_data(self.address, reg, list)
|
||||
except IOError as err:
|
||||
return self.errMsg()
|
||||
|
||||
def readList(self, reg, length):
|
||||
"Read a list of bytes from the I2C device"
|
||||
try:
|
||||
results = self.bus.read_i2c_block_data(self.address, reg, length)
|
||||
if self.debug:
|
||||
print("I2C: Device 0x%02X returned the following from reg 0x%02X" %
|
||||
(self.address, reg))
|
||||
print(results)
|
||||
return results
|
||||
except IOError as err:
|
||||
return self.errMsg()
|
||||
|
||||
def readU8(self, reg):
|
||||
"Read an unsigned byte from the I2C device"
|
||||
try:
|
||||
result = self.bus.read_byte_data(self.address, reg)
|
||||
if self.debug:
|
||||
print("I2C: Device 0x%02X returned 0x%02X from reg 0x%02X" %
|
||||
(self.address, result & 0xFF, reg))
|
||||
return result
|
||||
except IOError as err:
|
||||
return self.errMsg()
|
||||
|
||||
def readS8(self, reg):
|
||||
"Reads a signed byte from the I2C device"
|
||||
try:
|
||||
result = self.bus.read_byte_data(self.address, reg)
|
||||
if result > 127: result -= 256
|
||||
if self.debug:
|
||||
print("I2C: Device 0x%02X returned 0x%02X from reg 0x%02X" %
|
||||
(self.address, result & 0xFF, reg))
|
||||
return result
|
||||
except IOError as err:
|
||||
return self.errMsg()
|
||||
|
||||
def readU16(self, reg, little_endian=True):
|
||||
"Reads an unsigned 16-bit value from the I2C device"
|
||||
try:
|
||||
result = self.bus.read_word_data(self.address,reg)
|
||||
# Swap bytes if using big endian because read_word_data assumes little
|
||||
# endian on ARM (little endian) systems.
|
||||
if not little_endian:
|
||||
result = ((result << 8) & 0xFF00) + (result >> 8)
|
||||
if (self.debug):
|
||||
print("I2C: Device 0x%02X returned 0x%04X from reg 0x%02X" % (self.address, result & 0xFFFF, reg))
|
||||
return result
|
||||
except IOError as err:
|
||||
return self.errMsg()
|
||||
|
||||
def readS16(self, reg, little_endian=True):
|
||||
"Reads a signed 16-bit value from the I2C device"
|
||||
try:
|
||||
result = self.readU16(reg,little_endian)
|
||||
if result > 32767: result -= 65536
|
||||
return result
|
||||
except IOError as err:
|
||||
return self.errMsg()
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
bus = Adafruit_I2C(address=0)
|
||||
print("Default I2C bus is accessible")
|
||||
except:
|
||||
print("Error accessing default I2C bus")
|
||||
|
|
@ -0,0 +1,310 @@
|
|||
#!/usr/bin/python
|
||||
# TSL2561 I2C Light-To-Digital converter library for the Raspberry Pi.
|
||||
# Datasheet: https://www.adafruit.com/datasheets/TSL2561.pdf
|
||||
#
|
||||
# This library is based on the work by Cedric Maion https://github.com/cmaion/TSL2561
|
||||
#
|
||||
# Read http://www.dexterindustries.com/topic/greehouse-project/ for the forum discussion about the sensor
|
||||
|
||||
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()
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
This is a Python 2.7 script which can be used to get readings from the Grove Digital Light Sensor(http://www.seeedstudio.com/wiki/Grove_-_Digital_Light_Sensor) connected to the GrovePi on a Raspberry Pi.
|
||||
|
||||
If you set debug = 1 (standard option) it displays all calculations on screen.
|
||||
If you set debug = 0, the script just runs and only displays the output.
|
||||
|
||||
The script get's both the IR-reading and ambient reading from the sensor. It then scales the the readings and calculates the lux-value.
|
||||
|
||||
the main function performs a continuous loop, gets the readings and calculated lux-value and displays the result (depending on the result the output can be normal values and a message 'it's light' or 'it's dark' or a message if the sensor is saturated and no values can be achieved. The loop is repeated with a time.sleep(10) so you can easily read the result on screen.
|
||||
|
||||
If your not interested in the IR or ambient values but just want the lux value, comment out the undisered output lines. Be sure not to comment out the reading and calculating lines in the different functions because you need both the IR and the ambient values in order to calculate the lux value.
|
||||
|
||||
September 2014.
|
||||
Loading…
Add table
Add a link
Reference in a new issue