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:
0:92cb496cbbe1
Child:
2:c17b84879a2f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/veml60xx.cpp	Thu Apr 21 23:46:53 2016 +0000
@@ -0,0 +1,229 @@
+// Vishay veml6040 RGBW and veml6075 UVA + UVB optical sensors
+
+#include "veml60xx.h"
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+// Constructor, to allow for user to select i2c frequency
+
+veml60xx::veml60xx(PinName sda, PinName scl,  int i2cFrequency) {
+    _i2c_ = new I2C(sda, scl);
+    _i2c_->frequency(i2cFrequency);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+// deconstructor
+
+veml60xx::~veml60xx() {
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+// Set/initialize the veml60xx config register.
+
+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];
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+// Get veml60xx ID register.  Returns register value
+// Note: the veml6040 does hvae 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.is6075 = true;
+        Pntr.is6040 = false;
+    } else
+    if((rdata & VEML6040_DEVICE_ID) == VEML6040_DEVICE_ID) {
+        Pntr.is6075 = false;
+        Pntr.is6040 = true;
+    } else {
+        Pntr.is6075 = false;
+        Pntr.is6040 = false;
+    }
+    return(rdata);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+// Get veml60xx config register.  Returns register value
+
+uint16_t veml60xx::getConfig(veml60xx_struct& Pntr) {
+    vemlBuffer[0] = VEML60xx_CONF_REG;
+    _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
+    _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
+    uint16_t rdata = (vemlBuffer[1] << 8)  | vemlBuffer[0];
+    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;
+                break;
+            case VEML60xx_CONF_BITS_IT_100m80m:
+                Pntr.lux_step = VEML6040_LUX_STEP_001;
+                break;
+            case VEML60xx_CONF_BITS_IT_200m160m:
+                Pntr.lux_step = VEML6040_LUX_STEP_010;
+                break;
+            case VEML60xx_CONF_BITS_IT_400m320m:
+                Pntr.lux_step = VEML6040_LUX_STEP_011;
+                break;
+            case VEML60xx_CONF_BITS_IT_800m640m:
+                Pntr.lux_step = VEML6040_LUX_STEP_100;
+                break;
+            case VEML6040_CONF_BITS_IT_1280m:
+                Pntr.lux_step = VEML6040_LUX_STEP_101;
+                break;
+            default:
+                Pntr.lux_step = 0.0;
+                break;
+        }
+    }
+    return(rdata);
+}    
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+// If AF set to trigger mode, start a conversion process trigger
+// Returns: 0=trigger set, 1=already triggered,  2=no AF bit - cannot set trigger
+
+uint16_t veml60xx::startAccess(veml60xx_struct& Pntr) {
+    uint16_t val = getConfig(Pntr);
+    if((val & VEML60xx_CONF_BITS_AF) == VEML60xx_CONF_BITS_AF) {
+        if((val & VEML60xx_CONF_BITS_TRIG) == VEML60xx_CONF_BITS_TRIG) return(1);
+        val |= VEML60xx_CONF_BITS_TRIG;
+        setConfig(Pntr, val);
+        return(0);
+    }
+    return(2);
+}       
+    
+//--------------------------------------------------------------------------------------------------------------------------------------//
+// Get VEML60xx values.  Saves raw data is data structure.  Returns 0 if successful, !0 if status is (something else);
+// mode: false = VEML6075, true = VEML6040
+
+uint16_t veml60xx::getRawData(veml60xx_struct& Pntr) {
+    Pntr.conf_reg = getConfig(Pntr);
+    Pntr.id = getID(Pntr);
+        
+    if(Pntr.is6075) {
+        vemlBuffer[0] = VEML6075_UVA_DATA_REG;
+        _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
+        _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
+        Pntr.uva_d = ((vemlBuffer[1] << 8)  | vemlBuffer[0]);
+    }
+    
+    vemlBuffer[0] = VEML6075_DUMMY_REG;
+    _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
+    _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
+    if(Pntr.is6075) {
+        Pntr.dummy_d = ((vemlBuffer[1] << 8)  | vemlBuffer[0]);
+    } else 
+    if(Pntr.is6040) {
+        Pntr.r_d = ((vemlBuffer[1] << 8)  | vemlBuffer[0]);
+    }
+    
+    vemlBuffer[0] = VEML6075_UVB_DATA_REG;
+    _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
+    _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
+    if(Pntr.is6075) {
+        Pntr.uvb_d = ((vemlBuffer[1] << 8)  | vemlBuffer[0]);
+    } else 
+    if(Pntr.is6040) {
+        Pntr.g_d = ((vemlBuffer[1] << 8)  | vemlBuffer[0]);
+    }
+       
+    vemlBuffer[0] = VEML6075_UV_COMP1_REG;
+    _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
+    _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
+    if(Pntr.is6075) {
+        Pntr.uv_c1 = ((vemlBuffer[1] << 8)  | vemlBuffer[0]);
+    } else 
+    if(Pntr.is6040) {
+        Pntr.b_d = ((vemlBuffer[1] << 8)  | vemlBuffer[0]);
+    }
+        
+    vemlBuffer[0] = VEML6075_UV_COMP2_REG;
+    _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
+    _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
+    if(Pntr.is6075) {
+        Pntr.uv_c1 = ((vemlBuffer[1] << 8)  | vemlBuffer[0]);
+    } else
+    if(Pntr.is6040) {
+        Pntr.w_d = ((vemlBuffer[1] << 8)  | vemlBuffer[0]);
+    }
+    
+    return(0);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+// 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);
+    
+    //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 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.
+
+bool veml60xx::autoAdjustLux(veml60xx_struct& Pntr) {
+    getRawData(Pntr);
+    uint16_t rdata = Pntr.conf_reg;
+    uint16_t lux = rdata & VEML60xx_CONF_BITS_IT;
+    if(Pntr.is6040) {
+        if((Pntr.r_d < 255) && (Pntr.g_d < 255) && (Pntr.b_d < 255) && (Pntr.w_d < 255)) {
+            if(lux == VEML6040_CONF_BITS_IT_1280m) return false;
+            lux += VEML60xx_CONF_BITS_IT_100m80m;
+            rdata = (rdata & ~VEML60xx_CONF_BITS_IT) | lux;
+            setConfig(Pntr, rdata);
+            return true;
+        } else 
+        if((Pntr.r_d == 65535) || (Pntr.g_d == 65535) || (Pntr.b_d == 65535) || (Pntr.w_d == 65535)) {
+            if(lux == VEML60xx_CONF_BITS_IT_50m40m) return false;
+            lux -= VEML60xx_CONF_BITS_IT_100m80m;
+            rdata = (rdata & ~VEML60xx_CONF_BITS_IT) | lux;
+            setConfig(Pntr, rdata);
+            return true;
+        }
+    } else
+    if(Pntr.is6075) {
+        if((Pntr.uva_d < 255) && (Pntr.uvb_d < 255)) {
+            if(lux == VEML60xx_CONF_BITS_IT_800m640m) return false;
+            lux += VEML60xx_CONF_BITS_IT_100m80m;
+            rdata = (rdata & ~VEML60xx_CONF_BITS_IT) | lux;
+            setConfig(Pntr, rdata);
+            return true;
+        } else 
+        if((Pntr.uva_d == 65535) || (Pntr.uvb_d == 65535)) {
+            if(lux == VEML60xx_CONF_BITS_IT_50m40m) return false;
+            lux -= VEML60xx_CONF_BITS_IT_100m80m;
+            rdata = (rdata & ~VEML60xx_CONF_BITS_IT) | lux;
+            setConfig(Pntr, rdata);
+            return true;
+        }
+    }
+    return false;
+}
+            
+    
\ No newline at end of file