grove_digital_light

Files at this revision

API Documentation at this revision

Comitter:
JackyZhangFromSeeed
Date:
Tue Jun 09 10:17:49 2015 +0000
Commit message:
grove_digital_light

Changed in this revision

grove_digital_light.cpp Show annotated file Show diff for this revision Revisions of this file
grove_digital_light.h Show annotated file Show diff for this revision Revisions of this file
grove_digital_light_class.cpp Show annotated file Show diff for this revision Revisions of this file
grove_digital_light_class.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 54ed8f245631 grove_digital_light.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/grove_digital_light.cpp	Tue Jun 09 10:17:49 2015 +0000
@@ -0,0 +1,155 @@
+
+
+#include "suli2.h"
+#include "grove_digital_light.h"
+
+
+
+//local functions
+static void grove_digital_light_getlux(I2C_T *i2c);
+static unsigned long grove_digital_light_calculatelux(unsigned int iGain, unsigned int tInt, int iType);
+
+//local variables
+static unsigned char cmdbuf[2];
+static uint16_t ch0, ch1;
+static unsigned long chScale;
+static unsigned long channel1;
+static unsigned long channel0;
+static unsigned long  ratio1;
+static unsigned int b;
+static unsigned int m;
+static unsigned long temp;
+static unsigned long lux;
+
+
+
+void grove_digital_light_init(I2C_T *i2c, int pinsda, int pinscl)
+{
+    suli_i2c_init(i2c, pinsda, pinscl);
+}
+
+bool grove_digital_light_write_setup(I2C_T *i2c)
+{
+    cmdbuf[0] = TSL2561_Control;
+    cmdbuf[1] = 0x03;
+    suli_i2c_write(i2c, TSL2561_Address, cmdbuf, 2);  // POWER UP
+    cmdbuf[0] = TSL2561_Timing;
+    cmdbuf[1] = 0x00;
+    suli_i2c_write(i2c, TSL2561_Address, cmdbuf, 2);  //No High Gain (1x), integration time of 13ms
+    cmdbuf[0] = TSL2561_Interrupt;
+    cmdbuf[1] = 0x00;
+    suli_i2c_write(i2c, TSL2561_Address, cmdbuf, 2);  
+    cmdbuf[0] = TSL2561_Control;
+    cmdbuf[1] = 0x00;
+    suli_i2c_write(i2c, TSL2561_Address, cmdbuf, 2);  // POWER Down
+    
+    return true;
+}
+
+static void grove_digital_light_getlux(I2C_T *i2c)
+{
+    uint8_t CH0_LOW = 0, CH0_HIGH = 0, CH1_LOW = 0, CH1_HIGH = 0;
+
+    cmdbuf[0] = TSL2561_Channal0L;
+    suli_i2c_write(i2c, TSL2561_Address, cmdbuf, 1);
+    suli_i2c_read(i2c, TSL2561_Address, &CH0_LOW, 1);
+    cmdbuf[0] = TSL2561_Channal0H;
+    suli_i2c_write(i2c, TSL2561_Address, cmdbuf, 1);
+    suli_i2c_read(i2c, TSL2561_Address, &CH0_HIGH, 1);
+    cmdbuf[0] = TSL2561_Channal1L;
+    suli_i2c_write(i2c, TSL2561_Address, cmdbuf, 1);
+    suli_i2c_read(i2c, TSL2561_Address, &CH1_LOW, 1);
+    cmdbuf[0] = TSL2561_Channal1H;
+    suli_i2c_write(i2c, TSL2561_Address, cmdbuf, 1);
+    suli_i2c_read(i2c, TSL2561_Address, &CH1_HIGH, 1);
+
+    ch0 = (CH0_HIGH<<8) | CH0_LOW;
+    ch1 = (CH1_HIGH<<8) | CH1_LOW;
+}
+
+static unsigned long grove_digital_light_calculatelux(unsigned int iGain, unsigned int tInt, int iType)
+{
+    switch (tInt)
+    {
+        case 0:  // 13.7 msec
+            chScale = CHSCALE_TINT0;
+            break;
+        case 1: // 101 msec
+            chScale = CHSCALE_TINT1;
+            break;
+        default: // assume no scaling
+            chScale = (1 << CH_SCALE);
+            break;
+    }
+    if (!iGain)  chScale = chScale << 4; // scale 1X to 16X
+    // scale the channel values
+    channel0 = (ch0 * chScale) >> CH_SCALE;
+    channel1 = (ch1 * chScale) >> CH_SCALE;
+
+    ratio1 = 0;
+    if (channel0!= 0) ratio1 = (channel1 << (RATIO_SCALE+1))/channel0;
+    // round the ratio value
+    unsigned long ratio = (ratio1 + 1) >> 1;
+
+    switch (iType)
+    {
+        case 0: // T package
+            if ((ratio >= 0) && (ratio <= K1T))
+            {b=B1T; m=M1T;}
+            else if (ratio <= K2T)
+            {b=B2T; m=M2T;}
+            else if (ratio <= K3T)
+            {b=B3T; m=M3T;}
+            else if (ratio <= K4T)
+            {b=B4T; m=M4T;}
+            else if (ratio <= K5T)
+            {b=B5T; m=M5T;}
+            else if (ratio <= K6T)
+            {b=B6T; m=M6T;}
+            else if (ratio <= K7T)
+            {b=B7T; m=M7T;}
+            else if (ratio > K8T)
+            {b=B8T; m=M8T;}
+            break;
+        case 1:// CS package
+            if ((ratio >= 0) && (ratio <= K1C))
+            {b=B1C; m=M1C;}
+            else if (ratio <= K2C)
+            {b=B2C; m=M2C;}
+            else if (ratio <= K3C)
+            {b=B3C; m=M3C;}
+            else if (ratio <= K4C)
+            {b=B4C; m=M4C;}
+            else if (ratio <= K5C)
+            {b=B5C; m=M5C;}
+            else if (ratio <= K6C)
+            {b=B6C; m=M6C;}
+            else if (ratio <= K7C)
+            {b=B7C; m=M7C;}
+    }
+    temp=((channel0*b)-(channel1*m));
+    if(temp<0) temp=0;
+    temp+=(1<<(LUX_SCALE-1));
+    // strip off fractional portion
+    lux=temp>>LUX_SCALE;
+    return (lux);
+}
+
+bool grove_digital_light_readvisiblelux(I2C_T *i2c, uint32_t *lux)
+{
+    cmdbuf[0] = TSL2561_Control;
+    cmdbuf[1] = 0x03;
+    suli_i2c_write(i2c, TSL2561_Address, cmdbuf, 2);  // POWER UP
+    suli_delay_ms(14);
+    grove_digital_light_getlux(i2c);
+
+    cmdbuf[0] = TSL2561_Control;
+    cmdbuf[1] = 0x00;
+    suli_i2c_write(i2c, TSL2561_Address, cmdbuf, 2);  // POWER Down
+    if(ch0/ch1 < 2 && ch0 > 4900)
+    {
+        return -1;  //ch0 out of range, but ch1 not. the lux is not valid in this situation.
+    }
+    *lux = grove_digital_light_calculatelux(0, 0, 0);  //T package, no gain, 13ms
+    return true;
+}
diff -r 000000000000 -r 54ed8f245631 grove_digital_light.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/grove_digital_light.h	Tue Jun 09 10:17:49 2015 +0000
@@ -0,0 +1,79 @@
+
+
+
+#ifndef __GROVE_DIGITAL_LIGHT_H__
+#define __GROVE_DIGITAL_LIGHT_H__
+
+#include "suli2.h"
+
+#define TSL2561_Address  (0x29<<1)       //device address
+
+#define  TSL2561_Control  0x80
+#define  TSL2561_Timing   0x81
+#define  TSL2561_Interrupt 0x86
+#define  TSL2561_Channal0L 0x8C
+#define  TSL2561_Channal0H 0x8D
+#define  TSL2561_Channal1L 0x8E
+#define  TSL2561_Channal1H 0x8F
+
+#define LUX_SCALE 14           // scale by 2^14
+#define RATIO_SCALE 9          // scale ratio by 2^9
+#define CH_SCALE 10            // scale channel values by 2^10
+#define CHSCALE_TINT0 0x7517   // 322/11 * 2^CH_SCALE
+#define CHSCALE_TINT1 0x0fe7   // 322/81 * 2^CH_SCALE
+
+#define K1T 0x0040   // 0.125 * 2^RATIO_SCALE
+#define B1T 0x01f2   // 0.0304 * 2^LUX_SCALE
+#define M1T 0x01be   // 0.0272 * 2^LUX_SCALE
+#define K2T 0x0080   // 0.250 * 2^RATIO_SCA
+#define B2T 0x0214   // 0.0325 * 2^LUX_SCALE
+#define M2T 0x02d1   // 0.0440 * 2^LUX_SCALE
+#define K3T 0x00c0   // 0.375 * 2^RATIO_SCALE
+#define B3T 0x023f   // 0.0351 * 2^LUX_SCALE
+#define M3T 0x037b   // 0.0544 * 2^LUX_SCALE
+#define K4T 0x0100   // 0.50 * 2^RATIO_SCALE
+#define B4T 0x0270   // 0.0381 * 2^LUX_SCALE
+#define M4T 0x03fe   // 0.0624 * 2^LUX_SCALE
+#define K5T 0x0138   // 0.61 * 2^RATIO_SCALE
+#define B5T 0x016f   // 0.0224 * 2^LUX_SCALE
+#define M5T 0x01fc   // 0.0310 * 2^LUX_SCALE
+#define K6T 0x019a   // 0.80 * 2^RATIO_SCALE
+#define B6T 0x00d2   // 0.0128 * 2^LUX_SCALE
+#define M6T 0x00fb   // 0.0153 * 2^LUX_SCALE
+#define K7T 0x029a   // 1.3 * 2^RATIO_SCALE
+#define B7T 0x0018   // 0.00146 * 2^LUX_SCALE
+#define M7T 0x0012   // 0.00112 * 2^LUX_SCALE
+#define K8T 0x029a   // 1.3 * 2^RATIO_SCALE
+#define B8T 0x0000   // 0.000 * 2^LUX_SCALE
+#define M8T 0x0000   // 0.000 * 2^LUX_SCALE
+
+#define K1C 0x0043   // 0.130 * 2^RATIO_SCALE
+#define B1C 0x0204   // 0.0315 * 2^LUX_SCALE
+#define M1C 0x01ad   // 0.0262 * 2^LUX_SCALE
+#define K2C 0x0085   // 0.260 * 2^RATIO_SCALE
+#define B2C 0x0228   // 0.0337 * 2^LUX_SCALE
+#define M2C 0x02c1   // 0.0430 * 2^LUX_SCALE
+#define K3C 0x00c8   // 0.390 * 2^RATIO_SCALE
+#define B3C 0x0253   // 0.0363 * 2^LUX_SCALE
+#define M3C 0x0363   // 0.0529 * 2^LUX_SCALE
+#define K4C 0x010a   // 0.520 * 2^RATIO_SCALE
+#define B4C 0x0282   // 0.0392 * 2^LUX_SCALE
+#define M4C 0x03df   // 0.0605 * 2^LUX_SCALE
+#define K5C 0x014d   // 0.65 * 2^RATIO_SCALE
+#define B5C 0x0177   // 0.0229 * 2^LUX_SCALE
+#define M5C 0x01dd   // 0.0291 * 2^LUX_SCALE
+#define K6C 0x019a   // 0.80 * 2^RATIO_SCALE
+#define B6C 0x0101   // 0.0157 * 2^LUX_SCALE
+#define M6C 0x0127   // 0.0180 * 2^LUX_SCALE
+#define K7C 0x029a   // 1.3 * 2^RATIO_SCALE
+#define B7C 0x0037   // 0.00338 * 2^LUX_SCALE
+#define M7C 0x002b   // 0.00260 * 2^LUX_SCALE
+#define K8C 0x029a   // 1.3 * 2^RATIO_SCALE
+#define B8C 0x0000   // 0.000 * 2^LUX_SCALE
+#define M8C 0x0000   // 0.000 * 2^LUX_SCALE
+
+void grove_digital_light_init(I2C_T *i2c, int pinsda, int pinscl);
+bool grove_digital_light_write_setup(I2C_T *i2c);
+bool grove_digital_light_readvisiblelux(I2C_T *i2c, uint32_t *lux);
+
+#endif
diff -r 000000000000 -r 54ed8f245631 grove_digital_light_class.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/grove_digital_light_class.cpp	Tue Jun 09 10:17:49 2015 +0000
@@ -0,0 +1,22 @@
+
+
+#include "grove_digital_light_class.h"
+
+GroveDigitalLight::GroveDigitalLight(int pinsda, int pinscl)
+{
+    this->i2c = (I2C_T *)malloc(sizeof(I2C_T));
+    grove_digital_light_init(this->i2c, pinsda, pinscl);
+}
+
+bool GroveDigitalLight::write_setup(void)
+{
+    return grove_digital_light_write_setup(this->i2c);
+}
+
+bool GroveDigitalLight::read_lux(uint32_t *lux)
+{
+    return grove_digital_light_readvisiblelux(this->i2c, lux);
+}
+
+
+
diff -r 000000000000 -r 54ed8f245631 grove_digital_light_class.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/grove_digital_light_class.h	Tue Jun 09 10:17:49 2015 +0000
@@ -0,0 +1,24 @@
+
+
+
+#ifndef __GROVE_DIGITAL_LIGHT_CLASS_H__
+#define __GROVE_DIGITAL_LIGHT_CLASS_H__
+
+#include "grove_digital_light.h"
+
+//GROVE_NAME        "Grove_DigitalLight"
+//IF_TYPE           I2C
+//IMAGE_URL         http://www.seeedstudio.com/wiki/File:Digital_Light_Sensor.jpg
+
+class GroveDigitalLight
+{
+public:
+    GroveDigitalLight(int pinsda, int pinscl);
+    bool write_setup(void);
+    bool read_lux(uint32_t *lux);
+
+private:
+    I2C_T *i2c;
+};
+
+#endif