So you have a tsl2591 sensor? Have I got a deal for you!

The following flow can drive the tsl2591 light intensity sensor. This flow is a bit more involved, based on nodes, than functional code, this was done by design to better illustrate how to use the i2c nodes in NR. Refer to the tsl2591 data sheet for details on gain and integration time settings. This flow does explicit validation for the tsl2591 chip, so it will not work as is with the tsl2561. If someone wanted to send me a tsl2561, I would develop a similar flow for the tsl2561. I have tested this flow against the de-facto standard Adafruit python solution for the tsl2591 board. The results are very similar, there is some very minor variance, but that was due to the light source and ambient background light variance.

[{"id":"29faa2ae.afbbbe","type":"tab","label":"TSL2591 1.0","disabled":false,"info":""},{"id":"f4b75ae3.17c09","type":"i2c in","z":"29faa2ae.afbbbe","name":"TSL2591 Command 177 (Register 0x11)","busno":"1","address":"41","command":"177","count":"1","x":500,"y":200,"wires":[["c04db50e.02a628","37b05060.5f0df8"]]},{"id":"9f6e587f.0f394","type":"inject","z":"29faa2ae.afbbbe","name":"Invoke","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":90,"y":120,"wires":[["e6a250fc.08bc08"]]},{"id":"82337db8.a90a2","type":"i2c in","z":"29faa2ae.afbbbe","name":"TSL2591 Command 178 (Register 0x12)","busno":"1","address":"41","command":"178","count":"1","x":500,"y":100,"wires":[["7bcef52c.068e4c","82a46e27.43d5e"]]},{"id":"7bcef52c.068e4c","type":"debug","z":"29faa2ae.afbbbe","name":"Message","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":760,"y":120,"wires":[]},{"id":"e6a250fc.08bc08","type":"function","z":"29faa2ae.afbbbe","name":"Calculate","func":"// For TSL2591, Id Bits, 5:4 Package, 7:0 Device\n\nconst theRegister = 18,     // 0x12\n      theMask = 255,        // 0xFF\n      theCommand = 160;     // 0xA0\n\nmsg.command = theRegister | theCommand & theMask;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":240,"y":120,"wires":[["b1da7f72.e27098","82337db8.a90a2"]]},{"id":"b1da7f72.e27098","type":"debug","z":"29faa2ae.afbbbe","name":"Command","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"command","targetType":"msg","statusVal":"","statusType":"auto","x":410,"y":140,"wires":[]},{"id":"43cf5ced.a6d5d4","type":"function","z":"29faa2ae.afbbbe","name":"Calculate","func":"// For TSL2591, Id Bits, 5:4 Package, 7:0 Device\n\nconst theRegister = 17,     // 0x12\n      theMask = 255,        // 0xFF\n      theCommand = 160;     // 0xA0\n\nmsg.command = theRegister | theCommand & theMask;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":240,"y":220,"wires":[["f4b75ae3.17c09","6569a501.0a17ac"]]},{"id":"82a46e27.43d5e","type":"switch","z":"29faa2ae.afbbbe","name":"TSL2591?","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"80","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":770,"y":80,"wires":[["6990fbba.b0a1ec"],["73d46acf.90ecc4"]]},{"id":"6990fbba.b0a1ec","type":"change","z":"29faa2ae.afbbbe","name":"Found","rules":[{"t":"set","p":"tsl2591","pt":"msg","to":"true","tot":"bool"},{"t":"set","p":"id","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":930,"y":60,"wires":[["a7362d33.05ab38","f0f41633.a51bd"]]},{"id":"a7362d33.05ab38","type":"debug","z":"29faa2ae.afbbbe","name":"Message","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1100,"y":80,"wires":[]},{"id":"73d46acf.90ecc4","type":"change","z":"29faa2ae.afbbbe","name":"!Found","rules":[{"t":"set","p":"tsl2591","pt":"msg","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":940,"y":100,"wires":[["a7362d33.05ab38"]]},{"id":"c04db50e.02a628","type":"function","z":"29faa2ae.afbbbe","name":"Evalaute","func":"// For TSL2591, Id Bits, 5:4 Package, 7:0 Device\n\nfunction BitExtract(theNumber, theLength, thePosition) \n{ \n    return (((1 << theLength) - 1) & (theNumber >> (thePosition - 1))); \n} \n    \nmsg.package = BitExtract(msg.payload, 2, 4);\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":760,"y":180,"wires":[["ee0d1555.6c2198"]]},{"id":"f0f41633.a51bd","type":"link out","z":"29faa2ae.afbbbe","name":"","links":["be1a09d4.2d96c"],"x":1055,"y":40,"wires":[]},{"id":"be1a09d4.2d96c","type":"link in","z":"29faa2ae.afbbbe","name":"","links":["f0f41633.a51bd"],"x":115,"y":220,"wires":[["43cf5ced.a6d5d4"]]},{"id":"c9f8c643.f379f8","type":"i2c out","z":"29faa2ae.afbbbe","name":"Write Gain","busno":"1","address":"41","command":"1","payload":"","payloadType":"num","count":"1","x":930,"y":260,"wires":[["db193ff8.d6a75"]]},{"id":"55283e78.61d7b","type":"i2c in","z":"29faa2ae.afbbbe","name":"Channel 0","busno":"1","address":"41","command":"180","count":"2","x":590,"y":500,"wires":[["4e66ca9b.a82d5c"]]},{"id":"e10dcf27.e022c","type":"i2c in","z":"29faa2ae.afbbbe","name":"Channel 1","busno":"1","address":"41","command":"182","count":"2","x":590,"y":600,"wires":[["e66697c0.0f5148"]]},{"id":"1b7dc767.56da99","type":"debug","z":"29faa2ae.afbbbe","name":"Message","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":940,"y":620,"wires":[]},{"id":"ac855e49.ffc8d8","type":"debug","z":"29faa2ae.afbbbe","name":"Message","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":940,"y":520,"wires":[]},{"id":"e6f51a6.93e1468","type":"function","z":"29faa2ae.afbbbe","name":"Calculate Lux Level","func":"// Gain...\nconst MAXIMUM = 48,     // 0x30 (9876x)\n      HIGH = 32,        // 0x20 (428x)\n      LOW = 0,          // 0x00 (1x)\n      MEDIUM = 16;      // 0x10 (25x)\n\n// Integration Time...\nconst _100MS = 0,       // 0x00 100 millis\n      _200MS = 1,       // 0x01 200 millis\n      _300MS = 2,       // 0x02 300 millis\n      _400MS = 3,       // 0x03 400 millis\n      _500MS = 4,       // 0x04 500 millis\n      _600MS = 5;       // 0x05 600 millis\n\n// Command / Register...\nconst ADDRESS = 0x29,\n      COMMAND = 0xA0,\n      OFF = 0x00,\n      ON = 0x01,\n      AEN = 0x02,\n      AIEN = 0x10,\n      NPIEN = 0x80,\n      ENABLE = 0x00,\n      CONTROL = 0x01,\n      ID = 0x12,\n      CHAN0_LOW = 0x14,\n      CHAN1_LOW = 0x16;\n\nconst LUX_COEFB = 1.64,\n      LUX_DF = 408.0,\n      LUX_COEFC = 0.59,\n      LUX_COEFD = 0.86;\n\nconst LIMIT_100MS = 36863,  // 0x8FFF\n      LIMIT = 65535;        // 0xFFFF\n\nconst TIME = 100.0;\n\ndelete msg.payload;\n\nmsg.spectrum = (msg.channel1 << 16) | msg.channel0;\nmsg.visible = msg.spectrum - msg.channel1;\nmsg.infrared = msg.channel1;\n\n//\nvar theLimit = (msg.time == _100MS) ? LIMIT_100MS : LIMIT,\n    theGain = 1.0,\n    theTime = (TIME * msg.time) + TIME;\n\nif (msg.channel0 >= theLimit || msg.channel1 >= theLimit) {\n  \n    //  \n    msg.error = true;\n    msg.lux = NaN;\n    \n} else {\n\n    //\n    if (msg.gain == MAXIMUM)\n        theGain = 9876.0;\n    if (msg.gain == HIGH)\n        theGain = 428.0;\n    if (msg.gain == MEDIUM)\n        theGain = 25.0;\n\n    var theDivisor = (theTime * theGain) / LUX_DF;\n    var theLux = (msg.channel0 - (LUX_COEFB * msg.channel1)) / theDivisor;\n    var theAlternate = ((LUX_COEFC * msg.channel0) - (LUX_COEFD * msg.channel1)) / theDivisor;\n    \n    msg.lux = Math.max(theLux, theAlternate);\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":970,"y":580,"wires":[["d7d4b393.ba0048"]]},{"id":"d7d4b393.ba0048","type":"debug","z":"29faa2ae.afbbbe","name":"Message","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1160,"y":580,"wires":[]},{"id":"c8da21f7.e9c3f","type":"function","z":"29faa2ae.afbbbe","name":"Command 0","func":"const theChannel = 20; // 0x14\nconst theCommand = 160; // 0xA0\nconst theInvert = 255; // 0xFF\n\nmsg.command0 = (theCommand | theChannel) & theInvert;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":410,"y":520,"wires":[["55283e78.61d7b","93b03f3c.5cb76"]]},{"id":"ac3c5218.be266","type":"function","z":"29faa2ae.afbbbe","name":"Command 1","func":"const theChannel = 22; // 0x14\nconst theCommand = 160; // 0xA0\nconst theInvert = 255; // 0xFF\n\nmsg.command1 = (theCommand | theChannel) & theInvert;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":410,"y":620,"wires":[["e10dcf27.e022c","b9611cae.c5d198"]]},{"id":"b9611cae.c5d198","type":"debug","z":"29faa2ae.afbbbe","name":"Message","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":580,"y":640,"wires":[]},{"id":"93b03f3c.5cb76","type":"debug","z":"29faa2ae.afbbbe","name":"Command 0","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"command0","targetType":"msg","statusVal":"","statusType":"auto","x":590,"y":540,"wires":[]},{"id":"4e66ca9b.a82d5c","type":"function","z":"29faa2ae.afbbbe","name":"Channel 0","func":"msg.channel0 = (msg.payload[1] << 8) | msg.payload[0];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":770,"y":500,"wires":[["ac855e49.ffc8d8","4429cc2f.2f0014"]]},{"id":"e66697c0.0f5148","type":"function","z":"29faa2ae.afbbbe","name":"Channel 1","func":"msg.channel1 = (msg.payload[1] << 8) | msg.payload[0];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":770,"y":600,"wires":[["1b7dc767.56da99","e6f51a6.93e1468"]]},{"id":"4429cc2f.2f0014","type":"link out","z":"29faa2ae.afbbbe","name":"","links":["57028fbf.578b18"],"x":895,"y":480,"wires":[]},{"id":"57028fbf.578b18","type":"link in","z":"29faa2ae.afbbbe","name":"","links":["4429cc2f.2f0014"],"x":275,"y":620,"wires":[["ac3c5218.be266"]]},{"id":"4094e57c.a50a94","type":"link in","z":"29faa2ae.afbbbe","name":"","links":["ff8861f6.4dfda","372bf0da.59fa58"],"x":275,"y":520,"wires":[["c8da21f7.e9c3f"]]},{"id":"3e5da301.57b634","type":"link in","z":"29faa2ae.afbbbe","name":"","links":["ee0d1555.6c2198"],"x":275,"y":320,"wires":[["e07e0f30.fe5608"]]},{"id":"e07e0f30.fe5608","type":"i2c in","z":"29faa2ae.afbbbe","name":"Read Gain","busno":"1","address":"41","command":"1","count":"1","x":410,"y":320,"wires":[["b5b2589c.f33d38","3e9c7da.2f9f482"]]},{"id":"b5b2589c.f33d38","type":"debug","z":"29faa2ae.afbbbe","name":"Message","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":580,"y":340,"wires":[]},{"id":"3e9c7da.2f9f482","type":"function","z":"29faa2ae.afbbbe","name":"Get Gain","func":"var theControl = msg.payload;\n\ntheControl = theControl & 48;   // 00110000\n\nmsg.gain = theControl;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":580,"y":300,"wires":[["4b695605.06a08","4fabf2fc.232edc"]]},{"id":"4b695605.06a08","type":"debug","z":"29faa2ae.afbbbe","name":"Message","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":740,"y":320,"wires":[]},{"id":"ee0d1555.6c2198","type":"link out","z":"29faa2ae.afbbbe","name":"","links":["3e5da301.57b634"],"x":875,"y":180,"wires":[]},{"id":"6569a501.0a17ac","type":"debug","z":"29faa2ae.afbbbe","name":"Command","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"command","targetType":"msg","statusVal":"","statusType":"auto","x":410,"y":240,"wires":[]},{"id":"37b05060.5f0df8","type":"debug","z":"29faa2ae.afbbbe","name":"Message","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":760,"y":220,"wires":[]},{"id":"4fabf2fc.232edc","type":"function","z":"29faa2ae.afbbbe","name":"Set Gain","func":"const GAIN = 16;    // 0x10 Medium Gain Per Data Sheet\n\nvar theControl = msg.gain;\n\ntheControl &= 207;  // 11001111\ntheControl |= GAIN;\n\nmsg.payload = theControl;\nmsg.gain = GAIN;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":750,"y":280,"wires":[["c9f8c643.f379f8","948b2ac0.4d51f"]]},{"id":"948b2ac0.4d51f","type":"debug","z":"29faa2ae.afbbbe","name":"Message","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":920,"y":300,"wires":[]},{"id":"773ec64a.4ef4f","type":"i2c in","z":"29faa2ae.afbbbe","name":"Read Time","busno":"1","address":"41","command":"1","count":"1","x":410,"y":420,"wires":[["cb0402da.4effd8","d4018b5b.ec8a7"]]},{"id":"db193ff8.d6a75","type":"link out","z":"29faa2ae.afbbbe","name":"","links":["b15fbeb3.fc37d8"],"x":1055,"y":260,"wires":[]},{"id":"b15fbeb3.fc37d8","type":"link in","z":"29faa2ae.afbbbe","name":"","links":["db193ff8.d6a75"],"x":275,"y":420,"wires":[["773ec64a.4ef4f"]]},{"id":"cb0402da.4effd8","type":"function","z":"29faa2ae.afbbbe","name":"Get Time","func":"var theControl = msg.payload;\n\ntheControl = theControl & 7;   // 00000111\n\nmsg.time = theControl;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":580,"y":400,"wires":[["6bb19ea4.fccb1","5f1134b1.c285e4"]]},{"id":"d4018b5b.ec8a7","type":"debug","z":"29faa2ae.afbbbe","name":"Message","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":580,"y":440,"wires":[]},{"id":"6bb19ea4.fccb1","type":"function","z":"29faa2ae.afbbbe","name":"Set Time","func":"const TIME = 0;    // 0x00 100 ms Integration Time Per Data Sheet\n\nvar theControl = msg.time;\n\ntheControl &= 248;  // 11111000\ntheControl |= TIME;\n\nmsg.payload = theControl;\nmsg.time = TIME;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":740,"y":380,"wires":[["32bed05b.579bf8","56186f47.1e422"]]},{"id":"5f1134b1.c285e4","type":"debug","z":"29faa2ae.afbbbe","name":"Message","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":740,"y":420,"wires":[]},{"id":"32bed05b.579bf8","type":"debug","z":"29faa2ae.afbbbe","name":"Message","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":900,"y":400,"wires":[]},{"id":"56186f47.1e422","type":"i2c out","z":"29faa2ae.afbbbe","name":"Write Gain","busno":"1","address":"41","command":"1","payload":"","payloadType":"num","count":"1","x":910,"y":360,"wires":[["372bf0da.59fa58"]]},{"id":"372bf0da.59fa58","type":"link out","z":"29faa2ae.afbbbe","name":"","links":["4094e57c.a50a94"],"x":1045,"y":360,"wires":[]},{"id":"2d890c32.f17a74","type":"inject","z":"29faa2ae.afbbbe","name":"Power On","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"147","payloadType":"num","x":100,"y":760,"wires":[["248e572d.18442"]]},{"id":"43eb73e6.f0853c","type":"inject","z":"29faa2ae.afbbbe","name":"Power Off","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":100,"y":800,"wires":[["acbecbbf.60844"]]},{"id":"32eff58e.46bc8a","type":"i2c out","z":"29faa2ae.afbbbe","name":"On","busno":"1","address":"41","command":"0","payload":"payload","payloadType":"msg","count":"1","x":390,"y":760,"wires":[["df7f4df7.3ca4f8"]]},{"id":"bfb830db.a98718","type":"function","z":"29faa2ae.afbbbe","name":"On Or Off","func":"const OFF = 0,      // 0x00\n      ON =  1,      // 0x01\n      AEN = 2,      // 0x02\n      AIEN = 16,    // 0x10\n      NPIEN = 128,  // 0x80\n      ENABLE = 0;   // 0x00\n      \n//msg.on = ParseInt(ON | AEN | AIEN | NPIEN);\n//msg.off = ParseInt(OFF);\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":100,"y":720,"wires":[[]],"icon":"font-awesome/fa-comment"},{"id":"df7f4df7.3ca4f8","type":"debug","z":"29faa2ae.afbbbe","name":"Message","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":540,"y":780,"wires":[]},{"id":"702ae505.6c9a74","type":"i2c out","z":"29faa2ae.afbbbe","name":"Off","busno":"1","address":"41","command":"0","payload":"payload","payloadType":"msg","count":"1","x":390,"y":800,"wires":[["df7f4df7.3ca4f8"]]},{"id":"acbecbbf.60844","type":"function","z":"29faa2ae.afbbbe","name":"Adjust","func":"const HALF = 127,\n      FULL = 256;\n      \nmsg.payload = msg.payload > HALF ? msg.payload - FULL : msg.payload;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":250,"y":800,"wires":[["702ae505.6c9a74"]]},{"id":"248e572d.18442","type":"function","z":"29faa2ae.afbbbe","name":"Adjust","func":"const HALF = 127,\n      FULL = 256;\n      \nmsg.payload = msg.payload > HALF ? msg.payload - FULL : msg.payload;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":250,"y":760,"wires":[["32eff58e.46bc8a"]]},{"id":"d7e81225.97b148","type":"comment","z":"29faa2ae.afbbbe","name":"Adjust Required For Known Node Red Module Issue (Range -128 to 127) When Should Be 0-255","info":"","x":550,"y":720,"wires":[]},{"id":"69f7e8d1.61f058","type":"comment","z":"29faa2ae.afbbbe","name":"Default Gain Medium And Default Integration Time 100 ms","info":"","x":230,"y":60,"wires":[]}]

This flow, with applicable integration will be used to monitor the lights on the various fans I have around the house, to provide feed back on when or if the fan light fails to illuminate, since I have Pi Zero devices in most of the rooms of the house. Also plan to use it in the garage, so that if someone leave the lights on, NR can turn them off. :slight_smile: