Multi environmental sensor
My version of the bme280 pressure, humidity and temperature sensor
Revision 3:96075bee19f0, committed 2016-04-22
- Comitter:
- loopsva
- Date:
- Fri Apr 22 14:25:55 2016 +0000
- Parent:
- 1:d8d62aee6d5b
- Commit message:
- Trying again to delete VEML60xx remenants
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bme280.cpp Fri Apr 22 14:25:55 2016 +0000 @@ -0,0 +1,425 @@ +// Borch BME280 Barometer, Humidity and Temperature sensor IC + +#include "bme280.h" + +//--------------------------------------------------------------------------------------------------------------------------------------// +// Constructor, to allow for user to select i2c address based on CSB pin + +bme280::bme280(PinName sda, PinName scl, CSBpolarity CSBpin) : _i2c(sda, scl) { + _i2c.frequency(400000); + i2cWAddr = BME280_WADDR; + i2cRAddr = BME280_RADDR; + if(CSBpin == CSBpin_1) { + i2cWAddr++; + i2cWAddr++; + i2cRAddr++; + i2cRAddr++; + } +} + +//--------------------------------------------------------------------------------------------------------------------------------------// +// deconstructor + +bme280::~bme280() { +} + +//--------------------------------------------------------------------------------------------------------------------------------------// +// I2C start. Returns "ack" from slave + +int bme280::_i2c_start(uint8_t i2c_addr) { + int ack; + _i2c.start(); + ack = _i2c_write(i2c_addr); + return(ack); +} + +//--------------------------------------------------------------------------------------------------------------------------------------// +// I2C stop + +void bme280::_i2c_stop() { + _i2c.stop(); +} + +//--------------------------------------------------------------------------------------------------------------------------------------// +// I2C write a byte. Returns "ack" from slave + +uint8_t bme280::_i2c_write(uint8_t data) { + int ack = _i2c.write(data); + return(ack); +} + +//--------------------------------------------------------------------------------------------------------------------------------------// +// I2C read byte and sending ACK. Returns data byte. + +uint8_t bme280::_i2c_readACK() { + uint8_t rdata = _i2c.read(1); + return(rdata); +} + +//--------------------------------------------------------------------------------------------------------------------------------------// +// I2C read byte and sending NACK. Returns data byte. + +uint8_t bme280::_i2c_readNACK() { + uint8_t rdata = _i2c.read(0); + return(rdata); +} + +//--------------------------------------------------------------------------------------------------------------------------------------// +// Get BME280 ID register + +uint8_t bme280::getBmeID() { +#if defined BMEi2cLOWLEVEL + _i2c_start(i2cWAddr); + _i2c_write(BME280_CHIP_ID_REG); + _i2c_start(i2cRAddr); + uint8_t rdata = _i2c_readNACK(); + _i2c_stop(); + return(rdata); +#else + bme280Buffer[0] = BME280_CHIP_ID_REG; + _i2c.write(i2cWAddr, bme280Buffer, 1, true); + _i2c.read(i2cRAddr, bme280Buffer, 1, false); + uint8_t rdata = bme280Buffer[0]; + return(bme280Buffer[0]); +#endif +} + +//--------------------------------------------------------------------------------------------------------------------------------------// +// Soft reset the chip + +uint8_t bme280::resetBme() { +#if defined BMEi2cLOWLEVEL + uint8_t rdata = _i2c_start(i2cWAddr); + if(rdata) return(rdata); + _i2c_write(BME280_RST_REG); + _i2c_write(BME280_RESET_VALUE); + _i2c_stop(); +#else + bme280Buffer[0] = BME280_RST_REG; + bme280Buffer[1] = BME280_RESET_VALUE; + uint8_t rdata = _i2c.write(i2cWAddr, bme280Buffer, 2, false); +#endif + return(rdata); +} + +//--------------------------------------------------------------------------------------------------------------------------------------// +// Get BME280 status register. Returns register value + +uint8_t bme280::getBmeStatus() { +#if defined BMEi2cLOWLEVEL + _i2c_start(i2cWAddr); + _i2c_write(BME280_STAT_REG); + _i2c_start(i2cRAddr); + uint8_t rdata = _i2c_readNACK(); + _i2c_stop(); + return(rdata); +#else + bme280Buffer[0] = BME280_STAT_REG; + _i2c.write(i2cWAddr, bme280Buffer, 1, true); + _i2c.read(i2cRAddr, bme280Buffer, 1, false); + return(bme280Buffer[0]); +#endif +} + +//--------------------------------------------------------------------------------------------------------------------------------------// +// Get BME280 PTH values. Saves raw data is data structure. Returns 0 if successful, !0 if status was busy - pass thru from getBmeStatus(); + +uint8_t bme280::getBmeRawData(bme_data& bmed) { + uint8_t rdata = getBmeStatus(); + if(rdata) return(rdata); + bmed.raw_hum = 0; +#if defined BMEi2cLOWLEVEL + _i2c_start(i2cWAddr); + _i2c_write(BME280_PRESSURE_MSB_REG); + _i2c_start(i2cRAddr); + + // MSB first LSB second XLSB third + bmed.raw_baro = ((_i2c_readACK() << 12) | (_i2c_readACK() << 4) | (_i2c_readACK())); + bmed.raw_temp = ((_i2c_readACK() << 12) | (_i2c_readACK() << 4) | (_i2c_readACK())); + bmed.raw_hum = ((_i2c_readACK() << 8) | (_i2c_readNACK())); + _i2c_stop(); +#else + bme280Buffer[0] = BME280_PRESSURE_MSB_REG; + _i2c.write(i2cWAddr, bme280Buffer, 1, true); + _i2c.read(i2cRAddr, bme280Buffer, 8, false); + // MSB first LSB second XLSB third + bmed.raw_baro = ((bme280Buffer[0] << 12) | (bme280Buffer[1] << 4) | (bme280Buffer[2])); + bmed.raw_temp = ((bme280Buffer[3] << 12) | (bme280Buffer[4] << 4) | (bme280Buffer[5])); + bmed.raw_hum = ((bme280Buffer[6] << 8) | (bme280Buffer[7])); +#endif + return(0); +} + +//--------------------------------------------------------------------------------------------------------------------------------------// +//Convert BME280 PTH values. Takes raw data from data structure and applies calibration values to it. + +void bme280::convertBmeRawData(bme_data& bmed, bme_cal& bmec) { + + //Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC. + //t_fine carries fine temperature as global value + int var1t = ((((bmed.raw_temp >> 3) - ((int)bmec.dig_T1 << 1))) * ((int)bmec.dig_T2)) >> 11; + int var2t = (((((bmed.raw_temp >> 4) - ((int)bmec.dig_T1)) * ((bmed.raw_temp >> 4) - ((int)bmec.dig_T1))) >> 12) * + ((int)bmec.dig_T3)) >> 14; + bmec.t_fine = var1t + var2t; + bmed.corr_temp = (bmec.t_fine * 5 + 128) >> 8; + bmed.bme_temp = (double)bmed.corr_temp / 100.0; + + //Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits). + //Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa + int64_t var1p, var2p, p; + var1p = ((int64_t)bmec.t_fine) - 128000; + var2p = var1p * var1p * (int64_t)bmec.dig_P6; + var2p = var2p + ((var1p * (int64_t)bmec.dig_P5) << 17); + var2p = var2p + (((int64_t)bmec.dig_P4) << 35); + var1p = ((var1p * var1p * (int64_t)bmec.dig_P3 )>> 8) + ((var1p * (int64_t)bmec.dig_P2) << 12); + var1p = (((((int64_t)1) << 47) + var1p)) * ((int64_t)bmec.dig_P1) >> 33; + if (var1p == 0) return; // avoid exception caused by division by zero + p = 1048576 - bmed.raw_baro; + p = (((p << 31) - var2p) * 3125)/var1p; + var1p = (((int64_t)bmec.dig_P9) * (p >> 13) * (p >> 13)) >> 25; + var2p = (((int64_t)bmec.dig_P8) * p) >> 19; + p = ((p + var1p + var2p) >> 8) + (((int64_t)bmec.dig_P7) << 4); + bmed.corr_baro = p >> 8; + bmed.bme_baro = (double)bmed.corr_baro / 100.0; + + //Returns humidity in %RH as unsigned 32 bit integer in Q22.10 format (22 integer and 10 fractional bits). + //Output value of “47445” represents 47445/1024 = 46.333 %RH + int v_x1_u32r = (bmec.t_fine - ((int)76800)); + v_x1_u32r = (((((bmed.raw_hum << 14) - (((int)bmec.dig_H4) << 20) - (((int)bmec.dig_H5) * v_x1_u32r)) + + ((int)16384)) >> 15) * (((((((v_x1_u32r * ((int)bmec.dig_H6)) >> 10) * (((v_x1_u32r * + ((int)bmec.dig_H3)) >> 11) + ((int)32768))) >> 10) + ((int)2097152)) * + ((int)bmec.dig_H2) + 8192) >> 14)); + v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((int)bmec.dig_H1)) >> 4)); + v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r); + v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r); + bmed.corr_hum = (uint32_t)(v_x1_u32r >> 12); + bmed.bme_hum = (double)bmed.corr_hum / 1024.0; //was: / 1000.0 +} + +//--------------------------------------------------------------------------------------------------------------------------------------// +//Convert BME280 PTH values. Takes raw data from data structure and applies calibration values to it. +//Note: This is the floating point version. + +void bme280::convertBmeRawDataFloat(bme_data& bmed, bme_cal& bmec) { + + //Returns temperature in DegC, double precision. Output value of “51.23” equals 51.23 DegC. + //t_fine carries fine temperature as global value + double var1, var2; + var1 = (((double)bmed.raw_temp) / 16384.0 - ((double)bmec.dig_T1) / 1024.0) * ((double)bmec.dig_T2); + var2 = ((((double)bmed.raw_temp) / 131072.0 - ((double)bmec.dig_T1) / 8192.0) * + (((double)bmed.raw_temp) / 131072.0 - ((double)bmec.dig_T1) / 8192.0)) * ((double)bmec.dig_T3); + bmec.t_fine = (int)(var1 + var2); + bmed.corr_temp = 0; + bmed.bme_temp = (var1 + var2) / 5120.0; + + //Returns pressure in Pa as double. Output value of “96386.2” equals 96386.2 Pa = 963.862 hPa + double p; + var1 = ((double)bmec.t_fine / 2.0) - 64000.0; + var2 = var1 * var1 * ((double)bmec.dig_P6) / 32768.0; + var2 = var2 + var1 * ((double)bmec.dig_P5) * 2.0; + var2 = (var2 / 4.0)+(((double)bmec.dig_P4) * 65536.0); + var1 = (((double)bmec.dig_P3) * var1 * var1 / 524288.0 + ((double)bmec.dig_P2) * var1) / 524288.0; + var1 = (1.0 + var1 / 32768.0)*((double)bmec.dig_P1); + if (var1 == 0.0) { + bmed.corr_baro = 0; + bmed.bme_baro = 0.0; + return; //avoid exception caused by division by zero + } + p = 1048576.0 - (double)bmed.raw_baro; + p = (p - (var2 / 4096.0)) * 6250.0 / var1; + var1 = ((double)bmec.dig_P9) * p * p / 2147483648.0; + var2 = p * ((double)bmec.dig_P8) / 32768.0; + p = p + (var1 + var2 + ((double)bmec.dig_P7)) / 16.0; + bmed.corr_baro = 0; + bmed.bme_baro = p / 100.0; + + //Returns humidity in %rH as as double. Output value of “46.332” represents 46.332 %rH + double var_H; + var_H = (((double)bmec.t_fine) - 76800.0); + var_H = (bmed.raw_hum - (((double)bmec.dig_H4) * 64.0 + ((double)bmec.dig_H5) / 16384.0 * var_H)) * + (((double)bmec.dig_H2) / 65536.0 * (1.0 + ((double)bmec.dig_H6) / 67108864.0 * var_H * + (1.0 + ((double)bmec.dig_H3) / 67108864.0 * var_H))); + var_H = var_H * (1.0 - ((double)bmec.dig_H1) * var_H / 524288.0); + if (var_H > 100.0) { + var_H = 100.0; + } else if (var_H < 0.0) { + var_H = 0.0; + } + bmed.corr_hum = 0; + bmed.bme_hum = var_H; +} + +//--------------------------------------------------------------------------------------------------------------------------------------// +// Initialize the chip + +uint8_t bme280::initBme(bme_cal& bmec) { +#if defined BMEi2cLOWLEVEL + //initialize the chip + _i2c_start(i2cWAddr); + _i2c_write(BME280_CTRL_HUMIDITY_REG); + _i2c_write(BME280_CTRL_HUMIDITY_REG_DATA); + _i2c_stop(); + + _i2c_start(i2cWAddr); + _i2c_write(BME280_CTRL_MEAS_REG); + _i2c_write(BME280_CTRL_MEAS_REG_DATA); + _i2c_stop(); + + _i2c_start(i2cWAddr); + _i2c_write(BME280_CONFIG_REG); + _i2c_write(BME280_CONFIG_REG_DATA); + _i2c_stop(); + + //read back config registers + _i2c_start(i2cWAddr); + _i2c_write(BME280_CTRL_HUMIDITY_REG); + _i2c_start(i2cRAddr); + bmec.ctrl_hum_reg = _i2c_readACK(); + uint8_t status = _i2c_readACK(); + bmec.ctrl_meas_reg = _i2c_readACK(); + bmec.config_reg = _i2c_readNACK(); + _i2c_stop(); + + //now get the calibration registers + _i2c_start(i2cWAddr); + _i2c_write(BME280_CAL_DATA_START_1); + _i2c_start(i2cRAddr); + // LSB first MSB second + bmec.dig_T1 = (_i2c_readACK() + (_i2c_readACK() << 8)); + bmec.dig_T2 = (_i2c_readACK() + (_i2c_readACK() << 8)); + bmec.dig_T3 = (_i2c_readACK() + (_i2c_readACK() << 8)); + bmec.dig_P1 = (_i2c_readACK() + (_i2c_readACK() << 8)); + bmec.dig_P2 = (_i2c_readACK() + (_i2c_readACK() << 8)); + bmec.dig_P3 = (_i2c_readACK() + (_i2c_readACK() << 8)); + bmec.dig_P4 = (_i2c_readACK() + (_i2c_readACK() << 8)); + bmec.dig_P5 = (_i2c_readACK() + (_i2c_readACK() << 8)); + bmec.dig_P6 = (_i2c_readACK() + (_i2c_readACK() << 8)); + bmec.dig_P7 = (_i2c_readACK() + (_i2c_readACK() << 8)); + bmec.dig_P8 = (_i2c_readACK() + (_i2c_readACK() << 8)); + bmec.dig_P9 = (_i2c_readACK() + (_i2c_readACK() << 8)); + uint8_t rdata = (_i2c_readACK()); //dummy read of address 0xa0 + bmec.dig_H1 = (_i2c_readNACK()); + _i2c_stop(); + + //finally, get the Humid calibration registers + _i2c_start(i2cWAddr); + _i2c_write(BME280_CAL_DATA_START_2); + _i2c_start(i2cRAddr); + bmec.dig_H2 = (_i2c_readACK() + (_i2c_readACK() << 8)); + bmec.dig_H3 = (_i2c_readACK()); + bmec.dig_H4 = (_i2c_readACK() + (_i2c_readACK() << 8)); + bmec.dig_H5 = (_i2c_readACK() + (_i2c_readACK() << 8)); + bmec.dig_H6 = (_i2c_readNACK()); + _i2c_stop(); + +#else + //initialize the chip + bme280Buffer[0] = BME280_CTRL_HUMIDITY_REG; + bme280Buffer[1] = BME280_CTRL_HUMIDITY_REG_DATA; + _i2c.write(i2cWAddr, bme280Buffer, 2, false); + + bme280Buffer[0] = BME280_CTRL_MEAS_REG; + bme280Buffer[1] = BME280_CTRL_MEAS_REG_DATA; + _i2c.write(i2cWAddr, bme280Buffer, 2, false); + + bme280Buffer[0] = BME280_CONFIG_REG; + bme280Buffer[1] = BME280_CONFIG_REG_DATA; + _i2c.write(i2cWAddr, bme280Buffer, 2, false); + + //read back config registers + bme280Buffer[0] = BME280_CTRL_HUMIDITY_REG; + _i2c.write(i2cWAddr, bme280Buffer, 1, true); + _i2c.read(i2cRAddr, bme280Buffer, 4, false); + bmec.ctrl_hum_reg = bme280Buffer[0]; +// uint8_t status = bme280Buffer[1]; + bmec.ctrl_meas_reg = bme280Buffer[2]; + bmec.config_reg = bme280Buffer[3]; + + //now get the calibration registers, Temp and Press first + bme280Buffer[0] = BME280_CAL_DATA_START_1; + _i2c.write(i2cWAddr, bme280Buffer, 1, true); + _i2c.read(i2cRAddr, bme280Buffer, 26, false); + // LSB first MSB second + bmec.dig_T1 = (bme280Buffer[0] | (bme280Buffer[1] << 8)); + bmec.dig_T2 = (bme280Buffer[2] | (bme280Buffer[3] << 8)); + bmec.dig_T3 = (bme280Buffer[4] | (bme280Buffer[5] << 8)); + bmec.dig_P1 = (bme280Buffer[6] | (bme280Buffer[7] << 8)); + bmec.dig_P2 = (bme280Buffer[8] | (bme280Buffer[9] << 8)); + bmec.dig_P3 = (bme280Buffer[10] | (bme280Buffer[11] << 8)); + bmec.dig_P4 = (bme280Buffer[12] | (bme280Buffer[13] << 8)); + bmec.dig_P5 = (bme280Buffer[14] | (bme280Buffer[15] << 8)); + bmec.dig_P6 = (bme280Buffer[16] | (bme280Buffer[17] << 8)); + bmec.dig_P7 = (bme280Buffer[18] | (bme280Buffer[19] << 8)); + bmec.dig_P8 = (bme280Buffer[20] | (bme280Buffer[21] << 8)); + bmec.dig_P9 = (bme280Buffer[22] | (bme280Buffer[23] << 8)); +// uint8_t rdata = (bme280Buffer[24]); //dummy read of address 0xa0 + bmec.dig_H1 = (bme280Buffer[25]); + + //finally, get the Humid calibration registers + bme280Buffer[0] = BME280_CAL_DATA_START_2; + _i2c.write(i2cWAddr, bme280Buffer, 1, true); + _i2c.read(i2cRAddr, bme280Buffer, 8, false); + bmec.dig_H2 = (bme280Buffer[0] | (bme280Buffer[1] << 8)); + bmec.dig_H3 = (bme280Buffer[2]); + bmec.dig_H4 = ((bme280Buffer[4] & 15) | (bme280Buffer[3] << 4)); + bmec.dig_H5 = (((bme280Buffer[4] >> 4) & 15) | (bme280Buffer[5] << 4)); + bmec.dig_H6 = (bme280Buffer[6]); + +#endif + return(0); + } + +//--------------------------------------------------------------------------------------------------------------------------------------// +// Return corrected altitude (in feet) from barometer at sea level (in mB) + +float bme280::getAltitudeFT(bme_data& bmed, float sea_pressure) { + return(float)((1 - (pow((bmed.bme_baro / (double)sea_pressure), 0.190284))) * 145366.45); +} + +//--------------------------------------------------------------------------------------------------------------------------------------// +// Return corrected barometer, based on altitude (in feet) + +float bme280::getSeaLevelBaroFT(bme_data& bmed, float known_alt) { + return(pow(pow((bmed.bme_baro * MB_INHG_DOUBLE), 0.190284) + 0.00001313 * (double)known_alt , 5.2553026) * INHG_MB_DOUBLE); +} + +//--------------------------------------------------------------------------------------------------------------------------------------// +// Return corrected barometer, based on altitude (in meters) + +float bme280::getSeaLevelBaroM(bme_data& bmed, float known_alt) { + return(pow(pow((bmed.bme_baro * MB_INHG_DOUBLE), 0.190284) + 0.00001313 * (double)known_alt * FEET_METERS , 5.2553026) * INHG_MB_DOUBLE); +} + +//--------------------------------------------------------------------------------------------------------------------------------------// +// Return dew point. More accurate, slower + +float bme280::getDewPt(bme_data& bmed) { + // dewPoint function NOAA + // reference: http://wahiduddin.net/calc/density_algorithms.htm + double A0= 373.15 / (273.15 + (double)bmed.bme_temp); + double SUM = -7.90298 * (A0 -1); + SUM += 5.02808 * log10(A0); + SUM += -1.3816e-7 * (pow(10, (11.344 * (1 - 1/A0))) -1) ; + SUM += 8.1328e-3 * (pow(10,(-3.49149 * (A0 -1))) -1) ; + SUM += log10(1013.246); + double VP = pow(10, SUM -3) * bmed.bme_hum; + double T = log(VP / 0.61078); // temp var + return (241.88 * T) / (17.558 - T); +} + +//--------------------------------------------------------------------------------------------------------------------------------------// +// Return dew point. Less accurate, faster + +float bme280::getDewPtFast(bme_data& bmed) { + // delta max = 0.6544 wrt dewPoint() + // 5x faster than dewPoint() + // reference: http://en.wikipedia.org/wiki/Dew_point + double bmeDtzA = 17.271; + double bmeDtzB = 237.7; + double bmeDtzC = (bmeDtzA * bmed.bme_temp) / (bmeDtzB + bmed.bme_temp) + log(bmed.bme_hum / 100.0); + double bmeDtzD = (bmeDtzB * bmeDtzC) / (bmeDtzA - bmeDtzC); + return (bmeDtzD); +} + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bme280.h Fri Apr 22 14:25:55 2016 +0000 @@ -0,0 +1,331 @@ +#ifndef BME280_H +#define BME280_H + +#include "mbed.h" + +#if(defined(TARGET_KL25Z) || defined(TARGET_K64F)) + +// #define BME280i2cLOWLEVEL 1 //if the use of low-level I2C routines is needed +// #warning "BME280 using low level I2C routines" + +#endif + + +#define SEA_PRESS 1013.25 //default sea level pressure level in mb +//#define KNOWNALT 327.0 //default known altitude in feet +#define METERS_FEET 3.2808399 +#define FEET_METERS 0.3048006 +#define MB_INHG_DOUBLE 0.02952998751 +#define INHG_MB_DOUBLE 33.8638815767 +#define DEGC_DEGF_FLOAT 9.0 / 5.0 + 32.0 +#define DEGC_DEGF_INT 9 / 5 + 32 + +#define BME280_WADDR 0xEC //i2c address write mode (CSBpin = 0); +#define BME280_RADDR 0xED //i2c address read mode + +#define BME280_CHIP_ID_REG 0xD0 //Chip ID Register +#define BME280_CAL_DATA_START_1 0x88 //Calibration data parameters +#define BME280_CAL_DATA_START_2 0xE1 //More calibration data parameters +#define BME280_RST_REG 0xE0 //Softreset Register +#define BME280_STAT_REG 0xF3 //Status Register +#define BME280_CTRL_MEAS_REG 0xF4 //Ctrl Measure Register +#define BME280_CTRL_HUMIDITY_REG 0xF2 //Ctrl Humidity Register +#define BME280_CONFIG_REG 0xF5 //Configuration Register +#define BME280_PRESSURE_MSB_REG 0xF7 //Pressure MSB Register +#define BME280_PRESSURE_LSB_REG 0xF8 //Pressure LSB Register +#define BME280_PRESSURE_XLSB_REG 0xF9 //Pressure XLSB Register +#define BME280_TEMPERATURE_MSB_REG 0xFA //Temperature MSB Reg +#define BME280_TEMPERATURE_LSB_REG 0xFB //Temperature LSB Reg +#define BME280_TEMPERATURE_XLSB_REG 0xFC //Temperature XLSB Reg +#define BME280_HUMIDITY_MSB_REG 0xFD //Humidity MSB Reg +#define BME280_HUMIDITY_LSB_REG 0xFE //Humidity LSB Reg + +// Status register bits +#define BME280_STATUS_BUSY 0x08 +#define BME280_STATUS_UNKNOWN 0x04 +#define BME280_STATUS_IMUPDATE 0x01 + +#define BME280_RESET_VALUE 0xB6 + +// Config register equates +#define BME280_OVERSAMPLE_SKIP 0 +#define BME280_OVERSAMPLE_x1 1 +#define BME280_OVERSAMPLE_x2 2 +#define BME280_OVERSAMPLE_x4 3 +#define BME280_OVERSAMPLE_x8 4 +#define BME280_OVERSAMPLE_x16 5 + +#define BME280_TEMP_OVERSAMPLE BME280_OVERSAMPLE_x1 //was x2 +#define BME280_PRESS_OVERSAMPLE BME280_OVERSAMPLE_x1 //was x4 +#define BME280_HUM_OVERSAMPLE BME280_OVERSAMPLE_x1 //was x2 + +#define BME280_MODE_SLEEP 0 +#define BME280_MODE_FORCED 1 +#define BME280_MODE_NORMAL 3 + +#define BME280_STANDBY_0m5 0 +#define BME280_STANDBY_62m5 1 +#define BME280_STANDBY_125m 2 +#define BME280_STANDBY_250m 3 +#define BME280_STANDBY_500m 4 +#define BME280_STANDBY_1000m 5 +#define BME280_STANDBY_10m 6 +#define BME280_STANDBY_20m 7 + +#define BME280_FILTER_OFF 0 +#define BME280_FILTER_2 1 +#define BME280_FILTER_4 2 +#define BME280_FILTER_8 3 +#define BME280_FILTER_16 4 + +//osrs_t(7..5), osrs_p(4..2), mode(1..0) +#define BME280_CTRL_MEAS_REG_DATA ((BME280_TEMP_OVERSAMPLE << 5) | (BME280_PRESS_OVERSAMPLE << 2) | BME280_MODE_NORMAL) +//0(7..3), osrs_h(2..0) +#define BME280_CTRL_HUMIDITY_REG_DATA ((BME280_HUM_OVERSAMPLE)) +//sb(7..5), filter(4..2), 0(1), spl3w_en(0) +#define BME280_CONFIG_REG_DATA ((BME280_STANDBY_1000m << 5) | (BME280_FILTER_OFF << 2)) //was FILTER_4 + +//Until it is understood why data cannot be raed out of BME280 right after BUSY goes false, the +//defines below introduce a variable delay in main(), based on sb bits used. +// example: wait_ms(BME280_MAIN_WAIT); must be put between pth.getBmeRawData(bmed_struct); accesses +#if ((BME280_CONFIG_REG_DATA >> 5) == BME280_STANDBY_0m5) +#define BME280_MAIN_WAIT 100 +#elif ((BME280_CONFIG_REG_DATA >> 5) == BME280_STANDBY_62m5) +#define BME280_MAIN_WAIT 60 +#elif ((BME280_CONFIG_REG_DATA >> 5) == BME280_STANDBY_125m) +#define BME280_MAIN_WAIT 120 +#elif ((BME280_CONFIG_REG_DATA >> 5) == BME280_STANDBY_250m) +#define BME280_MAIN_WAIT 240 +#elif ((BME280_CONFIG_REG_DATA >> 5) == BME280_STANDBY_500m) +#define BME280_MAIN_WAIT 100 +#elif ((BME280_CONFIG_REG_DATA >> 5) == BME280_STANDBY_1000m) +#define BME280_MAIN_WAIT 500 +#elif ((BME280_CONFIG_REG_DATA >> 5) == BME280_STANDBY_10m) +#define BME280_MAIN_WAIT 50 +#elif ((BME280_CONFIG_REG_DATA >> 5) == BME280_STANDBY_20m) +#define BME280_MAIN_WAIT 59 +#endif + + + /** + * Create bme280 controller class + * + * @param bme280 class + * + */ +class bme280 { + +public: + + /** + * Public data structure for CME280 correction values. + * + **/ + typedef struct { + uint16_t dig_T1; /*!< calibration parameter -> Temp T1 */ + int16_t dig_T2; /*!< calibration parameter -> Temp T2 */ + int16_t dig_T3; /*!< calibration parameter -> Temp T3 */ + + uint16_t dig_P1; /*!< calibration parameter -> Press P1 */ + int16_t dig_P2; /*!< calibration parameter -> Press P2 */ + int16_t dig_P3; /*!< calibration parameter -> Press P3 */ + int16_t dig_P4; /*!< calibration parameter -> Press P4 */ + int16_t dig_P5; /*!< calibration parameter -> Press P5 */ + int16_t dig_P6; /*!< calibration parameter -> Press P6 */ + int16_t dig_P7; /*!< calibration parameter -> Press P7 */ + int16_t dig_P8; /*!< calibration parameter -> Press P8 */ + int16_t dig_P9; /*!< calibration parameter -> Press P9 */ + + uint8_t dig_H1; /*!< calibration parameter -> Hum H1 */ + int16_t dig_H2; /*!< calibration parameter -> Hum H2 */ + uint8_t dig_H3; /*!< calibration parameter -> Hum H3 */ + int16_t dig_H4; /*!< calibration parameter -> Hum H4 */ + int16_t dig_H5; /*!< calibration parameter -> Hum H5 */ + int8_t dig_H6; /*!< calibration parameter -> Hum H6 */ + + uint32_t t_fine; /*!< scratch T_FINE */ + + uint8_t ctrl_hum_reg; /*!< config -> hum */ + uint8_t ctrl_meas_reg; /*!< config -> temp press mode */ + uint8_t config_reg; /*!< config -> delay filter spi3w */ + } bme_cal; + + /** + * Public data structure to obtain CME280 data. + * + **/ + typedef struct { + int raw_temp; /*!< raw temperature reading, 20 bits */ + int raw_baro; /*!< raw pressure reading, 20 bits */ + int raw_hum; /*!< raw humidity reading, 16 bits */ + int corr_temp; /*!< corrected temperature as integer*/ + int64_t corr_baro; /*!< corrected pressure as integer */ + uint32_t corr_hum; /*!< corrected humidity as integer */ + double bme_temp; /*!< corrected temperature as a float */ + double bme_baro; /*!< corrected pressure as a float */ + double bme_hum; /*!< corrected humidity as a float */ + } bme_data; + + /** + * Public enum for selecting polarity of I2C address pin. + * + * - CSB pin = 0, user set I2C address to 0xEC + * - CSB pin = 1, user set I2C address to 0xEE + * + **/ + enum CSBpolarity { + CSBpin_0, //CSB pin is grounded, I2C address is 0xEC and 0xED + CSBpin_1, //CSB pin is tied to Vdd, I2C address is 0xEE and 0xEF + }; + + /** + * Create a BME280 object using the specified I2C object + * - User defined use of the CSB pin + * - CSB pin = 0, user set I2C address to 0xEC + * - CSB pin = 1, user set I2C address to 0xEE + * @param sda - mbed I2C interface pin + * @param scl - mbed I2C interface pin + * @param bme280::CSBpin_0 - CSB pin tied to ground + * @param bme280::CSBpin_1 - CSB pin tied to VDD + */ + bme280(PinName sda, PinName scl, CSBpolarity CSBpin); + + /** + * Destructor + * + * @param --none-- + */ + ~bme280(); + + /** + * Get BME280 ID Register + * + * @param --none-- + * + * @return ID Register value + */ + uint8_t getBmeID(); + + /** + * Soft Reset the BME280 + * + * @param --none-- + * + * @return ACK/NACK status + */ + uint8_t resetBme(); + + /** + * Get BME280 Status Register + * + * @param --none-- + * + * @return Status Register value + */ + uint8_t getBmeStatus(); + + /** + * Get BME280 Raw Data + * + * @param pointer to struct bme_data + * + * @return Status Register value. Pass-thru from getBmeStatus() + * @return raw data put into struct bme_data + */ + uint8_t getBmeRawData(bme_data& bmed); + + /** + * Convert BME280 Raw Data using integer based routines + * + * @param pointer to struct bme_data + * @param pointer to struct bme_cal + * + * @return converted data put into struct bme_data + */ + void convertBmeRawData(bme_data& bmed, bme_cal& bmec); + + /** + * Convert BME280 Raw Data using all floating routines + * + * @param pointer to struct bme_data + * @param pointer to struct bme_cal + * + * @return converted data put into struct bme_data + */ + void convertBmeRawDataFloat(bme_data& bmed, bme_cal& bmec); + + /** + * Initialize the BME280. + * - Sets up the command registers + * - Loads up the calibration data + * + * @param pointer to struct bme_data + * + * @return 0 + */ + uint8_t initBme(bme_cal& bmec); + + /** + * Corrected altitude (feet) from barometer at seal level (mB) + * + * @param pointer to struct bme_data + * @param pressure at sea level (in mB) + * + * @return corrected altimeter (in feet) + */ + float getAltitudeFT(bme_data& bmed, float sea_pressure); + + /** + * Altitude corrected barometer (feet) + * + * @param pointer to struct bme_data + * @param known_alt in feet + * + * @return corrected barometer + */ + float getSeaLevelBaroFT(bme_data& bmed, float known_alt); + + /** + * Altitude corrected barometer (meters) + * + * @param pointer to struct bme_data + * @param known_alt in meters + * + * @return corrected barometer + */ + float getSeaLevelBaroM(bme_data& bmed, float known_alt); + + /** + * Return the dew point based on T & H. Slower but more accurate. + * + * @param pointer to struct bme_data + * + * @return dew point in degrees C + */ + float getDewPt(bme_data& bmed); + + /** + * Return the dew point based on T & H. Faster but less accurate. + * + * @param pointer to struct bme_data + * + * @return dew point in degrees C + */ + float getDewPtFast(bme_data& bmed); + +private: +#if not defined BMEi2cLOWLEVEL + char bme280Buffer[32]; +#endif + char i2cWAddr; + char i2cRAddr; + int _i2c_start(uint8_t i2c_addr); + void _i2c_stop(); + uint8_t _i2c_write(uint8_t data); + uint8_t _i2c_readACK(); + uint8_t _i2c_readNACK(); + +protected: + I2C _i2c; +}; +#endif \ No newline at end of file
--- a/veml60xx.cpp Thu Apr 21 23:32:50 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,229 +0,0 @@ -// 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
--- a/veml60xx.h Thu Apr 21 23:32:50 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,212 +0,0 @@ -#ifndef VEML60XX_H -#define VEML60XX_H - -#include "mbed.h" - -// I2C address -#define VEML60_WADDR 0x20 //i2c address write mode -#define VEML60_RADDR 0x21 //i2c address read mode - - -// VEMP6040 and VEML6075 common register set -#define VEML60xx_CONF_REG 0x00 //rw Config Register - -// VEML6075-only register set -#define VEML6075_UVA_DATA_REG 0x07 //ro 16 bit UVA data Register -#define VEML6075_DUMMY_REG 0x08 //ro 16 bit dummy Register -#define VEML6075_UVB_DATA_REG 0x09 //ro 16 bit UVB data Register -#define VEML6075_UV_COMP1_REG 0x0A //ro 16 bit UV compensation Register 1 -#define VEML6075_UV_COMP2_REG 0x0B //ro 16 bit UV compensation Register 2 -#define VEML6075_CHIP_ID_REG 0x0C //ro 16 bit Chip ID Register - -// VEML6040-only register set -#define VEML6040_R_DATA_REG 0x08 //ro 16 bit RED data -#define VEML6040_G_DATA_REG 0x09 //ro 16 bit GREEN data -#define VEML6040_B_DATA_REG 0x0A //ro 16 bit BLUE data -#define VEML6040_W_DATA_REG 0x0B //ro 16 bit WHITE data - -// VEML6040 and VEML6075 common config register bits -#define VEML60xx_CONF_BITS_IT 0x70 //VEML6075 -> 0x00 = 50mS, 0x10 = 100mS, 0x20 = 200mS, 0x30 = 400mS, 0x40 = 800mS, 0x50-0x70 = reserved - //VEML6040 -> 0x00 = 40mS, 0x10 = 80mS, 0x20 = 160mS, 0x30 = 320mS, 0x40 = 640mS, 0x50 = 1280mS, 0x60-0x70 = reserved -#define VEML60xx_CONF_BITS_IT_50m40m 0x00 -#define VEML60xx_CONF_BITS_IT_100m80m 0x10 -#define VEML60xx_CONF_BITS_IT_200m160m 0x20 -#define VEML60xx_CONF_BITS_IT_400m320m 0x30 -#define VEML60xx_CONF_BITS_IT_800m640m 0x40 - -#define VEML60xx_CONF_BITS_TRIG 0x04 //0x00 = idle, 0x04 = trigger (measurement), auto returns to 0x00 note: AF == 1 -#define VEML60xx_CONF_BITS_AF 0x02 //0x00 = auto, 0x02 = force (mode) -#define VEML60xx_CONF_BITS_SD 0x01 //0x00 = run, 0x01 = shut down - -// VEML6075-only config register bits -#define VEML6075_CONF_BITS_HD 0x08 //0x00 = normal, 0x08 = high (dynamic setting) - -// VEML6040-only config register bits -#define VEML6040_CONF_BITS_IT_1280m 0x50 - -// VEML6075-only ID contents -#define VEML6075_DEVICE_ID 0x0026 //expected device ID - -// VEML6040-only ID contents -#define VEML6040_DEVICE_ID 0x0123 //expected device ID - -// VEML6075-only conversion coefficients -#define VEML6075_UVA_COEF_A 3.33 -#define VEML6075_UVA_COEF_B 2.50 -#define VEML6075_UVB_COEF_C 3.67 -#define VEML6075_UVB_COEF_D 2.75 - -// VEML6040-only conversion coefficients -#define VEML6040_LUX_STEP_000 0.18 -#define VEML6040_LUX_STEP_001 0.09 -#define VEML6040_LUX_STEP_010 0.045 -#define VEML6040_LUX_STEP_011 0.0225 -#define VEML6040_LUX_STEP_100 0.01125 -#define VEML6040_LUX_STEP_101 0.005625 - -// VEML6075-only conversion coefficients -#define VEML6075_UVA_RESP 0.0011 -#define VEML6075_UVB_RESP 0.00125 - - - /** - * Create VEML60 controller class - * - * @param VEML class - * - */ -class veml60xx { - -public: - - /** - * Public data structure for VEML60xx data values. - * - **/ - typedef struct { - uint16_t conf_reg; /*!< VEML60xx config register mirror */ - - uint16_t uva_d; /*!< VEML6075 UVA data */ - uint16_t dummy_d; /*!< VEML6075 Dummy data */ - uint16_t uvb_d; /*!< VEML6075 UVB data */ - uint16_t uv_c1; /*!< VEML6075 UV comp1 data */ - uint16_t uv_c2; /*!< VEML6075 UV comp2 data */ - uint16_t id; /*!< VEML6075 Device ID*/ - double uva_comp; /*!< VEML6075 UVA compensated data */ - double uvb_comp; /*!< VEML6075 UVB compensated data */ - double uv_index; /*!< VEML6075 UV Index */ - - uint16_t r_d; /*!< VEML6040 RED data */ - uint16_t g_d; /*!< VEML6040 GREEN data */ - uint16_t b_d; /*!< VEML6040 BLUE data */ - uint16_t w_d; /*!< VEML6040 WHITE data */ - double lux_step; /*!< VEML6040 Lux value per step */ - - bool is6075; /*!< connected device is a VEML6075 */ - bool is6040; /*!< connected device is a VEML6040 */ - } veml60xx_struct; - - /** - * Create a VME60xx object using the specified I2C object - * - * @param sda - mbed I2C interface pin - * - * @param scl - mbed I2C interface pin - * - * @param set_I2C_frequency - */ - veml60xx(PinName sda, PinName scl, int i2cFrequency); - - /** - * Destructor - * - * @param --none-- - */ - ~veml60xx(); - - /** - * Get VEMP6075 ID Register - * - * Note: the VEMP6040 seems to have an ID register. It's not published - * - * @param pointer to struct veml60xx_struct - * - * @return ID Register value - */ - uint16_t getID(veml60xx_struct& Pntr); - - /** - * Get VEMPxx Config Register - * - * @param pointer to struct veml60xx_struct - * - * @return Config Register value - */ - uint16_t getConfig(veml60xx_struct& Pntr); - - /** - * Get VEMP60xx Raw Data - * - * @param pointer to struct veml60xx_struct - * - * @return raw data put into struct vemp60xx_struct - */ - uint16_t getRawData(veml60xx_struct& Pntr); - - /** - * Convert the VEMP6075 Raw Data - * - * @param pointer to struct veml60xx_struct - * - * @return converted data put into struct vemp60xx_struct - */ - void convertRawData(veml60xx_struct& Pntr); - - /** - * Initialize the VEMP60xx - * - * Sets up the command register to proper operating mode - * - * @param pointer to struct veml60xx_struct - * - * @param val any value to be or'd into the config register - * - * @return 0 - */ - void setConfig(veml60xx_struct& Pntr, uint16_t val); - - /** - * Trigger a VEMP60xx conversion cycle - * - * Must be in manual trigger mode (AF == 1) - * - * Example: uv.setConfig(struct_ptr, VEML60xx_CONF_BITS_AF); - * - * @param pointer to struct veml60xx_struct - * - * @return 0 TRIG properly set - * @return 1 TRIG has been previously set - * @return 2 AF bit not set (in AUTO mode) - */ - uint16_t startAccess(veml60xx_struct& Pntr); - - /** - * Automatically adjust Lux scaling level - * - * Change CONF_BITS_IT by +-1 if count bits saturated or too low - * - * @param pointer to struct veml60xx_struct - * - * @return true = IT scale value has changed - * @return false = IT scale value not changed, could be at its limit - */ - bool autoAdjustLux(veml60xx_struct& Pntr); - -private: - char vemlBuffer[4]; - -protected: - I2C* _i2c_; - -}; -#endif \ No newline at end of file