[P168] Add VEML6030/VEML7700 Light/Lux sensor

This commit is contained in:
Ton Huisman
2024-05-18 16:51:42 +02:00
parent ea9adbb083
commit cecf4b76ee
13 changed files with 1205 additions and 1 deletions
+462
View File
@@ -0,0 +1,462 @@
/*!
* @file Adafruit_VEML7700.cpp
*
* @mainpage Adafruit VEML7700 I2C Lux Sensor
*
* @section intro_sec Introduction
*
* I2C Driver for the VEML7700 I2C Lux sensor
*
* This is a library for the Adafruit VEML7700 breakout:
* http://www.adafruit.com/
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing products from
* Adafruit!
*
* @section author Author
*
* Limor Fried (Adafruit Industries)
*
* @section license License
*
* BSD (see license.txt)
*
* @section HISTORY
*
* v1.0 - First release
*/
#include "Adafruit_VEML7700.h"
/*!
* @brief Instantiates a new VEML7700 class
*/
Adafruit_VEML7700::Adafruit_VEML7700(void) {}
/*!
* @brief Sets up the hardware for talking to the VEML7700
* @param theWire An optional pointer to an I2C interface
* @return True if initialization was successful, otherwise false.
*/
bool Adafruit_VEML7700::begin(TwoWire *theWire) {
i2c_dev = new Adafruit_I2CDevice(VEML7700_I2CADDR_DEFAULT, theWire);
if (!i2c_dev->begin()) {
return false;
}
ALS_Config =
new Adafruit_I2CRegister(i2c_dev, VEML7700_ALS_CONFIG, 2, LSBFIRST);
ALS_HighThreshold = new Adafruit_I2CRegister(
i2c_dev, VEML7700_ALS_THREHOLD_HIGH, 2, LSBFIRST);
ALS_LowThreshold =
new Adafruit_I2CRegister(i2c_dev, VEML7700_ALS_THREHOLD_LOW, 2, LSBFIRST);
Power_Saving =
new Adafruit_I2CRegister(i2c_dev, VEML7700_ALS_POWER_SAVE, 2, LSBFIRST);
ALS_Data = new Adafruit_I2CRegister(i2c_dev, VEML7700_ALS_DATA, 2, LSBFIRST);
White_Data =
new Adafruit_I2CRegister(i2c_dev, VEML7700_WHITE_DATA, 2, LSBFIRST);
Interrupt_Status =
new Adafruit_I2CRegister(i2c_dev, VEML7700_INTERRUPTSTATUS, 2, LSBFIRST);
ALS_Shutdown =
new Adafruit_I2CRegisterBits(ALS_Config, 1, 0); // # bits, bit_shift
ALS_Interrupt_Enable = new Adafruit_I2CRegisterBits(ALS_Config, 1, 1);
ALS_Persistence = new Adafruit_I2CRegisterBits(ALS_Config, 2, 4);
ALS_Integration_Time = new Adafruit_I2CRegisterBits(ALS_Config, 4, 6);
ALS_Gain = new Adafruit_I2CRegisterBits(ALS_Config, 2, 11);
PowerSave_Enable = new Adafruit_I2CRegisterBits(Power_Saving, 1, 0);
PowerSave_Mode = new Adafruit_I2CRegisterBits(Power_Saving, 2, 1);
enable(false);
interruptEnable(false);
setPersistence(VEML7700_PERS_1);
setGain(VEML7700_GAIN_1_8);
setIntegrationTime(VEML7700_IT_100MS);
powerSaveEnable(false);
enable(true);
lastRead = millis();
return true;
}
/*!
* @brief Read the calibrated lux value. See app note lux table on page 5
* @param method Lux comptation method to use. One of
* @returns Floating point Lux data
*/
float Adafruit_VEML7700::readLux(luxMethod method) {
bool wait = true;
switch (method) {
case VEML_LUX_NORMAL_NOWAIT:
wait = false;
VEML7700_FALLTHROUGH
case VEML_LUX_NORMAL:
return computeLux(readALS(wait));
case VEML_LUX_CORRECTED_NOWAIT:
wait = false;
VEML7700_FALLTHROUGH
case VEML_LUX_CORRECTED:
return computeLux(readALS(wait), true);
case VEML_LUX_AUTO:
return autoLux();
default:
return -1;
}
}
/*!
* @brief Read the raw ALS data
* @param wait If false (default), read out measurement with no delay. If
* true, wait as need based on integration time before reading out measurement
* results.
* @returns 16-bit data value from the ALS register
*/
uint16_t Adafruit_VEML7700::readALS(bool wait) {
if (wait)
readWait();
lastRead = millis();
return ALS_Data->read();
}
/*!
* @brief Read the raw white light data
* @param wait If false (default), read out measurement with no delay. If
* true, wait as need based on integration time before reading out measurement
* results.
* @returns 16-bit data value from the WHITE register
*/
uint16_t Adafruit_VEML7700::readWhite(bool wait) {
if (wait)
readWait();
lastRead = millis();
return White_Data->read();
}
/*!
* @brief Enable or disable the sensor
* @param enable The flag to enable/disable
*/
void Adafruit_VEML7700::enable(bool enable) {
ALS_Shutdown->write(!enable);
// From app note:
// '''
// When activating the sensor, set bit 0 of the command register
// to “0” with a wait time of 2.5 ms before the first measurement
// is needed, allowing for the correct start of the signal
// processor and oscillator.
// '''
if (enable)
delay(5); // doubling 2.5ms spec to be sure
}
/*!
* @brief Ask if the interrupt is enabled
* @returns True if enabled, false otherwise
*/
bool Adafruit_VEML7700::enabled(void) { return !ALS_Shutdown->read(); }
/*!
* @brief Enable or disable the interrupt
* @param enable The flag to enable/disable
*/
void Adafruit_VEML7700::interruptEnable(bool enable) {
ALS_Interrupt_Enable->write(enable);
}
/*!
* @brief Ask if the interrupt is enabled
* @returns True if enabled, false otherwise
*/
bool Adafruit_VEML7700::interruptEnabled(void) {
return ALS_Interrupt_Enable->read();
}
/*!
* @brief Set the ALS IRQ persistence setting
* @param pers Persistence constant, can be VEML7700_PERS_1, VEML7700_PERS_2,
* VEML7700_PERS_4 or VEML7700_PERS_8
*/
void Adafruit_VEML7700::setPersistence(uint8_t pers) {
ALS_Persistence->write(pers);
}
/*!
* @brief Get the ALS IRQ persistence setting
* @returns Persistence constant, can be VEML7700_PERS_1, VEML7700_PERS_2,
* VEML7700_PERS_4 or VEML7700_PERS_8
*/
uint8_t Adafruit_VEML7700::getPersistence(void) {
return ALS_Persistence->read();
}
/*!
* @brief Set ALS integration time
* @param it Can be VEML7700_IT_100MS, VEML7700_IT_200MS, VEML7700_IT_400MS,
* VEML7700_IT_800MS, VEML7700_IT_50MS or VEML7700_IT_25MS
* @param wait Waits to insure old integration time cycle has completed. This
* is a blocking delay. If disabled by passing false, user code must insure a
* new reading is not done before old integration cycle completes.
*/
void Adafruit_VEML7700::setIntegrationTime(uint8_t it, bool wait) {
// save current integration time
int flushDelay = wait ? getIntegrationTimeValue() : 0;
// set new integration time
ALS_Integration_Time->write(it);
// pause old integration time to insure sensor cycle has completed
delay(flushDelay);
// reset counter
lastRead = millis();
}
/*!
* @brief Get ALS integration time setting
* @returns IT index, can be VEML7700_IT_100MS, VEML7700_IT_200MS,
* VEML7700_IT_400MS, VEML7700_IT_800MS, VEML7700_IT_50MS or VEML7700_IT_25MS
*/
uint8_t Adafruit_VEML7700::getIntegrationTime(void) {
return ALS_Integration_Time->read();
}
/*!
* @brief Get ALS integration time value
* @returns ALS integration time in milliseconds
*/
int Adafruit_VEML7700::getIntegrationTimeValue(void) {
switch (getIntegrationTime()) {
case VEML7700_IT_25MS:
return 25;
case VEML7700_IT_50MS:
return 50;
case VEML7700_IT_100MS:
return 100;
case VEML7700_IT_200MS:
return 200;
case VEML7700_IT_400MS:
return 400;
case VEML7700_IT_800MS:
return 800;
default:
return -1;
}
}
/*!
* @brief Set ALS gain
* @param gain Can be VEML7700_GAIN_1, VEML7700_GAIN_2, VEML7700_GAIN_1_8 or
* VEML7700_GAIN_1_4
*/
void Adafruit_VEML7700::setGain(uint8_t gain) {
ALS_Gain->write(gain);
lastRead = millis(); // reset
}
/*!
* @brief Get ALS gain setting
* @returns Gain index, can be VEML7700_GAIN_1, VEML7700_GAIN_2,
* VEML7700_GAIN_1_8 or VEML7700_GAIN_1_4
*/
uint8_t Adafruit_VEML7700::getGain(void) { return ALS_Gain->read(); }
/*!
* @brief Get ALS gain value
* @returns Actual gain value as float
*/
float Adafruit_VEML7700::getGainValue(void) {
switch (getGain()) {
case VEML7700_GAIN_1_8:
return 0.125;
case VEML7700_GAIN_1_4:
return 0.25;
case VEML7700_GAIN_1:
return 1;
case VEML7700_GAIN_2:
return 2;
default:
return -1;
}
}
/*!
* @brief Enable power save mode
* @param enable True if power save should be enabled
*/
void Adafruit_VEML7700::powerSaveEnable(bool enable) {
PowerSave_Enable->write(enable);
}
/*!
* @brief Check if power save mode is enabled
* @returns True if power save is enabled
*/
bool Adafruit_VEML7700::powerSaveEnabled(void) {
return PowerSave_Enable->read();
}
/*!
* @brief Assign the power save register data
* @param mode The 16-bit data to write to VEML7700_ALS_POWER_SAVE
*/
void Adafruit_VEML7700::setPowerSaveMode(uint8_t mode) {
PowerSave_Mode->write(mode);
}
/*!
* @brief Retrieve the power save register data
* @return 16-bit data from VEML7700_ALS_POWER_SAVE
*/
uint8_t Adafruit_VEML7700::getPowerSaveMode(void) {
return PowerSave_Mode->read();
}
/*!
* @brief Assign the low threshold register data
* @param value The 16-bit data to write to VEML7700_ALS_THREHOLD_LOW
*/
void Adafruit_VEML7700::setLowThreshold(uint16_t value) {
ALS_LowThreshold->write(value);
}
/*!
* @brief Retrieve the low threshold register data
* @return 16-bit data from VEML7700_ALS_THREHOLD_LOW
*/
uint16_t Adafruit_VEML7700::getLowThreshold(void) {
return ALS_LowThreshold->read();
}
/*!
* @brief Assign the high threshold register data
* @param value The 16-bit data to write to VEML7700_ALS_THREHOLD_HIGH
*/
void Adafruit_VEML7700::setHighThreshold(uint16_t value) {
ALS_HighThreshold->write(value);
}
/*!
* @brief Retrieve the high threshold register data
* @return 16-bit data from VEML7700_ALS_THREHOLD_HIGH
*/
uint16_t Adafruit_VEML7700::getHighThreshold(void) {
return ALS_HighThreshold->read();
}
/*!
* @brief Retrieve the interrupt status register data
* @return 16-bit data from VEML7700_INTERRUPTSTATUS
*/
uint16_t Adafruit_VEML7700::interruptStatus(void) {
return Interrupt_Status->read();
}
/*!
* @brief Determines resolution for current gain and integration time
* settings.
*/
float Adafruit_VEML7700::getResolution(void) {
return MAX_RES * (IT_MAX / getIntegrationTimeValue()) *
(GAIN_MAX / getGainValue());
}
/*!
* @brief Copmute lux from ALS reading.
* @param rawALS raw ALS register value
* @param corrected if true, apply non-linear correction
* @return lux value
*/
float Adafruit_VEML7700::computeLux(uint16_t rawALS, bool corrected) {
float lux = getResolution() * rawALS;
if (corrected)
lux = (((6.0135e-13 * lux - 9.3924e-9) * lux + 8.1488e-5) * lux + 1.0023) *
lux;
return lux;
}
void Adafruit_VEML7700::readWait(void) {
// From app note:
// '''
// Without using the power-saving feature (PSM_EN = 0), the
// controller has to wait before reading out measurement results,
// at least for the programmed integration time. For example,
// for ALS_IT = 100 ms a wait time of ≥ 100 ms is needed.
// '''
// Based on testing, it needs more. So doubling to be sure.
unsigned long timeToWait = 2 * getIntegrationTimeValue(); // see above
unsigned long timeWaited = millis() - lastRead;
if (timeWaited < timeToWait)
delay(timeToWait - timeWaited);
}
bool Adafruit_VEML7700::readReady(void) {
// From app note:
// '''
// Without using the power-saving feature (PSM_EN = 0), the
// controller has to wait before reading out measurement results,
// at least for the programmed integration time. For example,
// for ALS_IT = 100 ms a wait time of ≥ 100 ms is needed.
// '''
// Based on testing, it needs more. So doubling to be sure.
unsigned long timeToWait = 2 * getIntegrationTimeValue(); // see above
unsigned long timeWaited = millis() - lastRead;
return (timeWaited >= timeToWait);
}
/*!
* @brief Implemenation of App Note "Designing the VEML7700 Into an
* Application", Vishay Document Number: 84323, Fig. 24 Flow Chart. This will
* automatically adjust gain and integration time as needed to obtain a good raw
* count value. Additionally, a non-linear correction is applied if needed.
*/
float Adafruit_VEML7700::autoLux(void) {
const uint8_t gains[] = {VEML7700_GAIN_1_8, VEML7700_GAIN_1_4,
VEML7700_GAIN_1, VEML7700_GAIN_2};
const uint8_t intTimes[] = {VEML7700_IT_25MS, VEML7700_IT_50MS,
VEML7700_IT_100MS, VEML7700_IT_200MS,
VEML7700_IT_400MS, VEML7700_IT_800MS};
uint8_t gainIndex = 0; // start with ALS gain = 1/8
uint8_t itIndex = 2; // start with ALS integration time = 100ms
bool useCorrection = false; // flag for non-linear correction
setGain(gains[gainIndex]);
setIntegrationTime(intTimes[itIndex]);
uint16_t ALS = readALS(true);
// Serial.println("** AUTO LUX DEBUG **");
// Serial.print("ALS initial = "); Serial.println(ALS);
if (ALS <= 100) {
// increase first gain and then integration time as needed
// compute lux using simple linear formula
while ((ALS <= 100) && !((gainIndex == 3) && (itIndex == 5))) {
if (gainIndex < 3) {
setGain(gains[++gainIndex]);
} else if (itIndex < 5) {
setIntegrationTime(intTimes[++itIndex]);
}
ALS = readALS(true);
// Serial.print("ALS low lux = "); Serial.println(ALS);
}
} else {
// decrease integration time as needed
// compute lux using non-linear correction
useCorrection = true;
while ((ALS > 10000) && (itIndex > 0)) {
setIntegrationTime(intTimes[--itIndex]);
ALS = readALS(true);
// Serial.print("ALS hi lux = "); Serial.println(ALS);
}
}
// Serial.println("** AUTO LUX DEBUG **");
return computeLux(ALS, useCorrection);
}
+136
View File
@@ -0,0 +1,136 @@
/*!
* @file Adafruit_VEML7700.h
*
* I2C Driver for VEML7700 Lux sensor
*
* This is a library for the Adafruit VEML7700 breakout:
* http://www.adafruit.com/
*
* Adafruit invests time and resources providing this open source code,
*please support Adafruit and open-source hardware by purchasing products from
* Adafruit!
*
*
* BSD license (see license.txt)
*/
#ifndef _ADAFRUIT_VEML7700_H
#define _ADAFRUIT_VEML7700_H
#include "Arduino.h"
#include <Adafruit_I2CDevice.h>
#include <Adafruit_I2CRegister.h>
#include <Wire.h>
#define VEML7700_I2CADDR_DEFAULT 0x10 ///< I2C address
#define VEML7700_ALS_CONFIG 0x00 ///< Light configuration register
#define VEML7700_ALS_THREHOLD_HIGH 0x01 ///< Light high threshold for irq
#define VEML7700_ALS_THREHOLD_LOW 0x02 ///< Light low threshold for irq
#define VEML7700_ALS_POWER_SAVE 0x03 ///< Power save regiester
#define VEML7700_ALS_DATA 0x04 ///< The light data output
#define VEML7700_WHITE_DATA 0x05 ///< The white light data output
#define VEML7700_INTERRUPTSTATUS 0x06 ///< What IRQ (if any)
#define VEML7700_INTERRUPT_HIGH 0x4000 ///< Interrupt status for high threshold
#define VEML7700_INTERRUPT_LOW 0x8000 ///< Interrupt status for low threshold
#define VEML7700_GAIN_1 0x00 ///< ALS gain 1x
#define VEML7700_GAIN_2 0x01 ///< ALS gain 2x
#define VEML7700_GAIN_1_8 0x02 ///< ALS gain 1/8x
#define VEML7700_GAIN_1_4 0x03 ///< ALS gain 1/4x
#define VEML7700_IT_100MS 0x00 ///< ALS intetgration time 100ms
#define VEML7700_IT_200MS 0x01 ///< ALS intetgration time 200ms
#define VEML7700_IT_400MS 0x02 ///< ALS intetgration time 400ms
#define VEML7700_IT_800MS 0x03 ///< ALS intetgration time 800ms
#define VEML7700_IT_50MS 0x08 ///< ALS intetgration time 50ms
#define VEML7700_IT_25MS 0x0C ///< ALS intetgration time 25ms
#define VEML7700_PERS_1 0x00 ///< ALS irq persistence 1 sample
#define VEML7700_PERS_2 0x01 ///< ALS irq persistence 2 samples
#define VEML7700_PERS_4 0x02 ///< ALS irq persistence 4 samples
#define VEML7700_PERS_8 0x03 ///< ALS irq persistence 8 samples
#define VEML7700_POWERSAVE_MODE1 0x00 ///< Power saving mode 1
#define VEML7700_POWERSAVE_MODE2 0x01 ///< Power saving mode 2
#define VEML7700_POWERSAVE_MODE3 0x02 ///< Power saving mode 3
#define VEML7700_POWERSAVE_MODE4 0x03 ///< Power saving mode 4
/*!
* @brief Used to explicitly annotate switch case fall throughs.
* Newer compilers will throw a warning otherwise.
*/
#if defined(__GNUC__) && __GNUC__ >= 7
#define VEML7700_FALLTHROUGH __attribute__((fallthrough));
#else
#define VEML7700_FALLTHROUGH
#endif
/** Options for lux reading method */
typedef enum {
VEML_LUX_NORMAL,
VEML_LUX_CORRECTED,
VEML_LUX_AUTO,
VEML_LUX_NORMAL_NOWAIT,
VEML_LUX_CORRECTED_NOWAIT
} luxMethod;
/*!
* @brief Class that stores state and functions for interacting with
* VEML7700 Light Sensor
*/
class Adafruit_VEML7700 {
public:
Adafruit_VEML7700();
bool begin(TwoWire *theWire = &Wire);
void enable(bool enable);
bool enabled(void);
void interruptEnable(bool enable);
bool interruptEnabled(void);
void setPersistence(uint8_t pers);
uint8_t getPersistence(void);
void setIntegrationTime(uint8_t it, bool wait = true);
uint8_t getIntegrationTime(void);
int getIntegrationTimeValue(void);
void setGain(uint8_t gain);
uint8_t getGain(void);
float getGainValue(void);
void powerSaveEnable(bool enable);
bool powerSaveEnabled(void);
void setPowerSaveMode(uint8_t mode);
uint8_t getPowerSaveMode(void);
void setLowThreshold(uint16_t value);
uint16_t getLowThreshold(void);
void setHighThreshold(uint16_t value);
uint16_t getHighThreshold(void);
uint16_t interruptStatus(void);
uint16_t readALS(bool wait = false);
uint16_t readWhite(bool wait = false);
float readLux(luxMethod method = VEML_LUX_NORMAL);
bool readReady(void); // 2024-05-18 tonhuisman: Added for ESPEasy
private:
const float MAX_RES = 0.0036;
const float GAIN_MAX = 2;
const float IT_MAX = 800;
float getResolution(void);
float computeLux(uint16_t rawALS, bool corrected = false);
float autoLux(void);
void readWait(void);
unsigned long lastRead;
Adafruit_I2CRegister *ALS_Config, *ALS_Data, *White_Data, *ALS_HighThreshold,
*ALS_LowThreshold, *Power_Saving, *Interrupt_Status;
Adafruit_I2CRegisterBits *ALS_Shutdown, *ALS_Interrupt_Enable,
*ALS_Persistence, *ALS_Integration_Time, *ALS_Gain, *PowerSave_Enable,
*PowerSave_Mode;
Adafruit_I2CDevice *i2c_dev;
};
#endif
+16
View File
@@ -0,0 +1,16 @@
Adafruit_VEML7700 [![Build Status](https://github.com/adafruit/Adafruit_VEML7700/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_VEML7700/actions)
================
This is the Adafruit VEML7700 Lux sensor library
Tested and works great with the [Adafruit VEML7700 Breakout Board](http://www.adafruit.com/)
This chip uses I2C to communicate, 2 pins are required to interface
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Kevin Townsend/Limor Fried for Adafruit Industries.
BSD license, check license.txt for more information
All text above must be included in any redistribution
@@ -0,0 +1,40 @@
#include <Adafruit_SSD1306.h>
#include "Adafruit_VEML7700.h"
Adafruit_VEML7700 veml = Adafruit_VEML7700();
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &Wire);
void setup() {
Serial.begin(115200);
//while (!Serial);
Serial.println("VEML7700 demo");
if (veml.begin()) {
Serial.println("Found a VEML7700 sensor");
} else {
Serial.println("No sensor found ... check your wiring?");
while (1);
}
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.display();
delay(500); // Pause for 2 seconds
display.setTextSize(2);
display.setTextColor(WHITE);
veml.setGain(VEML7700_GAIN_1);
veml.setIntegrationTime(VEML7700_IT_100MS);
}
void loop() {
display.clearDisplay();
display.setCursor(0,8);
display.print("Lux "); display.println(veml.readLux());
display.display();
delay(50);
}
@@ -0,0 +1,52 @@
/* VEML7700 Auto Lux Example
*
* This example sketch demonstrates reading lux using the automatic
* method which adjusts gain and integration time as needed to obtain
* a good reading. A non-linear correction is also applied if needed.
*
* See Vishy App Note "Designing the VEML7700 Into an Application"
* Vishay Document Number: 84323, Fig. 24 Flow Chart
*/
#include "Adafruit_VEML7700.h"
Adafruit_VEML7700 veml = Adafruit_VEML7700();
void setup() {
Serial.begin(115200);
while (!Serial) { delay(10); }
Serial.println("Adafruit VEML7700 Auto Lux Test");
if (!veml.begin()) {
Serial.println("Sensor not found");
while (1);
}
Serial.println("Sensor found");
}
void loop() {
// to read lux using automatic method, specify VEML_LUX_AUTO
float lux = veml.readLux(VEML_LUX_AUTO);
Serial.println("------------------------------------");
Serial.print("Lux = "); Serial.println(lux);
Serial.println("Settings used for reading:");
Serial.print(F("Gain: "));
switch (veml.getGain()) {
case VEML7700_GAIN_1: Serial.println("1"); break;
case VEML7700_GAIN_2: Serial.println("2"); break;
case VEML7700_GAIN_1_4: Serial.println("1/4"); break;
case VEML7700_GAIN_1_8: Serial.println("1/8"); break;
}
Serial.print(F("Integration Time (ms): "));
switch (veml.getIntegrationTime()) {
case VEML7700_IT_25MS: Serial.println("25"); break;
case VEML7700_IT_50MS: Serial.println("50"); break;
case VEML7700_IT_100MS: Serial.println("100"); break;
case VEML7700_IT_200MS: Serial.println("200"); break;
case VEML7700_IT_400MS: Serial.println("400"); break;
case VEML7700_IT_800MS: Serial.println("800"); break;
}
delay(1000);
}
@@ -0,0 +1,59 @@
#include "Adafruit_VEML7700.h"
Adafruit_VEML7700 veml = Adafruit_VEML7700();
void setup() {
Serial.begin(115200);
while (!Serial) { delay(10); }
Serial.println("Adafruit VEML7700 Test");
if (!veml.begin()) {
Serial.println("Sensor not found");
while (1);
}
Serial.println("Sensor found");
// == OPTIONAL =====
// Can set non-default gain and integration time to
// adjust for different lighting conditions.
// =================
// veml.setGain(VEML7700_GAIN_1_8);
// veml.setIntegrationTime(VEML7700_IT_100MS);
Serial.print(F("Gain: "));
switch (veml.getGain()) {
case VEML7700_GAIN_1: Serial.println("1"); break;
case VEML7700_GAIN_2: Serial.println("2"); break;
case VEML7700_GAIN_1_4: Serial.println("1/4"); break;
case VEML7700_GAIN_1_8: Serial.println("1/8"); break;
}
Serial.print(F("Integration Time (ms): "));
switch (veml.getIntegrationTime()) {
case VEML7700_IT_25MS: Serial.println("25"); break;
case VEML7700_IT_50MS: Serial.println("50"); break;
case VEML7700_IT_100MS: Serial.println("100"); break;
case VEML7700_IT_200MS: Serial.println("200"); break;
case VEML7700_IT_400MS: Serial.println("400"); break;
case VEML7700_IT_800MS: Serial.println("800"); break;
}
veml.setLowThreshold(10000);
veml.setHighThreshold(20000);
veml.interruptEnable(true);
}
void loop() {
Serial.print("raw ALS: "); Serial.println(veml.readALS());
Serial.print("raw white: "); Serial.println(veml.readWhite());
Serial.print("lux: "); Serial.println(veml.readLux());
uint16_t irq = veml.interruptStatus();
if (irq & VEML7700_INTERRUPT_LOW) {
Serial.println("** Low threshold");
}
if (irq & VEML7700_INTERRUPT_HIGH) {
Serial.println("** High threshold");
}
delay(500);
}
+10
View File
@@ -0,0 +1,10 @@
name=Adafruit VEML7700 Library
version=2.1.6
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=Arduino library for the VEML7700 sensors in the Adafruit shop
paragraph=Arduino library for the VEML7700 sensors in the Adafruit shop
category=Sensors
url=https://github.com/adafruit/Adafruit_VEML7700
architectures=*
depends=Adafruit BusIO, Adafruit SSD1306
+26
View File
@@ -0,0 +1,26 @@
Software License Agreement (BSD License)
Copyright (c) 2012, Adafruit Industries
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+246
View File
@@ -0,0 +1,246 @@
#include "_Plugin_Helper.h"
#ifdef USES_P168
// #######################################################################################################
// ####################### Plugin 168: Light/Lux - VEML6030/VEML7700 I2C Light sensor ####################
// #######################################################################################################
/**
* 2024-05-18 tonhuisman: Implement AutoLux feature, and Get Config Value for automatically determined gain and integration
* 2024-05-16 tonhuisman: Start plugin for VEML6030/VEML7700 I2C Light sensor, using a slightly adjusted Adafruit library:
* https://github.com/adafruit/Adafruit_VEML7700
**/
# define PLUGIN_168
# define PLUGIN_ID_168 168
# define PLUGIN_NAME_168 "Light/Lux - VEML6030/VEML7700"
# define PLUGIN_VALUENAME1_168 "Lux"
# define PLUGIN_VALUENAME2_168 "White"
# define PLUGIN_VALUENAME3_168 "Raw"
# include "./src/PluginStructs/P168_data_struct.h"
boolean Plugin_168(uint8_t function, struct EventStruct *event, String& string)
{
boolean success = false;
switch (function)
{
case PLUGIN_DEVICE_ADD:
{
Device[++deviceCount].Number = PLUGIN_ID_168;
Device[deviceCount].Type = DEVICE_TYPE_I2C;
Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE;
Device[deviceCount].Ports = 0;
Device[deviceCount].FormulaOption = true;
Device[deviceCount].ValueCount = 3;
Device[deviceCount].SendDataOption = true;
Device[deviceCount].TimerOption = true;
Device[deviceCount].GlobalSyncOption = true;
Device[deviceCount].PluginStats = true;
break;
}
case PLUGIN_GET_DEVICENAME:
{
string = F(PLUGIN_NAME_168);
break;
}
case PLUGIN_GET_DEVICEVALUENAMES:
{
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_168));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_168));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_168));
break;
}
case PLUGIN_I2C_HAS_ADDRESS:
case PLUGIN_WEBFORM_SHOW_I2C_PARAMS:
{
const uint8_t i2cAddressValues[] = { 0x10, 0x48 };
if (PLUGIN_WEBFORM_SHOW_I2C_PARAMS == function) {
addFormSelectorI2C(F("i2c_addr"), 2, i2cAddressValues, P168_I2C_ADDRESS);
# ifndef BUILD_NO_DEBUG
addFormNote(F("Address 0x48 only supported by VEML6030, ADDR -> VCC"));
# endif // ifndef BUILD_NO_DEBUG
} else {
success = intArrayContains(2, i2cAddressValues, event->Par1);
}
break;
}
# if FEATURE_I2C_GET_ADDRESS
case PLUGIN_I2C_GET_ADDRESS:
{
event->Par1 = P168_I2C_ADDRESS;
success = true;
break;
}
# endif // if FEATURE_I2C_GET_ADDRESS
case PLUGIN_SET_DEFAULTS:
{
P168_READLUX_MODE = VEML_LUX_AUTO;
P168_PSM_MODE = static_cast<int>(P168_power_save_mode_e::Disabled);
ExtraTaskSettings.TaskDeviceValueDecimals[1] = 0; // White
ExtraTaskSettings.TaskDeviceValueDecimals[2] = 0; // Raw
success = true;
break;
}
case PLUGIN_WEBFORM_LOAD:
{
{
const __FlashStringHelper *readMethod[] = {
F("Normal"),
F("Corrected"),
F("Auto"),
F("Normal (no wait)"),
F("Corrected (no wait)"),
};
const int readMethodOptions[] = {
VEML_LUX_NORMAL,
VEML_LUX_CORRECTED,
VEML_LUX_AUTO,
VEML_LUX_NORMAL_NOWAIT,
VEML_LUX_CORRECTED_NOWAIT,
};
addFormSelector(F("Lux Read-method"),
F("rmth"),
NR_ELEMENTS(readMethodOptions),
readMethod,
readMethodOptions,
P168_READLUX_MODE);
addFormNote(F("For 'Auto' Read-method, the Gain factor and Integration time settings are ignored."));
}
{
const __FlashStringHelper *alsGain[] = {
F("x1"),
F("x2"),
F("x(1/8)"),
F("x(1/4)"),
};
const int alsGainOptions[] = {
0b00,
0b01,
0b10,
0b11,
};
addFormSelector(F("Gain factor"),
F("gain"),
NR_ELEMENTS(alsGainOptions),
alsGain,
alsGainOptions,
P168_ALS_GAIN);
}
{
const __FlashStringHelper *alsIntegration[] = {
F("25 ms"),
F("50 ms"),
F("100 ms"),
F("200 ms"),
F("400 ms"),
F("800 ms"),
};
const int alsIntegrationOptions[] = {
0b1100,
0b1000,
0b0000,
0b0001,
0b0010,
0b0011,
};
addFormSelector(F("Integration time"),
F("int"),
NR_ELEMENTS(alsIntegrationOptions),
alsIntegration,
alsIntegrationOptions,
P168_ALS_INTEGRATION);
}
addFormSeparator(2);
{
const __FlashStringHelper *psmMode[] = {
F("Disabled"),
F("Mode 1"),
F("Mode 2"),
F("Mode 3"),
F("Mode 4"),
};
const int psmModeOptions[] = {
static_cast<int>(P168_power_save_mode_e::Disabled),
static_cast<int>(P168_power_save_mode_e::Mode1),
static_cast<int>(P168_power_save_mode_e::Mode2),
static_cast<int>(P168_power_save_mode_e::Mode3),
static_cast<int>(P168_power_save_mode_e::Mode4),
};
addFormSelector(F("Power Save Mode"),
F("psm"),
NR_ELEMENTS(psmModeOptions),
psmMode,
psmModeOptions,
P168_PSM_MODE);
}
success = true;
break;
}
case PLUGIN_WEBFORM_SAVE:
{
P168_I2C_ADDRESS = getFormItemInt(F("i2c_addr"));
P168_READLUX_MODE = getFormItemInt(F("rmth"));
P168_ALS_GAIN = getFormItemInt(F("gain"));
P168_ALS_INTEGRATION = getFormItemInt(F("int"));
P168_PSM_MODE = getFormItemInt(F("psm"));
success = true;
break;
}
case PLUGIN_INIT:
{
initPluginTaskData(event->TaskIndex, new (std::nothrow) P168_data_struct(P168_ALS_GAIN,
P168_ALS_INTEGRATION,
P168_PSM_MODE,
P168_READLUX_MODE));
P168_data_struct *P168_data = static_cast<P168_data_struct *>(getPluginTaskData(event->TaskIndex));
success = (nullptr != P168_data) && P168_data->init(event);
break;
}
case PLUGIN_READ:
{
P168_data_struct *P168_data = static_cast<P168_data_struct *>(getPluginTaskData(event->TaskIndex));
if (nullptr != P168_data) {
success = P168_data->plugin_read(event);
}
break;
}
case PLUGIN_GET_CONFIG_VALUE:
{
P168_data_struct *P168_data = static_cast<P168_data_struct *>(getPluginTaskData(event->TaskIndex));
if (nullptr != P168_data) {
success = P168_data->plugin_get_config_value(event, string);
}
break;
}
}
return success;
}
#endif // USES_P168
+9
View File
@@ -1642,6 +1642,9 @@ To create/register a plugin, you have to :
#ifndef USES_P166
#define USES_P166 // Output - GP8403 DAC 0-10V
#endif
#ifndef USES_P168
#define USES_P168 // Light - VEML6030/VEML7700
#endif
#endif
@@ -1946,6 +1949,9 @@ To create/register a plugin, you have to :
#ifndef USES_P166
#define USES_P166 // Output - GP8403 DAC 0-10V
#endif
#ifndef USES_P168
#define USES_P168 // Light - VEML6030/VEML7700
#endif
// Controllers
#ifndef USES_C011
@@ -2354,6 +2360,9 @@ To create/register a plugin, you have to :
#ifndef USES_P166
#define USES_P166 // Output - GP8403 DAC 0-10V
#endif
#ifndef USES_P168
#define USES_P168 // Light - VEML6030/VEML7700
#endif
// Controllers
#ifndef USES_C015
@@ -0,0 +1,91 @@
#include "../PluginStructs/P168_data_struct.h"
#ifdef USES_P168
# include "../Helpers/CRC_functions.h"
/**************************************************************************
* Constructor
**************************************************************************/
P168_data_struct::P168_data_struct(uint8_t alsGain,
uint8_t alsIntegration,
uint8_t psmMode,
uint8_t readMethod) :
_als_gain(alsGain), _als_integration(alsIntegration), _psm_mode(psmMode), _readMethod(readMethod), initialized(false)
{}
P168_data_struct::~P168_data_struct() {
delete veml;
}
bool P168_data_struct::init(struct EventStruct *event) {
veml = new (std::nothrow) Adafruit_VEML7700();
// - Read sensor serial number
if ((nullptr != veml) &&
veml->begin()) {
// Set config & start sensor
veml->setGain(_als_gain);
veml->setIntegrationTime(_als_integration);
veml->setPowerSaveMode(_psm_mode);
veml->enable(true);
addLog(LOG_LEVEL_INFO, F("VEML : 6030/7700 Initialized."));
initialized = true;
} else {
addLog(LOG_LEVEL_ERROR, F("VEML : 6030/7700 Init ERROR."));
}
return isInitialized();
}
/*****************************************************
* plugin_read
*****************************************************/
bool P168_data_struct::plugin_read(struct EventStruct *event) {
bool success = false;
if (isInitialized() && veml->readReady()) {
uint16_t amb = veml->readALS();
float lux = veml->readLux(static_cast<luxMethod>(_readMethod));
uint16_t whi = veml->readWhite();
if (luxMethod::VEML_LUX_AUTO == static_cast<luxMethod>(_readMethod)) {
addLog(LOG_LEVEL_INFO, strformat(F("VEML : 6030/7700 AutoLux, Lux: %.2f, Gain: %.3f, Integration: %d"),
lux, veml->getGainValue(), veml->getIntegrationTimeValue()));
}
UserVar.setFloat(event->TaskIndex, 0, lux);
UserVar.setFloat(event->TaskIndex, 1, whi);
UserVar.setFloat(event->TaskIndex, 2, amb);
success = true;
}
return success;
}
/*****************************************************
* plugin_get_config_value
*****************************************************/
bool P168_data_struct::plugin_get_config_value(struct EventStruct *event,
String & string) {
bool success = false;
if (isInitialized()) {
const String val = parseString(string, 1, '.');
if (equals(val, F("gain"))) {
string = toString(veml->getGainValue(), 3);
success = true;
} else
if (equals(val, F("integration"))) {
string = veml->getIntegrationTimeValue();
success = true;
}
}
return success;
}
#endif // ifdef USES_P168
+55
View File
@@ -0,0 +1,55 @@
#ifndef PLUGINSTRUCTS_P168_DATA_STRUCT_H
#define PLUGINSTRUCTS_P168_DATA_STRUCT_H
#include "../../_Plugin_Helper.h"
#ifdef USES_P168
# include <Adafruit_VEML7700.h>
# define P168_I2C_ADDRESS PCONFIG(0)
# define P168_ALS_GAIN PCONFIG(1)
# define P168_ALS_INTEGRATION PCONFIG(2)
# define P168_PSM_MODE PCONFIG(3)
# define P168_READLUX_MODE PCONFIG(4)
enum class P168_power_save_mode_e : uint8_t {
Disabled = 4,
Mode1 = 0,
Mode2 = 1,
Mode3 = 2,
Mode4 = 3,
};
struct P168_data_struct : public PluginTaskData_base {
public:
P168_data_struct(uint8_t alsGain,
uint8_t alsIntegration,
uint8_t psmMode,
uint8_t readMethod);
P168_data_struct() = delete;
virtual ~P168_data_struct();
bool init(struct EventStruct *event);
bool plugin_read(struct EventStruct *event);
bool plugin_get_config_value(struct EventStruct *event,
String & string);
bool isInitialized() const {
return initialized;
}
private:
Adafruit_VEML7700 *veml = nullptr;
uint8_t _als_gain;
uint8_t _als_integration;
uint8_t _psm_mode;
uint8_t _readMethod;
bool initialized = false;
};
#endif // ifdef USES_P168
#endif // ifndef PLUGINSTRUCTS_P168_DATA_STRUCT_H
+3 -1
View File
@@ -180,7 +180,7 @@ String getKnownI2Cdevice(uint8_t address) {
switch (address)
{
case 0x10:
result += F("VEML6075");
result += F("VEML6075,VEML6040,VEML6030,VEML7700");
break;
case 0x11:
result += F("VEML6075,I2C_MultiRelay");
@@ -263,6 +263,8 @@ String getKnownI2Cdevice(uint8_t address) {
result += F("SHT4x");
break;
case 0x48:
result += F("PCF8591,ADS1x15,LM75A,INA219,TMP117,VEML6030");
break;
case 0x4A:
case 0x4B:
result += F("PCF8591,ADS1x15,LM75A,INA219,TMP117");