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:
Fri Apr 29 16:40:06 2016 +0000
Revision:
4:0ce65ee5697f
Parent:
3:dda770fa7228
Added a delay variable in veml60xx_struct that is dependent on the IT bits and 6040 vs 6075
; Note: There is something screwy with the VEML6075 and FORCE mode, specially when dynamically changing the IT bits. It required much longer delays than...

Who changed what in which revision?

UserRevisionLine numberNew contents of line
loopsva 0:92cb496cbbe1 1 #ifndef VEML60XX_H
loopsva 0:92cb496cbbe1 2 #define VEML60XX_H
loopsva 0:92cb496cbbe1 3
loopsva 2:c17b84879a2f 4 /**
loopsva 2:c17b84879a2f 5 * Library for Vishay VEML6040 R+G+B+W and VEML6075 UVA+UVB optical sensors that operate on the I2C bus. There are
loopsva 2:c17b84879a2f 6 * routines for detecting which VEML device is connected to the I2C bus and sets the appropriate resigter values
loopsva 2:c17b84879a2f 7 * in the data structure "veml60xx_struct".
loopsva 2:c17b84879a2f 8 *
loopsva 2:c17b84879a2f 9 * The code has all of the hooks for gathering raw data from the VEML60xx chip and performs the necessary compensation
loopsva 2:c17b84879a2f 10 * in order to get the corrected output readings. There is also an optional automatic scaling routine that
loopsva 4:0ce65ee5697f 11 * modifies the integration time (IT bits in the CONF register), should the raw register reading saturate (65535) or
loopsva 2:c17b84879a2f 12 * are too small (< 255). Adjustments are made + or - one IT count, each time the routine is called. If the light
loopsva 2:c17b84879a2f 13 * striking the sensor changes dramatically, you may have to run the automatic scaling routine a few times. After
loopsva 4:0ce65ee5697f 14 * each change in integration time (changing of IT bits), you must wait a maximum of 2 * 1280mSec before taking a new
loopsva 2:c17b84879a2f 15 * reading in order to get accurate results.
loopsva 2:c17b84879a2f 16 *
loopsva 2:c17b84879a2f 17 * NOTE: Both the VEML6040 and the VEML6075 have the same I2C address. You cannot have both devices on the same I2C
loopsva 2:c17b84879a2f 18 * bus at the same time!! Vishay does have an application note for using multiple devices in the same I2C bus.
loopsva 2:c17b84879a2f 19 * However, it does require additional hardware to do so.
loopsva 2:c17b84879a2f 20 *
loopsva 2:c17b84879a2f 21 * NOTE: Although no device ID is noted in the VEML6040 datasheet, it apprears to have an ID of 0x0123. This code
loopsva 2:c17b84879a2f 22 * does look at the 0x0123 ID signature to determine that a VEML6040 has been detected and sets
loopsva 2:c17b84879a2f 23 * the "is6040" flag in the "veml60xx_struct" data structure.
loopsva 3:dda770fa7228 24 *
loopsva 3:dda770fa7228 25 * NOTE: It is not yet known when using startAccess(), whether or not that TRIG bit clear immediately or after the
loopsva 4:0ce65ee5697f 26 * integration time has finished. As a result, you should not depend on TRIG bit for polling.
loopsva 3:dda770fa7228 27 *
loopsva 2:c17b84879a2f 28 **/
loopsva 2:c17b84879a2f 29
loopsva 0:92cb496cbbe1 30 #include "mbed.h"
loopsva 0:92cb496cbbe1 31
loopsva 0:92cb496cbbe1 32 // I2C address
loopsva 0:92cb496cbbe1 33 #define VEML60_WADDR 0x20 //i2c address write mode
loopsva 0:92cb496cbbe1 34 #define VEML60_RADDR 0x21 //i2c address read mode
loopsva 0:92cb496cbbe1 35
loopsva 0:92cb496cbbe1 36
loopsva 1:f560bd61b3b3 37 // VEML6040 and VEML6075 common register set
loopsva 0:92cb496cbbe1 38 #define VEML60xx_CONF_REG 0x00 //rw Config Register
loopsva 0:92cb496cbbe1 39
loopsva 0:92cb496cbbe1 40 // VEML6075-only register set
loopsva 0:92cb496cbbe1 41 #define VEML6075_UVA_DATA_REG 0x07 //ro 16 bit UVA data Register
loopsva 0:92cb496cbbe1 42 #define VEML6075_DUMMY_REG 0x08 //ro 16 bit dummy Register
loopsva 0:92cb496cbbe1 43 #define VEML6075_UVB_DATA_REG 0x09 //ro 16 bit UVB data Register
loopsva 0:92cb496cbbe1 44 #define VEML6075_UV_COMP1_REG 0x0A //ro 16 bit UV compensation Register 1
loopsva 0:92cb496cbbe1 45 #define VEML6075_UV_COMP2_REG 0x0B //ro 16 bit UV compensation Register 2
loopsva 0:92cb496cbbe1 46 #define VEML6075_CHIP_ID_REG 0x0C //ro 16 bit Chip ID Register
loopsva 0:92cb496cbbe1 47
loopsva 0:92cb496cbbe1 48 // VEML6040-only register set
loopsva 0:92cb496cbbe1 49 #define VEML6040_R_DATA_REG 0x08 //ro 16 bit RED data
loopsva 0:92cb496cbbe1 50 #define VEML6040_G_DATA_REG 0x09 //ro 16 bit GREEN data
loopsva 0:92cb496cbbe1 51 #define VEML6040_B_DATA_REG 0x0A //ro 16 bit BLUE data
loopsva 0:92cb496cbbe1 52 #define VEML6040_W_DATA_REG 0x0B //ro 16 bit WHITE data
loopsva 0:92cb496cbbe1 53
loopsva 0:92cb496cbbe1 54 // VEML6040 and VEML6075 common config register bits
loopsva 0:92cb496cbbe1 55 #define VEML60xx_CONF_BITS_IT 0x70 //VEML6075 -> 0x00 = 50mS, 0x10 = 100mS, 0x20 = 200mS, 0x30 = 400mS, 0x40 = 800mS, 0x50-0x70 = reserved
loopsva 0:92cb496cbbe1 56 //VEML6040 -> 0x00 = 40mS, 0x10 = 80mS, 0x20 = 160mS, 0x30 = 320mS, 0x40 = 640mS, 0x50 = 1280mS, 0x60-0x70 = reserved
loopsva 0:92cb496cbbe1 57 #define VEML60xx_CONF_BITS_IT_50m40m 0x00
loopsva 0:92cb496cbbe1 58 #define VEML60xx_CONF_BITS_IT_100m80m 0x10
loopsva 0:92cb496cbbe1 59 #define VEML60xx_CONF_BITS_IT_200m160m 0x20
loopsva 0:92cb496cbbe1 60 #define VEML60xx_CONF_BITS_IT_400m320m 0x30
loopsva 0:92cb496cbbe1 61 #define VEML60xx_CONF_BITS_IT_800m640m 0x40
loopsva 0:92cb496cbbe1 62
loopsva 0:92cb496cbbe1 63 #define VEML60xx_CONF_BITS_TRIG 0x04 //0x00 = idle, 0x04 = trigger (measurement), auto returns to 0x00 note: AF == 1
loopsva 0:92cb496cbbe1 64 #define VEML60xx_CONF_BITS_AF 0x02 //0x00 = auto, 0x02 = force (mode)
loopsva 3:dda770fa7228 65 #define VEML60xx_CONF_BITS_SD 0x01 //0x00 = run, 0x01 = shut down
loopsva 0:92cb496cbbe1 66
loopsva 0:92cb496cbbe1 67 // VEML6075-only config register bits
loopsva 0:92cb496cbbe1 68 #define VEML6075_CONF_BITS_HD 0x08 //0x00 = normal, 0x08 = high (dynamic setting)
loopsva 0:92cb496cbbe1 69
loopsva 0:92cb496cbbe1 70 // VEML6040-only config register bits
loopsva 0:92cb496cbbe1 71 #define VEML6040_CONF_BITS_IT_1280m 0x50
loopsva 0:92cb496cbbe1 72
loopsva 0:92cb496cbbe1 73 // VEML6075-only ID contents
loopsva 0:92cb496cbbe1 74 #define VEML6075_DEVICE_ID 0x0026 //expected device ID
loopsva 0:92cb496cbbe1 75
loopsva 0:92cb496cbbe1 76 // VEML6040-only ID contents
loopsva 4:0ce65ee5697f 77 #define VEML6040_DEVICE_ID 0x0023 //expected device ID
loopsva 0:92cb496cbbe1 78
loopsva 0:92cb496cbbe1 79 // VEML6075-only conversion coefficients
loopsva 2:c17b84879a2f 80 #define VEML6075_UVA_RESP 0.0011
loopsva 2:c17b84879a2f 81 #define VEML6075_UVB_RESP 0.00125
loopsva 2:c17b84879a2f 82
loopsva 0:92cb496cbbe1 83 #define VEML6075_UVA_COEF_A 3.33
loopsva 0:92cb496cbbe1 84 #define VEML6075_UVA_COEF_B 2.50
loopsva 0:92cb496cbbe1 85 #define VEML6075_UVB_COEF_C 3.67
loopsva 0:92cb496cbbe1 86 #define VEML6075_UVB_COEF_D 2.75
loopsva 0:92cb496cbbe1 87
loopsva 0:92cb496cbbe1 88 // VEML6040-only conversion coefficients
loopsva 3:dda770fa7228 89 #define VEML6040_LUX_STEP 0.007865
loopsva 0:92cb496cbbe1 90
loopsva 0:92cb496cbbe1 91 /**
loopsva 0:92cb496cbbe1 92 * Create VEML60 controller class
loopsva 0:92cb496cbbe1 93 *
loopsva 0:92cb496cbbe1 94 * @param VEML class
loopsva 0:92cb496cbbe1 95 *
loopsva 0:92cb496cbbe1 96 */
loopsva 0:92cb496cbbe1 97 class veml60xx {
loopsva 0:92cb496cbbe1 98
loopsva 0:92cb496cbbe1 99 public:
loopsva 0:92cb496cbbe1 100
loopsva 0:92cb496cbbe1 101 /**
loopsva 0:92cb496cbbe1 102 * Public data structure for VEML60xx data values.
loopsva 0:92cb496cbbe1 103 *
loopsva 0:92cb496cbbe1 104 **/
loopsva 0:92cb496cbbe1 105 typedef struct {
loopsva 2:c17b84879a2f 106 uint16_t id; /*!< VEML60xx Device ID*/
loopsva 0:92cb496cbbe1 107 uint16_t conf_reg; /*!< VEML60xx config register mirror */
loopsva 4:0ce65ee5697f 108 int trig_dly; /*!< VEML60xx FORCE mode min trigger delay (mS) before resding data registers */
loopsva 2:c17b84879a2f 109
loopsva 2:c17b84879a2f 110 bool is6075; /*!< connected device is a VEML6075 */
loopsva 2:c17b84879a2f 111 bool is6040; /*!< connected device is a VEML6040 */
loopsva 0:92cb496cbbe1 112
loopsva 2:c17b84879a2f 113 uint16_t uva_d; /*!< VEML6075 UVA data */
loopsva 0:92cb496cbbe1 114 uint16_t uvb_d; /*!< VEML6075 UVB data */
loopsva 2:c17b84879a2f 115 uint16_t dummy_d; /*!< VEML6075 Dummy data */
loopsva 0:92cb496cbbe1 116 uint16_t uv_c1; /*!< VEML6075 UV comp1 data */
loopsva 0:92cb496cbbe1 117 uint16_t uv_c2; /*!< VEML6075 UV comp2 data */
loopsva 2:c17b84879a2f 118 double uva_step; /*!< VEML6075 UVA value per step */
loopsva 2:c17b84879a2f 119 double uvb_step; /*!< VEML6075 UVB value per step */
loopsva 0:92cb496cbbe1 120 double uva_comp; /*!< VEML6075 UVA compensated data */
loopsva 0:92cb496cbbe1 121 double uvb_comp; /*!< VEML6075 UVB compensated data */
loopsva 0:92cb496cbbe1 122 double uv_index; /*!< VEML6075 UV Index */
loopsva 2:c17b84879a2f 123
loopsva 2:c17b84879a2f 124 double lux_step; /*!< VEML6040 Lux value per step */
loopsva 0:92cb496cbbe1 125 uint16_t r_d; /*!< VEML6040 RED data */
loopsva 0:92cb496cbbe1 126 uint16_t g_d; /*!< VEML6040 GREEN data */
loopsva 0:92cb496cbbe1 127 uint16_t b_d; /*!< VEML6040 BLUE data */
loopsva 0:92cb496cbbe1 128 uint16_t w_d; /*!< VEML6040 WHITE data */
loopsva 2:c17b84879a2f 129 double r_lux; /*!< VEML6040 RED Lux value */
loopsva 2:c17b84879a2f 130 double g_lux; /*!< VEML6040 GREEN Lux value */
loopsva 2:c17b84879a2f 131 double b_lux; /*!< VEML6040 BLUE Lux value */
loopsva 2:c17b84879a2f 132 double w_lux; /*!< VEML6040 WHITE Lux value */
loopsva 2:c17b84879a2f 133
loopsva 0:92cb496cbbe1 134 } veml60xx_struct;
loopsva 0:92cb496cbbe1 135
loopsva 0:92cb496cbbe1 136 /**
loopsva 0:92cb496cbbe1 137 * Create a VME60xx object using the specified I2C object
loopsva 0:92cb496cbbe1 138 *
loopsva 0:92cb496cbbe1 139 * @param sda - mbed I2C interface pin
loopsva 0:92cb496cbbe1 140 *
loopsva 0:92cb496cbbe1 141 * @param scl - mbed I2C interface pin
loopsva 0:92cb496cbbe1 142 *
loopsva 0:92cb496cbbe1 143 * @param set_I2C_frequency
loopsva 0:92cb496cbbe1 144 */
loopsva 0:92cb496cbbe1 145 veml60xx(PinName sda, PinName scl, int i2cFrequency);
loopsva 0:92cb496cbbe1 146
loopsva 0:92cb496cbbe1 147 /**
loopsva 0:92cb496cbbe1 148 * Destructor
loopsva 0:92cb496cbbe1 149 *
loopsva 0:92cb496cbbe1 150 * @param --none--
loopsva 0:92cb496cbbe1 151 */
loopsva 0:92cb496cbbe1 152 ~veml60xx();
loopsva 0:92cb496cbbe1 153
loopsva 0:92cb496cbbe1 154 /**
loopsva 1:f560bd61b3b3 155 * Get VEML60xx ID Register
loopsva 0:92cb496cbbe1 156 *
loopsva 4:0ce65ee5697f 157 * Note: the VEML6040 seems to have an ID register. However, it's not published by Vishay
loopsva 0:92cb496cbbe1 158 *
loopsva 0:92cb496cbbe1 159 * @param pointer to struct veml60xx_struct
loopsva 0:92cb496cbbe1 160 *
loopsva 0:92cb496cbbe1 161 * @return ID Register value
loopsva 0:92cb496cbbe1 162 */
loopsva 0:92cb496cbbe1 163 uint16_t getID(veml60xx_struct& Pntr);
loopsva 0:92cb496cbbe1 164
loopsva 0:92cb496cbbe1 165 /**
loopsva 1:f560bd61b3b3 166 * Get VEMLxx Config Register
loopsva 0:92cb496cbbe1 167 *
loopsva 0:92cb496cbbe1 168 * @param pointer to struct veml60xx_struct
loopsva 0:92cb496cbbe1 169 *
loopsva 0:92cb496cbbe1 170 * @return Config Register value
loopsva 0:92cb496cbbe1 171 */
loopsva 0:92cb496cbbe1 172 uint16_t getConfig(veml60xx_struct& Pntr);
loopsva 0:92cb496cbbe1 173
loopsva 0:92cb496cbbe1 174 /**
loopsva 1:f560bd61b3b3 175 * Get VEML60xx Raw Data
loopsva 0:92cb496cbbe1 176 *
loopsva 0:92cb496cbbe1 177 * @param pointer to struct veml60xx_struct
loopsva 0:92cb496cbbe1 178 *
loopsva 1:f560bd61b3b3 179 * @return raw data put into struct VEML60xx_struct
loopsva 0:92cb496cbbe1 180 */
loopsva 0:92cb496cbbe1 181 uint16_t getRawData(veml60xx_struct& Pntr);
loopsva 0:92cb496cbbe1 182
loopsva 0:92cb496cbbe1 183 /**
loopsva 1:f560bd61b3b3 184 * Convert the VEML6075 Raw Data
loopsva 0:92cb496cbbe1 185 *
loopsva 0:92cb496cbbe1 186 * @param pointer to struct veml60xx_struct
loopsva 0:92cb496cbbe1 187 *
loopsva 1:f560bd61b3b3 188 * @return converted data put into struct VEML60xx_struct
loopsva 0:92cb496cbbe1 189 */
loopsva 0:92cb496cbbe1 190 void convertRawData(veml60xx_struct& Pntr);
loopsva 0:92cb496cbbe1 191
loopsva 0:92cb496cbbe1 192 /**
loopsva 1:f560bd61b3b3 193 * Initialize the VEML60xx
loopsva 0:92cb496cbbe1 194 *
loopsva 0:92cb496cbbe1 195 * Sets up the command register to proper operating mode
loopsva 0:92cb496cbbe1 196 *
loopsva 0:92cb496cbbe1 197 * @param pointer to struct veml60xx_struct
loopsva 0:92cb496cbbe1 198 *
loopsva 0:92cb496cbbe1 199 * @param val any value to be or'd into the config register
loopsva 0:92cb496cbbe1 200 *
loopsva 2:c17b84879a2f 201 * Typical val variable settings:
loopsva 2:c17b84879a2f 202 * - veml.setConfig(vemlSTR, 0);
loopsva 2:c17b84879a2f 203 * - veml.setConfig(vemlSTR, VEML60xx_CONF_BITS_IT_100m80m);
loopsva 2:c17b84879a2f 204 * - veml.setConfig(vemlSTR, VEML60xx_CONF_BITS_IT_400m320m);
loopsva 2:c17b84879a2f 205 * - veml.setConfig(vemlSTR, VEML60xx_CONF_BITS_IT_800m640m | VEML6075_CONF_BITS_HD | VEML60xx_CONF_BITS_AF);
loopsva 2:c17b84879a2f 206 *
loopsva 2:c17b84879a2f 207 * @return nothing
loopsva 0:92cb496cbbe1 208 */
loopsva 0:92cb496cbbe1 209 void setConfig(veml60xx_struct& Pntr, uint16_t val);
loopsva 0:92cb496cbbe1 210
loopsva 0:92cb496cbbe1 211 /**
loopsva 1:f560bd61b3b3 212 * Trigger a VEML60xx conversion cycle
loopsva 0:92cb496cbbe1 213 *
loopsva 0:92cb496cbbe1 214 * Must be in manual trigger mode (AF == 1)
loopsva 0:92cb496cbbe1 215 *
loopsva 2:c17b84879a2f 216 * Example: veml.setConfig(vemlSTR, VEML60xx_CONF_BITS_AF);
loopsva 0:92cb496cbbe1 217 *
loopsva 0:92cb496cbbe1 218 * @param pointer to struct veml60xx_struct
loopsva 0:92cb496cbbe1 219 *
loopsva 0:92cb496cbbe1 220 * @return 0 TRIG properly set
loopsva 0:92cb496cbbe1 221 * @return 1 TRIG has been previously set
loopsva 0:92cb496cbbe1 222 * @return 2 AF bit not set (in AUTO mode)
loopsva 0:92cb496cbbe1 223 */
loopsva 0:92cb496cbbe1 224 uint16_t startAccess(veml60xx_struct& Pntr);
loopsva 0:92cb496cbbe1 225
loopsva 0:92cb496cbbe1 226 /**
loopsva 0:92cb496cbbe1 227 * Automatically adjust Lux scaling level
loopsva 0:92cb496cbbe1 228 *
loopsva 0:92cb496cbbe1 229 * Change CONF_BITS_IT by +-1 if count bits saturated or too low
loopsva 0:92cb496cbbe1 230 *
loopsva 0:92cb496cbbe1 231 * @param pointer to struct veml60xx_struct
loopsva 0:92cb496cbbe1 232 *
loopsva 0:92cb496cbbe1 233 * @return true = IT scale value has changed
loopsva 0:92cb496cbbe1 234 * @return false = IT scale value not changed, could be at its limit
loopsva 0:92cb496cbbe1 235 */
loopsva 0:92cb496cbbe1 236 bool autoAdjustLux(veml60xx_struct& Pntr);
loopsva 0:92cb496cbbe1 237
loopsva 0:92cb496cbbe1 238 private:
loopsva 0:92cb496cbbe1 239 char vemlBuffer[4];
loopsva 0:92cb496cbbe1 240
loopsva 0:92cb496cbbe1 241 protected:
loopsva 0:92cb496cbbe1 242 I2C* _i2c_;
loopsva 0:92cb496cbbe1 243
loopsva 0:92cb496cbbe1 244 };
loopsva 0:92cb496cbbe1 245 #endif