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 Ipce | 4.6uA @ 20lux |
7.5 .. 39uA @ 100lux | |
average = (7.5 + 39)/2 = 23.25uA | |
Dark current | typical 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
BIN | min | max | avg | |
Group A | Ipce (uA) | 7.5 | 15 | 11.25 |
Group B | Ipce (uA) | 12 | 24 | 18 |
Group C | Ipce (uA) | 19.5 | 39 | 29.25 |
Schematic: Wi-Go KL25Z kit - TEMT6200 wiring
- 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.
lux | current (uA) |
100 | 23.25 |
1 | 0.2325 |
1000 | 232.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. }