TEMT6200 - Ambient light sensor library for Wi-Go board

Dependents:   TEMT6200_demo Wi-Go_IOT_Demo MMA8451Q IoT_World_Hackathon_WiGo_NSP_Demo ... more

TEMT6200 library


TEMT6200 specifications

TEMT6200 datasheet

Photo current Ipce4.6uA @ 20lux
7.5 .. 39uA @ 100lux
average = (7.5 + 39)/2 = 23.25uA
Dark currenttypical 3nA
max. 50nA

IMPORTANT NOTE
There are 3 binned groups defining Ipce min/max @ 100lux.
If the BIN group is unknown, we use the overall average Ipce value @ 100lux = 23.25uA

BINminmaxavg
Group AIpce (uA)7.51511.25
Group BIpce (uA)122418
Group CIpce (uA)19.53929.25

Schematic: Wi-Go KL25Z kit - TEMT6200 wiring

/media/uploads/frankvnk/temt6200_wi-go_diagram.jpg

  • U8 - Collector : directly connected to PTD5 - AMBLGHT_EN = 3v3
  • U8 - Emitter : connected to GND through 1k resistor (R42). Wired to non-inverting amplifier (U7 - MAX9636) - amplification = 11.
  • MAX9636 : output wired to PTB0 (ADC0_SE8 analog in) and PTC8 (CMP0_IN2 comparator in) = AMBLGHT_LVL label.

Formulas

AnalogIn.read() returns a float value between 0.0 and 1.0
A/D converter input : full scale = 3v3
VR42 (V) = AnalogIn.read() * 3.3 / 11
IR42 (A) = VR42 / R42 = VR42 / 1000
Since R42 = 1000ohm, IR42 in mA = VR42

Basic theoretical formula

                          100lux * IR42   100 * IR42(mA)
Ev (illuminance in lux) = ------------- = --------------
                           Ipce@100lux      0.02325mA


Complete formula
This formula only applies to the Wi-Go board since we set the amplification and reference voltage to a fixed level.
see further for a generic formula.
Current in mA
Voltage in V
Ipce = value @ 100lux in mA
Ain = AnalogIn.read() value

                       Ain * 3.3
                       ---------
                          11             Ain * 3.3   Ain * 330   Ain * 30
      Ev (lux) = 100 * --------- = 100 * --------- = --------- = --------
                         Ipce            11 * Ipce   11 * Ipce     Ipce


Theoretical values for 1..1000lux
Reference is current @ 100lux.

luxcurrent (uA)
10023.25
10.2325
1000232.5

R42 = 1k => VR42 @ 1lux    = 232.5nA * 1000 = 232.5uV  => AMBLGHT_LVL = 11 x VR42 = 2.5575mV
            VR42 @ 1000lux = 232.5uA * 1000 = 232.5mV  => AMBLGHT_LVL = 11 x VR42 = 2.5575V

Extrapolate to full scale (3.3V) - Max. level = 1290 lux.

NOTE
These values are calculated without taking the dark current into account.
Worst case deviation = 50nA dark current.

1lux    = 232.5nA - 50nA = 182.50nA (21.5% error)
1000lux = 232.5uA - 50nA = 232.45uA


We can measure the actual dark current by taping off the sensor and reading the A/D value using the calibrate() function.

  • The resulting value will also contain the A/D-D/A error, resistor value error and external interferences.
  • Temperature drift is not included.

This value can be used in our formula to even out basic conversion errors.

Calibrate function : We take 10 consecutive samples discarding samples > 0.000050

                     ds   = discarded samples
                     sa   = sum of samples
                     ns   = number of samples     = 10
                     amp  = opamp amplification   = 11
                     Vref = DAC reference voltage = 3.3V

                     If ds = ns : set dark_current = 0

                                         (sa / (ns - ds)) * Vref   (sa / (ns - ds)) * 3.3     sa * 3.3
                     dark_current (mA) = ----------------------- = ---------------------- = ------------
                                                    amp                       11            (ns-ds) * 11


Generic complete formula
Inserting the dark current calculation into the complete formula gives us following generic formula:

Ain  = Analog input value read from input (float) 0.0 .. 1.0
amp  = opamp amplification
Vref = DAC reference voltage (V)
Ipce = theoretical average current @ 100lux (mA)
dc   = averaged dark current obtained from calibrate() function (mA)

                       Ain * Vref
                       ----------
                          amp      100 * Ain * Vref
      Ev (lux) = 100 * --------- = -----------------
                       Ipce - dc   amp * (Ipce - dc)

TEMT6200.h contains defines allowing us to easily modify each parameter:

#define TEMT_AREF          (float)3.3           // Analog reference voltage
#define TEMT_MAXLX         1290                 // Calculated max. lux
#define TEMT_AMP           11                   // Op-amp amplification
#define TEMT_IAVG          (float)0.02325       // Theoretical average Ipce @ 100lux
#define TEMT_DARKC         (float)0.000050      // Max. dark current


Used in our formula : Vref = TEMT_AREF
                      amp  = TEMT_AMP
                      Ipce = TEMT_IAVG

Calibration

The ambient light sensor needs to be completely obscured when we use the calibrate() function.
The function takes 10 consecutive 'dark current' samples and calculates the average value of these samples.
This value is subtracted from the theoretical mean value (23.25uA).
Safeguards are built into this function:

  • Each value larger than the max. dark current specified in the datasheet is discarded.
  • When all values are out of range, the theoretical mean value is used (23.25uA).
    So, a valid result is set even when we forget to obscure the ambient light sensor.

Generating an interrupt when a certain level is reached

The ComparatorIn library can be used to generate an interrupt on a specified level.

