diff --git a/Adafruit_VEML6046.cpp b/Adafruit_VEML6046.cpp index 79916aa..a7af339 100644 --- a/Adafruit_VEML6046.cpp +++ b/Adafruit_VEML6046.cpp @@ -398,4 +398,160 @@ bool Adafruit_VEML6046::getData(uint16_t* r, uint16_t* g, uint16_t* b, *ir = buffer[6] | (buffer[7] << 8); return true; +} + +/*! + * @brief Calculates lux value from green channel count + * @param green_count Raw green channel reading + * @return Calculated lux value + */ +float Adafruit_VEML6046::calculateLux(uint16_t green_count) { + // Get current settings to determine resolution factor + veml6046_integration_time_t it = getIntegrationTime(); + veml6046_gain_t gain = getRGBGain(); + bool half_pd = getPhotoDiodeHalfSize(); + + float resolution = 0.0; + + // Resolution table from datasheet (lx/cnt) + // TABLE 13 - 2/2 PD USED, TABLE 14 - 1/2 PD USED + if (half_pd) { + // 1/2 PD used - TABLE 14 + switch (it) { + case VEML6046_IT_400MS: + switch (gain) { + case VEML6046_GAIN_2X: resolution = 0.0105; break; + case VEML6046_GAIN_1X: resolution = 0.0210; break; + case VEML6046_GAIN_0_66X: resolution = 0.0318; break; + case VEML6046_GAIN_0_5X: resolution = 0.0420; break; + } + break; + case VEML6046_IT_200MS: + switch (gain) { + case VEML6046_GAIN_2X: resolution = 0.0210; break; + case VEML6046_GAIN_1X: resolution = 0.0420; break; + case VEML6046_GAIN_0_66X: resolution = 0.0636; break; + case VEML6046_GAIN_0_5X: resolution = 0.0840; break; + } + break; + case VEML6046_IT_100MS: + switch (gain) { + case VEML6046_GAIN_2X: resolution = 0.0420; break; + case VEML6046_GAIN_1X: resolution = 0.0840; break; + case VEML6046_GAIN_0_66X: resolution = 0.1273; break; + case VEML6046_GAIN_0_5X: resolution = 0.1680; break; + } + break; + case VEML6046_IT_50MS: + switch (gain) { + case VEML6046_GAIN_2X: resolution = 0.0840; break; + case VEML6046_GAIN_1X: resolution = 0.1680; break; + case VEML6046_GAIN_0_66X: resolution = 0.2545; break; + case VEML6046_GAIN_0_5X: resolution = 0.3360; break; + } + break; + case VEML6046_IT_25MS: + switch (gain) { + case VEML6046_GAIN_2X: resolution = 0.1680; break; + case VEML6046_GAIN_1X: resolution = 0.3360; break; + case VEML6046_GAIN_0_66X: resolution = 0.5091; break; + case VEML6046_GAIN_0_5X: resolution = 0.6720; break; + } + break; + case VEML6046_IT_12_5MS: + switch (gain) { + case VEML6046_GAIN_2X: resolution = 0.3360; break; + case VEML6046_GAIN_1X: resolution = 0.6720; break; + case VEML6046_GAIN_0_66X: resolution = 1.0182; break; + case VEML6046_GAIN_0_5X: resolution = 1.3440; break; + } + break; + case VEML6046_IT_6_25MS: + switch (gain) { + case VEML6046_GAIN_2X: resolution = 0.6720; break; + case VEML6046_GAIN_1X: resolution = 1.3440; break; + case VEML6046_GAIN_0_66X: resolution = 2.0364; break; + case VEML6046_GAIN_0_5X: resolution = 2.6880; break; + } + break; + case VEML6046_IT_3_125MS: + switch (gain) { + case VEML6046_GAIN_2X: resolution = 1.3440; break; + case VEML6046_GAIN_1X: resolution = 2.6880; break; + case VEML6046_GAIN_0_66X: resolution = 4.0727; break; + case VEML6046_GAIN_0_5X: resolution = 5.3760; break; + } + break; + } + } else { + // 2/2 PD used - TABLE 13 + switch (it) { + case VEML6046_IT_400MS: + switch (gain) { + case VEML6046_GAIN_2X: resolution = 0.0053; break; + case VEML6046_GAIN_1X: resolution = 0.0105; break; + case VEML6046_GAIN_0_66X: resolution = 0.0159; break; + case VEML6046_GAIN_0_5X: resolution = 0.0210; break; + } + break; + case VEML6046_IT_200MS: + switch (gain) { + case VEML6046_GAIN_2X: resolution = 0.0105; break; + case VEML6046_GAIN_1X: resolution = 0.0210; break; + case VEML6046_GAIN_0_66X: resolution = 0.0318; break; + case VEML6046_GAIN_0_5X: resolution = 0.0420; break; + } + break; + case VEML6046_IT_100MS: + switch (gain) { + case VEML6046_GAIN_2X: resolution = 0.0210; break; + case VEML6046_GAIN_1X: resolution = 0.0420; break; + case VEML6046_GAIN_0_66X: resolution = 0.0636; break; + case VEML6046_GAIN_0_5X: resolution = 0.0840; break; + } + break; + case VEML6046_IT_50MS: + switch (gain) { + case VEML6046_GAIN_2X: resolution = 0.0420; break; + case VEML6046_GAIN_1X: resolution = 0.0840; break; + case VEML6046_GAIN_0_66X: resolution = 0.1273; break; + case VEML6046_GAIN_0_5X: resolution = 0.1680; break; + } + break; + case VEML6046_IT_25MS: + switch (gain) { + case VEML6046_GAIN_2X: resolution = 0.0840; break; + case VEML6046_GAIN_1X: resolution = 0.1680; break; + case VEML6046_GAIN_0_66X: resolution = 0.2545; break; + case VEML6046_GAIN_0_5X: resolution = 0.3360; break; + } + break; + case VEML6046_IT_12_5MS: + switch (gain) { + case VEML6046_GAIN_2X: resolution = 0.1680; break; + case VEML6046_GAIN_1X: resolution = 0.3360; break; + case VEML6046_GAIN_0_66X: resolution = 0.5091; break; + case VEML6046_GAIN_0_5X: resolution = 0.6720; break; + } + break; + case VEML6046_IT_6_25MS: + switch (gain) { + case VEML6046_GAIN_2X: resolution = 0.3360; break; + case VEML6046_GAIN_1X: resolution = 0.6720; break; + case VEML6046_GAIN_0_66X: resolution = 1.0182; break; + case VEML6046_GAIN_0_5X: resolution = 1.3440; break; + } + break; + case VEML6046_IT_3_125MS: + switch (gain) { + case VEML6046_GAIN_2X: resolution = 0.6720; break; + case VEML6046_GAIN_1X: resolution = 1.3440; break; + case VEML6046_GAIN_0_66X: resolution = 2.0364; break; + case VEML6046_GAIN_0_5X: resolution = 2.6880; break; + } + break; + } + } + + return green_count * resolution; } \ No newline at end of file diff --git a/Adafruit_VEML6046.h b/Adafruit_VEML6046.h index a29d7a7..ccc43c6 100644 --- a/Adafruit_VEML6046.h +++ b/Adafruit_VEML6046.h @@ -125,6 +125,8 @@ class Adafruit_VEML6046 { bool getData(uint16_t* r, uint16_t* g, uint16_t* b, uint16_t* ir); + float calculateLux(uint16_t green_count); + private: Adafruit_I2CDevice* i2c_dev; ///< Pointer to I2C bus interface }; diff --git a/examples/test_veml6046/test_veml6046.ino b/examples/test_veml6046/test_veml6046.ino index b0cab97..621feda 100644 --- a/examples/test_veml6046/test_veml6046.ino +++ b/examples/test_veml6046/test_veml6046.ino @@ -8,6 +8,7 @@ #include "Adafruit_VEML6046.h" Adafruit_VEML6046 veml = Adafruit_VEML6046(); +uint16_t sample_delay_ms = 30; // Will be calculated in setup void setup() { Serial.begin(115200); @@ -111,12 +112,111 @@ void setup() { bool green_int_enabled = veml.getGreenIntEnabled(); Serial.print(F("Green interrupt enabled: ")); Serial.println(green_int_enabled ? F("Yes") : F("No")); + + // Test RGB gain setter/getter + Serial.println(F("Setting RGB gain to 1x")); + if (veml.setRGBGain(VEML6046_GAIN_1X)) { + Serial.println(F("RGB gain set successfully")); + } else { + Serial.println(F("Failed to set RGB gain")); + } + + // Read back and display current RGB gain + veml6046_gain_t current_gain = veml.getRGBGain(); + Serial.print(F("Current RGB gain: ")); + switch (current_gain) { + case VEML6046_GAIN_1X: + Serial.println(F("1x")); + break; + case VEML6046_GAIN_2X: + Serial.println(F("2x")); + break; + case VEML6046_GAIN_0_66X: + Serial.println(F("0.66x")); + break; + case VEML6046_GAIN_0_5X: + Serial.println(F("0.5x")); + break; + default: + Serial.println(F("Unknown")); + break; + } + + // Test interrupt persistence setter/getter + Serial.println(F("Setting interrupt persistence to 1")); + if (veml.setIntPersistence(VEML6046_PERS_1)) { + Serial.println(F("Interrupt persistence set successfully")); + } else { + Serial.println(F("Failed to set interrupt persistence")); + } + + // Read back and display current persistence + veml6046_persistence_t current_pers = veml.getIntPersistence(); + Serial.print(F("Current interrupt persistence: ")); + switch (current_pers) { + case VEML6046_PERS_1: + Serial.println(F("1 time")); + break; + case VEML6046_PERS_2: + Serial.println(F("2 times")); + break; + case VEML6046_PERS_4: + Serial.println(F("4 times")); + break; + case VEML6046_PERS_8: + Serial.println(F("8 times")); + break; + default: + Serial.println(F("Unknown")); + break; + } + + // Test green threshold setter/getter + Serial.println(F("Setting green thresholds: low=1000, high=10000")); + if (veml.setGreenThresholdLow(1000)) { + Serial.println(F("Green low threshold set successfully")); + } else { + Serial.println(F("Failed to set green low threshold")); + } + + if (veml.setGreenThresholdHigh(10000)) { + Serial.println(F("Green high threshold set successfully")); + } else { + Serial.println(F("Failed to set green high threshold")); + } + + // Read back and display current thresholds + uint16_t low_thresh = veml.getGreenThresholdLow(); + uint16_t high_thresh = veml.getGreenThresholdHigh(); + Serial.print(F("Current green thresholds - Low: ")); + Serial.print(low_thresh); + Serial.print(F(", High: ")); + Serial.println(high_thresh); + + // Calculate optimal delay based on current integration time + 5ms buffer + current_it = veml.getIntegrationTime(); + sample_delay_ms = 5; // Base 5ms buffer + switch (current_it) { + case VEML6046_IT_3_125MS: sample_delay_ms += 4; break; // 3.125ms rounded up + case VEML6046_IT_6_25MS: sample_delay_ms += 7; break; // 6.25ms rounded up + case VEML6046_IT_12_5MS: sample_delay_ms += 13; break; // 12.5ms rounded up + case VEML6046_IT_25MS: sample_delay_ms += 25; break; + case VEML6046_IT_50MS: sample_delay_ms += 50; break; + case VEML6046_IT_100MS: sample_delay_ms += 100; break; + case VEML6046_IT_200MS: sample_delay_ms += 200; break; + case VEML6046_IT_400MS: sample_delay_ms += 400; break; + default: sample_delay_ms += 25; break; // Default fallback + } + Serial.print(F("Using sample delay: ")); + Serial.print(sample_delay_ms); + Serial.println(F("ms")); } void loop() { // Read RGBIR data in continuous mode uint16_t r, g, b, ir; if (veml.getData(&r, &g, &b, &ir)) { + float lux = veml.calculateLux(g); Serial.print(F("R: ")); Serial.print(r); Serial.print(F(" G: ")); @@ -124,10 +224,17 @@ void loop() { Serial.print(F(" B: ")); Serial.print(b); Serial.print(F(" IR: ")); - Serial.println(ir); + Serial.print(ir); + Serial.print(F(" Lux: ")); + Serial.println(lux, 2); } else { Serial.println(F("Failed to read data")); } - delay(1000); + // If in forced mode, trigger next reading + if (veml.getRGBModeForced()) { + veml.RGBTrigger(); + } + + delay(sample_delay_ms); } \ No newline at end of file