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

Committer:
loopsva
Date:
Thu Apr 21 23:46:53 2016 +0000
Revision:
0:92cb496cbbe1
Child:
2:c17b84879a2f
Separate from BME280 library - an mbed oddity...

Who changed what in which revision?

UserRevisionLine numberNew contents of line
loopsva 0:92cb496cbbe1 1 // Vishay veml6040 RGBW and veml6075 UVA + UVB optical sensors
loopsva 0:92cb496cbbe1 2
loopsva 0:92cb496cbbe1 3 #include "veml60xx.h"
loopsva 0:92cb496cbbe1 4
loopsva 0:92cb496cbbe1 5 //--------------------------------------------------------------------------------------------------------------------------------------//
loopsva 0:92cb496cbbe1 6 // Constructor, to allow for user to select i2c frequency
loopsva 0:92cb496cbbe1 7
loopsva 0:92cb496cbbe1 8 veml60xx::veml60xx(PinName sda, PinName scl, int i2cFrequency) {
loopsva 0:92cb496cbbe1 9 _i2c_ = new I2C(sda, scl);
loopsva 0:92cb496cbbe1 10 _i2c_->frequency(i2cFrequency);
loopsva 0:92cb496cbbe1 11 }
loopsva 0:92cb496cbbe1 12
loopsva 0:92cb496cbbe1 13 //--------------------------------------------------------------------------------------------------------------------------------------//
loopsva 0:92cb496cbbe1 14 // deconstructor
loopsva 0:92cb496cbbe1 15
loopsva 0:92cb496cbbe1 16 veml60xx::~veml60xx() {
loopsva 0:92cb496cbbe1 17 }
loopsva 0:92cb496cbbe1 18
loopsva 0:92cb496cbbe1 19 //--------------------------------------------------------------------------------------------------------------------------------------//
loopsva 0:92cb496cbbe1 20 // Set/initialize the veml60xx config register.
loopsva 0:92cb496cbbe1 21
loopsva 0:92cb496cbbe1 22 void veml60xx::setConfig(veml60xx_struct& Pntr, uint16_t val) {
loopsva 0:92cb496cbbe1 23 vemlBuffer[0] = VEML60xx_CONF_REG;
loopsva 0:92cb496cbbe1 24 vemlBuffer[1] = val;
loopsva 0:92cb496cbbe1 25 //vemlBuffer[1] = VEML60xx_CONF_BITS_IT_400m320m | val;
loopsva 0:92cb496cbbe1 26 //vemlBuffer[1] = VEML60xx_CONF_BITS_IT_400m320m | VEML6075_CONF_BITS_HD;
loopsva 0:92cb496cbbe1 27 //vemlBuffer[1] = VEML60xx_CONF_BITS_IT_400m320m | VEML6075_CONF_BITS_HD | VEML60xx_CONF_BITS_AF;
loopsva 0:92cb496cbbe1 28 vemlBuffer[2] = 0;
loopsva 0:92cb496cbbe1 29 _i2c_->write(VEML60_WADDR, vemlBuffer, 3, false);
loopsva 0:92cb496cbbe1 30 Pntr.conf_reg = (vemlBuffer[2] << 8) | vemlBuffer[1];
loopsva 0:92cb496cbbe1 31 }
loopsva 0:92cb496cbbe1 32
loopsva 0:92cb496cbbe1 33 //--------------------------------------------------------------------------------------------------------------------------------------//
loopsva 0:92cb496cbbe1 34 // Get veml60xx ID register. Returns register value
loopsva 0:92cb496cbbe1 35 // Note: the veml6040 does hvae a device ID, but is not in datasheet
loopsva 0:92cb496cbbe1 36
loopsva 0:92cb496cbbe1 37 uint16_t veml60xx::getID(veml60xx_struct& Pntr) {
loopsva 0:92cb496cbbe1 38 vemlBuffer[0] = VEML6075_CHIP_ID_REG;
loopsva 0:92cb496cbbe1 39 _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
loopsva 0:92cb496cbbe1 40 _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
loopsva 0:92cb496cbbe1 41 uint16_t rdata = (vemlBuffer[1] << 8) | vemlBuffer[0];
loopsva 0:92cb496cbbe1 42 if((rdata & VEML6075_DEVICE_ID) == VEML6075_DEVICE_ID) {
loopsva 0:92cb496cbbe1 43 Pntr.is6075 = true;
loopsva 0:92cb496cbbe1 44 Pntr.is6040 = false;
loopsva 0:92cb496cbbe1 45 } else
loopsva 0:92cb496cbbe1 46 if((rdata & VEML6040_DEVICE_ID) == VEML6040_DEVICE_ID) {
loopsva 0:92cb496cbbe1 47 Pntr.is6075 = false;
loopsva 0:92cb496cbbe1 48 Pntr.is6040 = true;
loopsva 0:92cb496cbbe1 49 } else {
loopsva 0:92cb496cbbe1 50 Pntr.is6075 = false;
loopsva 0:92cb496cbbe1 51 Pntr.is6040 = false;
loopsva 0:92cb496cbbe1 52 }
loopsva 0:92cb496cbbe1 53 return(rdata);
loopsva 0:92cb496cbbe1 54 }
loopsva 0:92cb496cbbe1 55
loopsva 0:92cb496cbbe1 56 //--------------------------------------------------------------------------------------------------------------------------------------//
loopsva 0:92cb496cbbe1 57 // Get veml60xx config register. Returns register value
loopsva 0:92cb496cbbe1 58
loopsva 0:92cb496cbbe1 59 uint16_t veml60xx::getConfig(veml60xx_struct& Pntr) {
loopsva 0:92cb496cbbe1 60 vemlBuffer[0] = VEML60xx_CONF_REG;
loopsva 0:92cb496cbbe1 61 _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
loopsva 0:92cb496cbbe1 62 _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
loopsva 0:92cb496cbbe1 63 uint16_t rdata = (vemlBuffer[1] << 8) | vemlBuffer[0];
loopsva 0:92cb496cbbe1 64 if(Pntr.is6040) {
loopsva 0:92cb496cbbe1 65 uint16_t c = rdata & VEML60xx_CONF_BITS_IT;
loopsva 0:92cb496cbbe1 66 switch (c) {
loopsva 0:92cb496cbbe1 67 case VEML60xx_CONF_BITS_IT_50m40m:
loopsva 0:92cb496cbbe1 68 Pntr.lux_step = VEML6040_LUX_STEP_000;
loopsva 0:92cb496cbbe1 69 break;
loopsva 0:92cb496cbbe1 70 case VEML60xx_CONF_BITS_IT_100m80m:
loopsva 0:92cb496cbbe1 71 Pntr.lux_step = VEML6040_LUX_STEP_001;
loopsva 0:92cb496cbbe1 72 break;
loopsva 0:92cb496cbbe1 73 case VEML60xx_CONF_BITS_IT_200m160m:
loopsva 0:92cb496cbbe1 74 Pntr.lux_step = VEML6040_LUX_STEP_010;
loopsva 0:92cb496cbbe1 75 break;
loopsva 0:92cb496cbbe1 76 case VEML60xx_CONF_BITS_IT_400m320m:
loopsva 0:92cb496cbbe1 77 Pntr.lux_step = VEML6040_LUX_STEP_011;
loopsva 0:92cb496cbbe1 78 break;
loopsva 0:92cb496cbbe1 79 case VEML60xx_CONF_BITS_IT_800m640m:
loopsva 0:92cb496cbbe1 80 Pntr.lux_step = VEML6040_LUX_STEP_100;
loopsva 0:92cb496cbbe1 81 break;
loopsva 0:92cb496cbbe1 82 case VEML6040_CONF_BITS_IT_1280m:
loopsva 0:92cb496cbbe1 83 Pntr.lux_step = VEML6040_LUX_STEP_101;
loopsva 0:92cb496cbbe1 84 break;
loopsva 0:92cb496cbbe1 85 default:
loopsva 0:92cb496cbbe1 86 Pntr.lux_step = 0.0;
loopsva 0:92cb496cbbe1 87 break;
loopsva 0:92cb496cbbe1 88 }
loopsva 0:92cb496cbbe1 89 }
loopsva 0:92cb496cbbe1 90 return(rdata);
loopsva 0:92cb496cbbe1 91 }
loopsva 0:92cb496cbbe1 92
loopsva 0:92cb496cbbe1 93 //--------------------------------------------------------------------------------------------------------------------------------------//
loopsva 0:92cb496cbbe1 94 // If AF set to trigger mode, start a conversion process trigger
loopsva 0:92cb496cbbe1 95 // Returns: 0=trigger set, 1=already triggered, 2=no AF bit - cannot set trigger
loopsva 0:92cb496cbbe1 96
loopsva 0:92cb496cbbe1 97 uint16_t veml60xx::startAccess(veml60xx_struct& Pntr) {
loopsva 0:92cb496cbbe1 98 uint16_t val = getConfig(Pntr);
loopsva 0:92cb496cbbe1 99 if((val & VEML60xx_CONF_BITS_AF) == VEML60xx_CONF_BITS_AF) {
loopsva 0:92cb496cbbe1 100 if((val & VEML60xx_CONF_BITS_TRIG) == VEML60xx_CONF_BITS_TRIG) return(1);
loopsva 0:92cb496cbbe1 101 val |= VEML60xx_CONF_BITS_TRIG;
loopsva 0:92cb496cbbe1 102 setConfig(Pntr, val);
loopsva 0:92cb496cbbe1 103 return(0);
loopsva 0:92cb496cbbe1 104 }
loopsva 0:92cb496cbbe1 105 return(2);
loopsva 0:92cb496cbbe1 106 }
loopsva 0:92cb496cbbe1 107
loopsva 0:92cb496cbbe1 108 //--------------------------------------------------------------------------------------------------------------------------------------//
loopsva 0:92cb496cbbe1 109 // Get VEML60xx values. Saves raw data is data structure. Returns 0 if successful, !0 if status is (something else);
loopsva 0:92cb496cbbe1 110 // mode: false = VEML6075, true = VEML6040
loopsva 0:92cb496cbbe1 111
loopsva 0:92cb496cbbe1 112 uint16_t veml60xx::getRawData(veml60xx_struct& Pntr) {
loopsva 0:92cb496cbbe1 113 Pntr.conf_reg = getConfig(Pntr);
loopsva 0:92cb496cbbe1 114 Pntr.id = getID(Pntr);
loopsva 0:92cb496cbbe1 115
loopsva 0:92cb496cbbe1 116 if(Pntr.is6075) {
loopsva 0:92cb496cbbe1 117 vemlBuffer[0] = VEML6075_UVA_DATA_REG;
loopsva 0:92cb496cbbe1 118 _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
loopsva 0:92cb496cbbe1 119 _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
loopsva 0:92cb496cbbe1 120 Pntr.uva_d = ((vemlBuffer[1] << 8) | vemlBuffer[0]);
loopsva 0:92cb496cbbe1 121 }
loopsva 0:92cb496cbbe1 122
loopsva 0:92cb496cbbe1 123 vemlBuffer[0] = VEML6075_DUMMY_REG;
loopsva 0:92cb496cbbe1 124 _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
loopsva 0:92cb496cbbe1 125 _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
loopsva 0:92cb496cbbe1 126 if(Pntr.is6075) {
loopsva 0:92cb496cbbe1 127 Pntr.dummy_d = ((vemlBuffer[1] << 8) | vemlBuffer[0]);
loopsva 0:92cb496cbbe1 128 } else
loopsva 0:92cb496cbbe1 129 if(Pntr.is6040) {
loopsva 0:92cb496cbbe1 130 Pntr.r_d = ((vemlBuffer[1] << 8) | vemlBuffer[0]);
loopsva 0:92cb496cbbe1 131 }
loopsva 0:92cb496cbbe1 132
loopsva 0:92cb496cbbe1 133 vemlBuffer[0] = VEML6075_UVB_DATA_REG;
loopsva 0:92cb496cbbe1 134 _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
loopsva 0:92cb496cbbe1 135 _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
loopsva 0:92cb496cbbe1 136 if(Pntr.is6075) {
loopsva 0:92cb496cbbe1 137 Pntr.uvb_d = ((vemlBuffer[1] << 8) | vemlBuffer[0]);
loopsva 0:92cb496cbbe1 138 } else
loopsva 0:92cb496cbbe1 139 if(Pntr.is6040) {
loopsva 0:92cb496cbbe1 140 Pntr.g_d = ((vemlBuffer[1] << 8) | vemlBuffer[0]);
loopsva 0:92cb496cbbe1 141 }
loopsva 0:92cb496cbbe1 142
loopsva 0:92cb496cbbe1 143 vemlBuffer[0] = VEML6075_UV_COMP1_REG;
loopsva 0:92cb496cbbe1 144 _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
loopsva 0:92cb496cbbe1 145 _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
loopsva 0:92cb496cbbe1 146 if(Pntr.is6075) {
loopsva 0:92cb496cbbe1 147 Pntr.uv_c1 = ((vemlBuffer[1] << 8) | vemlBuffer[0]);
loopsva 0:92cb496cbbe1 148 } else
loopsva 0:92cb496cbbe1 149 if(Pntr.is6040) {
loopsva 0:92cb496cbbe1 150 Pntr.b_d = ((vemlBuffer[1] << 8) | vemlBuffer[0]);
loopsva 0:92cb496cbbe1 151 }
loopsva 0:92cb496cbbe1 152
loopsva 0:92cb496cbbe1 153 vemlBuffer[0] = VEML6075_UV_COMP2_REG;
loopsva 0:92cb496cbbe1 154 _i2c_->write(VEML60_WADDR, vemlBuffer, 1, true);
loopsva 0:92cb496cbbe1 155 _i2c_->read(VEML60_RADDR, vemlBuffer, 2, false);
loopsva 0:92cb496cbbe1 156 if(Pntr.is6075) {
loopsva 0:92cb496cbbe1 157 Pntr.uv_c1 = ((vemlBuffer[1] << 8) | vemlBuffer[0]);
loopsva 0:92cb496cbbe1 158 } else
loopsva 0:92cb496cbbe1 159 if(Pntr.is6040) {
loopsva 0:92cb496cbbe1 160 Pntr.w_d = ((vemlBuffer[1] << 8) | vemlBuffer[0]);
loopsva 0:92cb496cbbe1 161 }
loopsva 0:92cb496cbbe1 162
loopsva 0:92cb496cbbe1 163 return(0);
loopsva 0:92cb496cbbe1 164 }
loopsva 0:92cb496cbbe1 165
loopsva 0:92cb496cbbe1 166 //--------------------------------------------------------------------------------------------------------------------------------------//
loopsva 0:92cb496cbbe1 167 // Convert raw data into real UVA, UVB and UVI numbers
loopsva 0:92cb496cbbe1 168
loopsva 0:92cb496cbbe1 169 void veml60xx::convertRawData(veml60xx_struct& Pntr) {
loopsva 0:92cb496cbbe1 170 getRawData(Pntr);
loopsva 0:92cb496cbbe1 171
loopsva 0:92cb496cbbe1 172 //Eq (1)
loopsva 0:92cb496cbbe1 173 Pntr.uva_comp = (double)(Pntr.uva_d - Pntr.dummy_d) -
loopsva 0:92cb496cbbe1 174 VEML6075_UVA_COEF_A * (double)(Pntr.uv_c1 - Pntr.dummy_d) -
loopsva 0:92cb496cbbe1 175 VEML6075_UVA_COEF_B * (double)(Pntr.uv_c2 - Pntr.dummy_d);
loopsva 0:92cb496cbbe1 176
loopsva 0:92cb496cbbe1 177 //Eq (2)
loopsva 0:92cb496cbbe1 178 Pntr.uvb_comp = (double)(Pntr.uvb_d - Pntr.dummy_d) -
loopsva 0:92cb496cbbe1 179 VEML6075_UVB_COEF_C * (double)(Pntr.uv_c1 - Pntr.dummy_d) -
loopsva 0:92cb496cbbe1 180 VEML6075_UVB_COEF_D * (double)(Pntr.uv_c2 - Pntr.dummy_d);
loopsva 0:92cb496cbbe1 181 //Eq (3)
loopsva 0:92cb496cbbe1 182 Pntr.uv_index = ((Pntr.uva_comp * VEML6075_UVA_RESP) + (Pntr.uvb_comp * VEML6075_UVB_RESP))/2.0;
loopsva 0:92cb496cbbe1 183 }
loopsva 0:92cb496cbbe1 184
loopsva 0:92cb496cbbe1 185
loopsva 0:92cb496cbbe1 186 //--------------------------------------------------------------------------------------------------------------------------------------//
loopsva 0:92cb496cbbe1 187 // If there is a lux over/underflow, automatically adjust the CONF_BITS_IT by +-1 to compensate accordingly
loopsva 0:92cb496cbbe1 188 // if returns true, the Lux level was changed.
loopsva 0:92cb496cbbe1 189
loopsva 0:92cb496cbbe1 190 bool veml60xx::autoAdjustLux(veml60xx_struct& Pntr) {
loopsva 0:92cb496cbbe1 191 getRawData(Pntr);
loopsva 0:92cb496cbbe1 192 uint16_t rdata = Pntr.conf_reg;
loopsva 0:92cb496cbbe1 193 uint16_t lux = rdata & VEML60xx_CONF_BITS_IT;
loopsva 0:92cb496cbbe1 194 if(Pntr.is6040) {
loopsva 0:92cb496cbbe1 195 if((Pntr.r_d < 255) && (Pntr.g_d < 255) && (Pntr.b_d < 255) && (Pntr.w_d < 255)) {
loopsva 0:92cb496cbbe1 196 if(lux == VEML6040_CONF_BITS_IT_1280m) return false;
loopsva 0:92cb496cbbe1 197 lux += VEML60xx_CONF_BITS_IT_100m80m;
loopsva 0:92cb496cbbe1 198 rdata = (rdata & ~VEML60xx_CONF_BITS_IT) | lux;
loopsva 0:92cb496cbbe1 199 setConfig(Pntr, rdata);
loopsva 0:92cb496cbbe1 200 return true;
loopsva 0:92cb496cbbe1 201 } else
loopsva 0:92cb496cbbe1 202 if((Pntr.r_d == 65535) || (Pntr.g_d == 65535) || (Pntr.b_d == 65535) || (Pntr.w_d == 65535)) {
loopsva 0:92cb496cbbe1 203 if(lux == VEML60xx_CONF_BITS_IT_50m40m) return false;
loopsva 0:92cb496cbbe1 204 lux -= VEML60xx_CONF_BITS_IT_100m80m;
loopsva 0:92cb496cbbe1 205 rdata = (rdata & ~VEML60xx_CONF_BITS_IT) | lux;
loopsva 0:92cb496cbbe1 206 setConfig(Pntr, rdata);
loopsva 0:92cb496cbbe1 207 return true;
loopsva 0:92cb496cbbe1 208 }
loopsva 0:92cb496cbbe1 209 } else
loopsva 0:92cb496cbbe1 210 if(Pntr.is6075) {
loopsva 0:92cb496cbbe1 211 if((Pntr.uva_d < 255) && (Pntr.uvb_d < 255)) {
loopsva 0:92cb496cbbe1 212 if(lux == VEML60xx_CONF_BITS_IT_800m640m) return false;
loopsva 0:92cb496cbbe1 213 lux += VEML60xx_CONF_BITS_IT_100m80m;
loopsva 0:92cb496cbbe1 214 rdata = (rdata & ~VEML60xx_CONF_BITS_IT) | lux;
loopsva 0:92cb496cbbe1 215 setConfig(Pntr, rdata);
loopsva 0:92cb496cbbe1 216 return true;
loopsva 0:92cb496cbbe1 217 } else
loopsva 0:92cb496cbbe1 218 if((Pntr.uva_d == 65535) || (Pntr.uvb_d == 65535)) {
loopsva 0:92cb496cbbe1 219 if(lux == VEML60xx_CONF_BITS_IT_50m40m) return false;
loopsva 0:92cb496cbbe1 220 lux -= VEML60xx_CONF_BITS_IT_100m80m;
loopsva 0:92cb496cbbe1 221 rdata = (rdata & ~VEML60xx_CONF_BITS_IT) | lux;
loopsva 0:92cb496cbbe1 222 setConfig(Pntr, rdata);
loopsva 0:92cb496cbbe1 223 return true;
loopsva 0:92cb496cbbe1 224 }
loopsva 0:92cb496cbbe1 225 }
loopsva 0:92cb496cbbe1 226 return false;
loopsva 0:92cb496cbbe1 227 }
loopsva 0:92cb496cbbe1 228
loopsva 0:92cb496cbbe1 229