Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of the sensor VEML7700 #3893

Merged
merged 18 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
2 changes: 1 addition & 1 deletion protobufs
1 change: 1 addition & 0 deletions src/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define SHT31_4x_ADDR 0x44
#define PMSA0031_ADDR 0x12
#define RCWL9620_ADDR 0x57
#define VEML7700_ADDR 0x10

// -----------------------------------------------------------------------------
// ACCELEROMETER
Expand Down
1 change: 1 addition & 0 deletions src/detect/ScanI2C.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class ScanI2C
BQ24295,
LSM6DS3,
TCA9555,
VEML7700,
RCWL9620,
NCP5623,
} DeviceType;
Expand Down
1 change: 1 addition & 0 deletions src/detect/ScanI2CTwoWire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
34 changes: 26 additions & 8 deletions src/mesh/generated/meshtastic/telemetry.pb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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) */
Expand Down Expand Up @@ -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))



Expand All @@ -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}}
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -291,12 +309,12 @@ 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

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif
#endif
98 changes: 59 additions & 39 deletions src/modules/Telemetry/EnvironmentTelemetry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "Sensor/SHT31Sensor.h"
#include "Sensor/SHT4XSensor.h"
#include "Sensor/SHTC3Sensor.h"
#include "Sensor/VEML7700Sensor.h"

BMP085Sensor bmp085Sensor;
BMP280Sensor bmp280Sensor;
Expand All @@ -37,6 +38,7 @@ MCP9808Sensor mcp9808Sensor;
SHTC3Sensor shtc3Sensor;
LPS22HBSensor lps22hbSensor;
SHT31Sensor sht31Sensor;
VEML7700Sensor veml7700Sensor;
SHT4XSensor sht4xSensor;
RCWL9620Sensor rcwl9620Sensor;

Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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)
Expand All @@ -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;

Expand Down
60 changes: 60 additions & 0 deletions src/modules/Telemetry/Sensor/VEML7700Sensor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include "VEML7700Sensor.h"
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "TelemetrySensor.h"
#include "configuration.h"
#include <Adafruit_VEML7700.h>
#include <typeinfo>

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;
}
22 changes: 22 additions & 0 deletions src/modules/Telemetry/Sensor/VEML7700Sensor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "TelemetrySensor.h"
#include <Adafruit_VEML7700.h>

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;
};
3 changes: 3 additions & 0 deletions src/mqtt/MQTT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Dr-Gandalf marked this conversation as resolved.
Show resolved Hide resolved
} 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);
Expand Down
Loading