We can choose between two D/A channels (input range : 0.0 .. 1.0) to set the threshold level:

  • An internal 6-bit DAC
    range is from Vin / 64 to Vin.
    With Vref = 3.3V, each step = 3.3 / 64 = 51.56mV.
    This corresponds to 20.16 lux / step (very limited).
  • An external 12-bit DAC at PTE30
    range is from Vin / 4096 to Vin.
    With Vref = 3.3V, each step = 3.3 / 4096 = 0.806mV.
    This corresponds to 0.315 lux / step.
    This connection can only be used when no external output is connected to PTE30.

Calculating the comparator threshold level
The lux_pct(nnn) function allows us to translate a lux value to an analog level suitable for setting the ComparatorIn threshold, regardless which D/A converter is used (6-bit or 12-bit).


Sample code

#include "TEMT6200.h"
#include "ComparatorIn.h"
#include "mbed.h"

void ambi_rise(void);       // ISR callback pointer
void ambi_fall(void);       // ISR callback pointer

// RGB LED
DigitalOut cmpled (LED_GREEN);
DigitalOut blinky (LED_BLUE);

// Ambient light sensor to comparator plus input = PTC8, min input = 12-bit DAC0
ComparatorIn compi(PTC8, PTE30);

// Ambient light sensor : PTD5 = enable, PTB0 = analog input
TEMT6200 ambi(PTD5, PTB0);

int main()
{
    // Ambient light detector
    ambi.pwr(AMB_ON);
    printf("\n- Ambient light sensor calibration.\n");
    printf("  Make sure the sensor is obscured .\n");
    printf("  Press any key to calibrate.\n");
    getchar();
    ambi.calibrate();                                 // Calibrate 
    printf("- Calibration finished.\n");

    // Comparator settings
    compi.rising(&ambi_rise);                         // Set comparator rising int callback to ambi_rise
    compi.falling(&ambi_fall);                        // Set comparator falling int callback to ambi_fall
    compi.treshold(ambi.lux_pct(300.0));              // Set ISR treshold to 300lux
    compi.int_en(1);                                  // Enable comparator interrupt

    cmpled = 1;
    
    while (1)
    {
        printf("%7.2f lux\n",ambi.read());
        wait(0.5);
        blinky = !blinky;
    }
}

// Comparator callback
void ambi_rise(void)
{
    cmpled = 0;                       // Green led on.
}

void ambi_fall(void)
{
    cmpled = 1;                       // Green led off.
}

Files at this revision

API Documentation at this revision

Comitter:
frankvnk
Date:
Sun Aug 25 09:07:40 2013 +0000
Parent:
3:55136b956b17
Commit message:
Added function to read raw sensor data.

Changed in this revision

TEMT6200.cpp Show annotated file Show diff for this revision Revisions of this file
TEMT6200.h Show annotated file Show diff for this revision Revisions of this file
diff -r 55136b956b17 -r 5d1118cb5702 TEMT6200.cpp
--- a/TEMT6200.cpp	Sun Jun 16 19:48:41 2013 +0000
+++ b/TEMT6200.cpp	Sun Aug 25 09:07:40 2013 +0000
@@ -15,6 +15,11 @@
     Ipce100 = TEMT_IAVG;
 }
  
+unsigned short TEMT6200::readRaw(void)
+{
+    return(_level.read_u16());
+}
+
 float TEMT6200::read(void)
 {
     return(100 * (_level.read() * TEMT_AREF) / (TEMT_AMP * Ipce100));
@@ -69,3 +74,4 @@
 }
 
 
+
diff -r 55136b956b17 -r 5d1118cb5702 TEMT6200.h
--- a/TEMT6200.h	Sun Jun 16 19:48:41 2013 +0000
+++ b/TEMT6200.h	Sun Aug 25 09:07:40 2013 +0000
@@ -20,7 +20,7 @@
 #define TEMT_IAVG          (float)0.02325       // Theoretical average Ipce @ 100lux
 #define TEMT_DARKC         (float)0.000050      // Max. dark current
  
-/** Class to use TEMT6200 ambient light sensor
+/** Class to use TEMT6200 ambient light sensor.
 *
 * 'en' pin can be any digital pin.
 * 'level' pin MUST be an analog input
@@ -28,7 +28,7 @@
 
 class TEMT6200 {
 public:
-    /** Create a TEMT6200 object connected to 2 pins
+    /** Create a TEMT6200 object connected to 2 pins.
     *
     * @param en = Power on/off output
     * @param level = TEMT6200 analog level input
@@ -36,20 +36,26 @@
     */
     TEMT6200(PinName en, PinName level);
 
-    /** Read TEMT6200 level (lux)
+    /** Read TEMT6200 level (raw value).
+    * @param none
+    * @return unsigned short in the range [0x0, 0xFFFF].
+    */
+    unsigned short readRaw(void);
+
+    /** Read TEMT6200 level (lux).
     * @param none
     * @return lux value (float)
     */
     float read(void);
 
-    /** Power control
+    /** Power control.
     * @param AMB_ON  = enable light sensor
     * @param AMB_OFF = disable light sensor
     * @return none
     */
     void pwr(bool pwr);
 
-    /** Calibrate the ambient light sensor
+    /** Calibrate the ambient light sensor.
     * @param none
     * @return none
     * @return . IMPORTANT : Totally obscure the sensor before calibration.
@@ -58,7 +64,7 @@
     */
     void calibrate(void);
 
-    /** Convert lux value to percentile
+    /** Convert lux value to percentile.
     * @param input lux_val : lux value to be converted - range: 0..TEMT6200_MAXLX lux (float)
     * @return Value for setting ComparatorIn treshold (float)
     * @return . Conversion accuracy depends on the DAC input used with the comparator input: