diff --git a/platformio.ini b/platformio.ini
index 5e53c495f..0f2907dee 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -80,7 +80,7 @@ lib_deps =
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
https://github.com/meshtastic/TinyGPSPlus.git#71a82db35f3b973440044c476d4bcdc673b104f4
https://github.com/meshtastic/ArduinoThread.git#1ae8778c85d0a2a729f989e0b1e7d7c4dc84eef0
- nanopb/Nanopb@^0.4.7
+ nanopb/Nanopb@^0.4.8
erriez/ErriezCRC32@^1.0.1
; Used for the code analysis in PIO Home / Inspect
@@ -133,4 +133,5 @@ lib_deps =
https://github.com/lewisxhe/SensorLib#27fd0f721e20cd09e1f81383f0ba58a54fe84a17
adafruit/Adafruit LSM6DS@^4.7.2
mprograms/QMC5883LCompass@^1.2.0
+ adafruit/Adafruit VEML7700 Library@^2.1.6
https://github.com/adafruit/Adafruit_SHT4X#1.0.4
\ No newline at end of file
diff --git a/protobufs b/protobufs
index 1bfe0354d..eade2c6be 160000
--- a/protobufs
+++ b/protobufs
@@ -1 +1 @@
-Subproject commit 1bfe0354d101a6a71ea1354ea158e59193671a0b
+Subproject commit eade2c6befb65a9c46c5d28ae1e8e24c37a1a3d0
diff --git a/src/configuration.h b/src/configuration.h
index 0d9ee5451..858f3167e 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -129,6 +129,7 @@ along with this program. If not, see .
#define SHT31_4x_ADDR 0x44
#define PMSA0031_ADDR 0x12
#define RCWL9620_ADDR 0x57
+#define VEML7700_ADDR 0x10
// -----------------------------------------------------------------------------
// ACCELEROMETER
diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h
index a53df11f3..6c01b9100 100644
--- a/src/detect/ScanI2C.h
+++ b/src/detect/ScanI2C.h
@@ -42,6 +42,7 @@ class ScanI2C
BQ24295,
LSM6DS3,
TCA9555,
+ VEML7700,
RCWL9620,
NCP5623,
} DeviceType;
diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp
index 58d46a58d..7828dfb58 100644
--- a/src/detect/ScanI2CTwoWire.cpp
+++ b/src/detect/ScanI2CTwoWire.cpp
@@ -336,6 +336,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
SCAN_SIMPLE_CASE(BMA423_ADDR, BMA423, "BMA423 accelerometer found\n");
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3 accelerometer found at address 0x%x\n", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555 I2C expander found\n");
+ SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700 light sensor found\n");
default:
LOG_INFO("Device found at address 0x%x was not able to be enumerated\n", addr.address);
diff --git a/src/main.cpp b/src/main.cpp
index 93c6ef38f..f14d08188 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -541,6 +541,7 @@ void setup()
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::QMC5883L, meshtastic_TelemetrySensorType_QMC5883L)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::PMSA0031, meshtastic_TelemetrySensorType_PMSA003I)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::RCWL9620, meshtastic_TelemetrySensorType_RCWL9620)
+ SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::VEML7700, meshtastic_TelemetrySensorType_VEML7700)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHT4X, meshtastic_TelemetrySensorType_SHT4X)
i2cScanner.reset();
diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h
index b6b08f2e7..f4a79398f 100644
--- a/src/mesh/generated/meshtastic/telemetry.pb.h
+++ b/src/mesh/generated/meshtastic/telemetry.pb.h
@@ -47,7 +47,17 @@ typedef enum _meshtastic_TelemetrySensorType {
/* RCWL-9620 Doppler Radar Distance Sensor, used for water level detection */
meshtastic_TelemetrySensorType_RCWL9620 = 16,
/* Sensirion High accuracy temperature and humidity */
- meshtastic_TelemetrySensorType_SHT4X = 17
+ meshtastic_TelemetrySensorType_SHT4X = 17,
+ /* VEML7700 high accuracy ambient light(Lux) digital 16-bit resolution sensor. */
+ meshtastic_TelemetrySensorType_VEML7700 = 18,
+ /* MLX90632 non-contact IR temperature sensor. */
+ meshtastic_TelemetrySensorType_MLX90632 = 19,
+ /* TI OPT3001 Ambient Light Sensor */
+ meshtastic_TelemetrySensorType_OPT3001 = 20,
+ /* Lite On LTR-390UV-01 UV Light Sensor */
+ meshtastic_TelemetrySensorType_LTR390UV = 21,
+ /* AMS TSL25911FN RGB Light Sensor */
+ meshtastic_TelemetrySensorType_TSL25911FN = 22
} meshtastic_TelemetrySensorType;
/* Struct definitions */
@@ -84,6 +94,10 @@ typedef struct _meshtastic_EnvironmentMetrics {
uint16_t iaq;
/* RCWL9620 Doppler Radar Distance Sensor, used for water level detection. Float value in mm. */
float distance;
+ /* VEML7700 high accuracy ambient light(Lux) digital 16-bit resolution sensor. */
+ float lux;
+ /* VEML7700 high accuracy white light(irradiance) not calibrated digital 16-bit resolution sensor. */
+ float white_lux;
} meshtastic_EnvironmentMetrics;
/* Power Metrics (voltage / current / etc) */
@@ -154,8 +168,8 @@ extern "C" {
/* Helper constants for enums */
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
-#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_SHT4X
-#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_SHT4X+1))
+#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_VEML7700
+#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_VEML7700+1))
@@ -165,12 +179,12 @@ extern "C" {
/* Initializer values for message structs */
#define meshtastic_DeviceMetrics_init_default {0, 0, 0, 0, 0}
-#define meshtastic_EnvironmentMetrics_init_default {0, 0, 0, 0, 0, 0, 0, 0}
+#define meshtastic_EnvironmentMetrics_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_PowerMetrics_init_default {0, 0, 0, 0, 0, 0}
#define meshtastic_AirQualityMetrics_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}}
#define meshtastic_DeviceMetrics_init_zero {0, 0, 0, 0, 0}
-#define meshtastic_EnvironmentMetrics_init_zero {0, 0, 0, 0, 0, 0, 0, 0}
+#define meshtastic_EnvironmentMetrics_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_PowerMetrics_init_zero {0, 0, 0, 0, 0, 0}
#define meshtastic_AirQualityMetrics_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}}
@@ -189,6 +203,8 @@ extern "C" {
#define meshtastic_EnvironmentMetrics_current_tag 6
#define meshtastic_EnvironmentMetrics_iaq_tag 7
#define meshtastic_EnvironmentMetrics_distance_tag 8
+#define meshtastic_EnvironmentMetrics_lux_tag 9
+#define meshtastic_EnvironmentMetrics_white_lux_tag 10
#define meshtastic_PowerMetrics_ch1_voltage_tag 1
#define meshtastic_PowerMetrics_ch1_current_tag 2
#define meshtastic_PowerMetrics_ch2_voltage_tag 3
@@ -231,7 +247,9 @@ X(a, STATIC, SINGULAR, FLOAT, gas_resistance, 4) \
X(a, STATIC, SINGULAR, FLOAT, voltage, 5) \
X(a, STATIC, SINGULAR, FLOAT, current, 6) \
X(a, STATIC, SINGULAR, UINT32, iaq, 7) \
-X(a, STATIC, SINGULAR, FLOAT, distance, 8)
+X(a, STATIC, SINGULAR, FLOAT, distance, 8) \
+X(a, STATIC, SINGULAR, FLOAT, lux, 9) \
+X(a, STATIC, SINGULAR, FLOAT, white_lux, 10)
#define meshtastic_EnvironmentMetrics_CALLBACK NULL
#define meshtastic_EnvironmentMetrics_DEFAULT NULL
@@ -291,7 +309,7 @@ extern const pb_msgdesc_t meshtastic_Telemetry_msg;
#define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size
#define meshtastic_AirQualityMetrics_size 72
#define meshtastic_DeviceMetrics_size 27
-#define meshtastic_EnvironmentMetrics_size 39
+#define meshtastic_EnvironmentMetrics_size 49
#define meshtastic_PowerMetrics_size 30
#define meshtastic_Telemetry_size 79
@@ -299,4 +317,4 @@ extern const pb_msgdesc_t meshtastic_Telemetry_msg;
} /* extern "C" */
#endif
-#endif
+#endif
\ No newline at end of file
diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp
index 62adc9a8c..a3f63b0aa 100644
--- a/src/modules/Telemetry/EnvironmentTelemetry.cpp
+++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp
@@ -28,6 +28,7 @@
#include "Sensor/SHT31Sensor.h"
#include "Sensor/SHT4XSensor.h"
#include "Sensor/SHTC3Sensor.h"
+#include "Sensor/VEML7700Sensor.h"
BMP085Sensor bmp085Sensor;
BMP280Sensor bmp280Sensor;
@@ -37,6 +38,7 @@ MCP9808Sensor mcp9808Sensor;
SHTC3Sensor shtc3Sensor;
LPS22HBSensor lps22hbSensor;
SHT31Sensor sht31Sensor;
+VEML7700Sensor veml7700Sensor;
SHT4XSensor sht4xSensor;
RCWL9620Sensor rcwl9620Sensor;
@@ -99,6 +101,8 @@ int32_t EnvironmentTelemetryModule::runOnce()
result = ina219Sensor.runOnce();
if (ina260Sensor.hasSensor())
result = ina260Sensor.runOnce();
+ if (veml7700Sensor.hasSensor())
+ result = veml7700Sensor.runOnce();
if (rcwl9620Sensor.hasSensor())
result = rcwl9620Sensor.runOnce();
}
@@ -218,9 +222,8 @@ bool EnvironmentTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPac
sender, t->variant.environment_metrics.barometric_pressure, t->variant.environment_metrics.current,
t->variant.environment_metrics.gas_resistance, t->variant.environment_metrics.relative_humidity,
t->variant.environment_metrics.temperature);
- LOG_INFO("(Received from %s): voltage=%f, IAQ=%d, distance=%f\n", sender, t->variant.environment_metrics.voltage,
- t->variant.environment_metrics.iaq, t->variant.environment_metrics.distance);
-
+ LOG_INFO("(Received from %s): voltage=%f, IAQ=%d, distance=%f, lux=%f\n", sender, t->variant.environment_metrics.voltage,
+ t->variant.environment_metrics.iaq, t->variant.environment_metrics.distance, t->variant.environment_metrics.lux);
#endif
// release previous packet before occupying a new spot
if (lastMeasurementPacket != nullptr)
@@ -235,51 +238,68 @@ bool EnvironmentTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPac
bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
{
meshtastic_Telemetry m;
- bool valid = false;
+ bool valid = true;
+ bool hasSensor = false;
m.time = getTime();
m.which_variant = meshtastic_Telemetry_environment_metrics_tag;
- m.variant.environment_metrics.barometric_pressure = 0;
- m.variant.environment_metrics.current = 0;
- m.variant.environment_metrics.gas_resistance = 0;
- m.variant.environment_metrics.relative_humidity = 0;
- m.variant.environment_metrics.temperature = 0;
- m.variant.environment_metrics.voltage = 0;
- m.variant.environment_metrics.iaq = 0;
- m.variant.environment_metrics.distance = 0;
-
- if (sht31Sensor.hasSensor())
- valid = sht31Sensor.getMetrics(&m);
- if (sht4xSensor.hasSensor())
- valid = sht4xSensor.getMetrics(&m);
- if (lps22hbSensor.hasSensor())
- valid = lps22hbSensor.getMetrics(&m);
- if (shtc3Sensor.hasSensor())
- valid = shtc3Sensor.getMetrics(&m);
- if (bmp085Sensor.hasSensor())
- valid = bmp085Sensor.getMetrics(&m);
- if (bmp280Sensor.hasSensor())
- valid = bmp280Sensor.getMetrics(&m);
- if (bme280Sensor.hasSensor())
- valid = bme280Sensor.getMetrics(&m);
- if (bme680Sensor.hasSensor())
- valid = bme680Sensor.getMetrics(&m);
- if (mcp9808Sensor.hasSensor())
- valid = mcp9808Sensor.getMetrics(&m);
- if (ina219Sensor.hasSensor())
- valid = ina219Sensor.getMetrics(&m);
- if (ina260Sensor.hasSensor())
- valid = ina260Sensor.getMetrics(&m);
- if (rcwl9620Sensor.hasSensor())
- valid = rcwl9620Sensor.getMetrics(&m);
+ if (sht31Sensor.hasSensor()) {
+ valid = valid && sht31Sensor.getMetrics(&m);
+ hasSensor = true;
+ }
+ if (lps22hbSensor.hasSensor()) {
+ valid = valid && lps22hbSensor.getMetrics(&m);
+ hasSensor = true;
+ }
+ if (shtc3Sensor.hasSensor()) {
+ valid = valid && shtc3Sensor.getMetrics(&m);
+ hasSensor = true;
+ }
+ if (bmp085Sensor.hasSensor()) {
+ valid = valid && bmp085Sensor.getMetrics(&m);
+ hasSensor = true;
+ }
+ if (bmp280Sensor.hasSensor()) {
+ valid = valid && bmp280Sensor.getMetrics(&m);
+ hasSensor = true;
+ }
+ if (bme280Sensor.hasSensor()) {
+ valid = valid && bme280Sensor.getMetrics(&m);
+ hasSensor = true;
+ }
+ if (bme680Sensor.hasSensor()) {
+ valid = valid && bme680Sensor.getMetrics(&m);
+ hasSensor = true;
+ }
+ if (mcp9808Sensor.hasSensor()) {
+ valid = valid && mcp9808Sensor.getMetrics(&m);
+ hasSensor = true;
+ }
+ if (ina219Sensor.hasSensor()) {
+ valid = valid && ina219Sensor.getMetrics(&m);
+ hasSensor = true;
+ }
+ if (ina260Sensor.hasSensor()) {
+ valid = valid && ina260Sensor.getMetrics(&m);
+ hasSensor = true;
+ }
+ if (veml7700Sensor.hasSensor()) {
+ valid = valid && veml7700Sensor.getMetrics(&m);
+ hasSensor = true;
+ }
+ if (rcwl9620Sensor.hasSensor()) {
+ valid = valid && rcwl9620Sensor.getMetrics(&m);
+ hasSensor = true;
+ }
+ valid = valid && hasSensor;
if (valid) {
LOG_INFO("(Sending): barometric_pressure=%f, current=%f, gas_resistance=%f, relative_humidity=%f, temperature=%f\n",
m.variant.environment_metrics.barometric_pressure, m.variant.environment_metrics.current,
m.variant.environment_metrics.gas_resistance, m.variant.environment_metrics.relative_humidity,
m.variant.environment_metrics.temperature);
- LOG_INFO("(Sending): voltage=%f, IAQ=%d, distance=%f\n", m.variant.environment_metrics.voltage,
- m.variant.environment_metrics.iaq, m.variant.environment_metrics.distance);
+ LOG_INFO("(Sending): voltage=%f, IAQ=%d, distance=%f, lux=%f\n", m.variant.environment_metrics.voltage,
+ m.variant.environment_metrics.iaq, m.variant.environment_metrics.distance, m.variant.environment_metrics.lux);
sensor_read_error_count = 0;
diff --git a/src/modules/Telemetry/Sensor/VEML7700Sensor.cpp b/src/modules/Telemetry/Sensor/VEML7700Sensor.cpp
new file mode 100644
index 000000000..1abe8339f
--- /dev/null
+++ b/src/modules/Telemetry/Sensor/VEML7700Sensor.cpp
@@ -0,0 +1,60 @@
+#include "VEML7700Sensor.h"
+#include "../mesh/generated/meshtastic/telemetry.pb.h"
+#include "TelemetrySensor.h"
+#include "configuration.h"
+#include
+#include
+
+VEML7700Sensor::VEML7700Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_VEML7700, "VEML7700") {}
+
+int32_t VEML7700Sensor::runOnce()
+{
+ LOG_INFO("Init sensor: %s\n", sensorName);
+ if (!hasSensor()) {
+ return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
+ }
+ status = veml7700.begin(nodeTelemetrySensorsMap[sensorType].second);
+
+ veml7700.setLowThreshold(10000);
+ veml7700.setHighThreshold(20000);
+ veml7700.interruptEnable(true);
+
+ return initI2CSensor();
+}
+
+void VEML7700Sensor::setup() {}
+
+/*!
+ * @brief Copmute lux from ALS reading.
+ * @param rawALS raw ALS register value
+ * @param corrected if true, apply non-linear correction
+ * @return lux value
+ */
+float VEML7700Sensor::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;
+}
+
+/*!
+ * @brief Determines resolution for current gain and integration time
+ * settings.
+ */
+float VEML7700Sensor::getResolution(void)
+{
+ return MAX_RES * (IT_MAX / veml7700.getIntegrationTimeValue()) * (GAIN_MAX / veml7700.getGainValue());
+}
+
+bool VEML7700Sensor::getMetrics(meshtastic_Telemetry *measurement)
+{
+ int16_t white;
+ measurement->variant.environment_metrics.lux = veml7700.readLux(VEML_LUX_AUTO);
+ white = veml7700.readWhite(true);
+ measurement->variant.environment_metrics.white_lux = computeLux(white, white > 100);
+ LOG_INFO("white lux %f, als lux %f\n", measurement->variant.environment_metrics.white_lux,
+ measurement->variant.environment_metrics.lux);
+
+ return true;
+}
\ No newline at end of file
diff --git a/src/modules/Telemetry/Sensor/VEML7700Sensor.h b/src/modules/Telemetry/Sensor/VEML7700Sensor.h
new file mode 100644
index 000000000..9c7a584d9
--- /dev/null
+++ b/src/modules/Telemetry/Sensor/VEML7700Sensor.h
@@ -0,0 +1,22 @@
+#include "../mesh/generated/meshtastic/telemetry.pb.h"
+#include "TelemetrySensor.h"
+#include
+
+class VEML7700Sensor : public TelemetrySensor
+{
+ private:
+ const float MAX_RES = 0.0036;
+ const float GAIN_MAX = 2;
+ const float IT_MAX = 800;
+ Adafruit_VEML7700 veml7700;
+ float computeLux(uint16_t rawALS, bool corrected);
+ float getResolution(void);
+
+ protected:
+ virtual void setup() override;
+
+ public:
+ VEML7700Sensor();
+ virtual int32_t runOnce() override;
+ virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
+};
\ No newline at end of file
diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp
index 95b2daa99..2e367420a 100644
--- a/src/mqtt/MQTT.cpp
+++ b/src/mqtt/MQTT.cpp
@@ -671,6 +671,9 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
msgPayload["gas_resistance"] = new JSONValue(decoded->variant.environment_metrics.gas_resistance);
msgPayload["voltage"] = new JSONValue(decoded->variant.environment_metrics.voltage);
msgPayload["current"] = new JSONValue(decoded->variant.environment_metrics.current);
+ msgPayload["lux"] = new JSONValue(decoded->variant.environment_metrics.lux);
+ msgPayload["white_lux"] = new JSONValue(decoded->variant.environment_metrics.white_lux);
+ msgPayload["iaq"] = new JSONValue((uint)decoded->variant.environment_metrics.iaq);
} else if (decoded->which_variant == meshtastic_Telemetry_power_metrics_tag) {
msgPayload["voltage_ch1"] = new JSONValue(decoded->variant.power_metrics.ch1_voltage);
msgPayload["current_ch1"] = new JSONValue(decoded->variant.power_metrics.ch1_current);