Add calculateLux function and improve test coverage
- Add calculateLux() function using datasheet resolution tables - Support both 1/2 PD and 2/2 PD configurations - Add RGB gain and interrupt persistence tests to example - Add green threshold setter/getter tests - Optimize loop delay based on integration time + 5ms buffer - Add lux calculation display in test output 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
18f7d1812a
commit
77715e7a5d
3 changed files with 267 additions and 2 deletions
|
|
@ -399,3 +399,159 @@ bool Adafruit_VEML6046::getData(uint16_t* r, uint16_t* g, uint16_t* b,
|
||||||
|
|
||||||
return true;
|
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;
|
||||||
|
}
|
||||||
|
|
@ -125,6 +125,8 @@ class Adafruit_VEML6046 {
|
||||||
|
|
||||||
bool getData(uint16_t* r, uint16_t* g, uint16_t* b, uint16_t* ir);
|
bool getData(uint16_t* r, uint16_t* g, uint16_t* b, uint16_t* ir);
|
||||||
|
|
||||||
|
float calculateLux(uint16_t green_count);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Adafruit_I2CDevice* i2c_dev; ///< Pointer to I2C bus interface
|
Adafruit_I2CDevice* i2c_dev; ///< Pointer to I2C bus interface
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include "Adafruit_VEML6046.h"
|
#include "Adafruit_VEML6046.h"
|
||||||
|
|
||||||
Adafruit_VEML6046 veml = Adafruit_VEML6046();
|
Adafruit_VEML6046 veml = Adafruit_VEML6046();
|
||||||
|
uint16_t sample_delay_ms = 30; // Will be calculated in setup
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
|
|
@ -111,12 +112,111 @@ void setup() {
|
||||||
bool green_int_enabled = veml.getGreenIntEnabled();
|
bool green_int_enabled = veml.getGreenIntEnabled();
|
||||||
Serial.print(F("Green interrupt enabled: "));
|
Serial.print(F("Green interrupt enabled: "));
|
||||||
Serial.println(green_int_enabled ? F("Yes") : F("No"));
|
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() {
|
void loop() {
|
||||||
// Read RGBIR data in continuous mode
|
// Read RGBIR data in continuous mode
|
||||||
uint16_t r, g, b, ir;
|
uint16_t r, g, b, ir;
|
||||||
if (veml.getData(&r, &g, &b, &ir)) {
|
if (veml.getData(&r, &g, &b, &ir)) {
|
||||||
|
float lux = veml.calculateLux(g);
|
||||||
Serial.print(F("R: "));
|
Serial.print(F("R: "));
|
||||||
Serial.print(r);
|
Serial.print(r);
|
||||||
Serial.print(F(" G: "));
|
Serial.print(F(" G: "));
|
||||||
|
|
@ -124,10 +224,17 @@ void loop() {
|
||||||
Serial.print(F(" B: "));
|
Serial.print(F(" B: "));
|
||||||
Serial.print(b);
|
Serial.print(b);
|
||||||
Serial.print(F(" IR: "));
|
Serial.print(F(" IR: "));
|
||||||
Serial.println(ir);
|
Serial.print(ir);
|
||||||
|
Serial.print(F(" Lux: "));
|
||||||
|
Serial.println(lux, 2);
|
||||||
} else {
|
} else {
|
||||||
Serial.println(F("Failed to read data"));
|
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);
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue