A Vishay library for devices VEML6040 R+G+B+W and VEML6075 UVA+UVB optical sensors. Data is stored in a dedicated data structure.

Dependents:   vmel60xx_hello_world

This device library is for use with the Vishay VEML6040 and VEML6075 optical sensors. Ambient light conditions are gathered and stored in a user accessible data structure veml60xx_struct. The library has enough intelligence to determine which device is connected and performs the appropriate functions.

The VEML6040 detects Red, Green, Blue and White light data, which is easily converted to relative Lux intensities.

The VEML6075 detects UVA and UVB light which is converted to a UV Index value.

Since both devices use the same I2C address, they cannot be on the same I2C bus at the same time.

Tested on a K64F

Revision:
2:c17b84879a2f
Parent:
0:92cb496cbbe1
Child:
3:dda770fa7228
--- a/veml60xx.cpp	Fri Apr 22 18:23:07 2016 +0000
+++ b/veml60xx.cpp	Mon Apr 25 22:35:08 2016 +0000
@@ -1,4 +1,4 @@
-// Vishay veml6040 RGBW and veml6075 UVA + UVB optical sensors
+// Vishay veml6040 R+G+B+W and veml6075 UVA+UVB optical sensors
 
 #include "veml60xx.h"
 
@@ -22,9 +22,6 @@
 void veml60xx::setConfig(veml60xx_struct& Pntr, uint16_t val) {
     vemlBuffer[0] = VEML60xx_CONF_REG;
     vemlBuffer[1] = val;
-    //vemlBuffer[1] = VEML60xx_CONF_BITS_IT_400m320m | val;
-    //vemlBuffer[1] = VEML60xx_CONF_BITS_IT_400m320m | VEML6075_CONF_BITS_HD;
-    //vemlBuffer[1] = VEML60xx_CONF_BITS_IT_400m320m | VEML6075_CONF_BITS_HD | VEML60xx_CONF_BITS_AF;
     vemlBuffer[2] = 0;
     _i2c_->write(VEML60_WADDR, vemlBuffer, 3, false);
     Pntr.conf_reg = (vemlBuffer[2] << 8)  | vemlBuffer[1];
@@ -32,25 +29,26 @@
 
 //--------------------------------------------------------------------------------------------------------------------------------------//
 // Get veml60xx ID register.  Returns register value
-// Note: the veml6040 does hvae a device ID, but is not in datasheet
+// Note: the veml6040 does have a device ID, but is not in datasheet
 
 uint16_t veml60xx::getID(veml60xx_struct& Pntr) {
     vemlBuffer[0] = VEML6075_CHIP_ID_REG;
     _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
     _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
-    uint16_t rdata = (vemlBuffer[1] << 8)  | vemlBuffer[0];
-    if((rdata & VEML6075_DEVICE_ID) == VEML6075_DEVICE_ID) {
+    Pntr.id = (vemlBuffer[1] << 8)  | vemlBuffer[0];
+
+    if((Pntr.id & VEML6075_DEVICE_ID) == VEML6075_DEVICE_ID) {
         Pntr.is6075 = true;
         Pntr.is6040 = false;
     } else
-    if((rdata & VEML6040_DEVICE_ID) == VEML6040_DEVICE_ID) {
+    if((Pntr.id & VEML6040_DEVICE_ID) == VEML6040_DEVICE_ID) {
         Pntr.is6075 = false;
         Pntr.is6040 = true;
     } else {
         Pntr.is6075 = false;
         Pntr.is6040 = false;
     }
-    return(rdata);
+    return(Pntr.id);
 }
 
 //--------------------------------------------------------------------------------------------------------------------------------------//
@@ -61,32 +59,61 @@
     _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
     _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
     uint16_t rdata = (vemlBuffer[1] << 8)  | vemlBuffer[0];
+    Pntr.conf_reg = rdata;
+    uint16_t c = rdata & VEML60xx_CONF_BITS_IT;
     if(Pntr.is6040) {
-        uint16_t c = rdata & VEML60xx_CONF_BITS_IT;
         switch (c) {
             case VEML60xx_CONF_BITS_IT_50m40m: 
-                Pntr.lux_step = VEML6040_LUX_STEP_000;
+                Pntr.lux_step = VEML6040_LUX_STEP * 32.0;
                 break;
             case VEML60xx_CONF_BITS_IT_100m80m:
-                Pntr.lux_step = VEML6040_LUX_STEP_001;
+                Pntr.lux_step = VEML6040_LUX_STEP * 16.0;
                 break;
             case VEML60xx_CONF_BITS_IT_200m160m:
-                Pntr.lux_step = VEML6040_LUX_STEP_010;
+                Pntr.lux_step = VEML6040_LUX_STEP * 8.0;
                 break;
             case VEML60xx_CONF_BITS_IT_400m320m:
-                Pntr.lux_step = VEML6040_LUX_STEP_011;
+                Pntr.lux_step = VEML6040_LUX_STEP * 4.0;
                 break;
             case VEML60xx_CONF_BITS_IT_800m640m:
-                Pntr.lux_step = VEML6040_LUX_STEP_100;
+                Pntr.lux_step = VEML6040_LUX_STEP * 2.0;
                 break;
             case VEML6040_CONF_BITS_IT_1280m:
-                Pntr.lux_step = VEML6040_LUX_STEP_101;
+                Pntr.lux_step = VEML6040_LUX_STEP * 1.0;
                 break;
             default:
                 Pntr.lux_step = 0.0;
                 break;
         }
     }
+    if(Pntr.is6075) {
+        switch (c) {
+            case VEML60xx_CONF_BITS_IT_50m40m: 
+                Pntr.uva_step = VEML6075_UVA_RESP * 16.0;
+                Pntr.uvb_step = VEML6075_UVB_RESP * 16.0;
+                break;
+            case VEML60xx_CONF_BITS_IT_100m80m:
+                Pntr.uva_step = VEML6075_UVA_RESP * 8.0;
+                Pntr.uvb_step = VEML6075_UVB_RESP * 8.0;
+                break;
+            case VEML60xx_CONF_BITS_IT_200m160m:
+                Pntr.uva_step = VEML6075_UVA_RESP * 4.0;
+                Pntr.uvb_step = VEML6075_UVB_RESP * 4.0;
+                break;
+            case VEML60xx_CONF_BITS_IT_400m320m:
+                Pntr.uva_step = VEML6075_UVA_RESP * 2.0;
+                Pntr.uvb_step = VEML6075_UVB_RESP * 2.0;
+                break;
+            case VEML60xx_CONF_BITS_IT_800m640m:
+                Pntr.uva_step = VEML6075_UVA_RESP * 1.0;
+                Pntr.uvb_step = VEML6075_UVB_RESP * 1.0;
+                break;
+            default:
+                Pntr.uva_step = 0.0;
+                Pntr.uvb_step = 0.0;
+                break;
+        }
+    }
     return(rdata);
 }    
 
@@ -167,25 +194,36 @@
 // Convert raw data into real UVA, UVB and UVI numbers
 
 void veml60xx::convertRawData(veml60xx_struct& Pntr) {
-    getRawData(Pntr);
-    
-    //Eq (1)
-    Pntr.uva_comp = (double)(Pntr.uva_d - Pntr.dummy_d) - 
-                    VEML6075_UVA_COEF_A * (double)(Pntr.uv_c1 - Pntr.dummy_d) - 
-                    VEML6075_UVA_COEF_B * (double)(Pntr.uv_c2 - Pntr.dummy_d);
+    if(Pntr.is6075) {
+        //Eq (1)
+        Pntr.uva_comp = (double)(Pntr.uva_d - Pntr.dummy_d) - 
+                        VEML6075_UVA_COEF_A * (double)(Pntr.uv_c1 - Pntr.dummy_d) - 
+                        VEML6075_UVA_COEF_B * (double)(Pntr.uv_c2 - Pntr.dummy_d);
+        
+        //Eq (2)
+        Pntr.uvb_comp = (double)(Pntr.uvb_d - Pntr.dummy_d) - 
+                        VEML6075_UVB_COEF_C * (double)(Pntr.uv_c1 - Pntr.dummy_d) - 
+                        VEML6075_UVB_COEF_D * (double)(Pntr.uv_c2 - Pntr.dummy_d);
+        //Eq (3)
+        Pntr.uv_index = ((Pntr.uva_comp * Pntr.uva_step) + (Pntr.uvb_comp * Pntr.uvb_step))/2.0;
+        
+        if(Pntr.uva_comp < 0.0) Pntr.uva_comp = 0.0;
+        if(Pntr.uvb_comp < 0.0) Pntr.uvb_comp = 0.0;
+        if(Pntr.uv_index < 0.0) Pntr.uv_index = 0.0;
+    }
     
-    //Eq (2)
-    Pntr.uvb_comp = (double)(Pntr.uvb_d - Pntr.dummy_d) - 
-                    VEML6075_UVB_COEF_C * (double)(Pntr.uv_c1 - Pntr.dummy_d) - 
-                    VEML6075_UVB_COEF_D * (double)(Pntr.uv_c2 - Pntr.dummy_d);
-    //Eq (3)
-    Pntr.uv_index = ((Pntr.uva_comp * VEML6075_UVA_RESP) + (Pntr.uvb_comp * VEML6075_UVB_RESP))/2.0;
+    if(Pntr.is6040) {
+        Pntr.r_lux = (double)Pntr.r_d * Pntr.lux_step;
+        Pntr.g_lux = (double)Pntr.g_d * Pntr.lux_step;
+        Pntr.b_lux = (double)Pntr.b_d * Pntr.lux_step;
+        Pntr.w_lux = (double)Pntr.w_d * Pntr.lux_step;
+    }
 }
     
 
 //--------------------------------------------------------------------------------------------------------------------------------------//
 // If there is a lux over/underflow, automatically adjust the CONF_BITS_IT by +-1 to compensate accordingly
-// if returns true, the Lux level was changed.
+// if returns true, the Lux dwell time (IT bits in CONF reg) was changed.
 
 bool veml60xx::autoAdjustLux(veml60xx_struct& Pntr) {
     getRawData(Pntr);