Scan for i2c sensors in environmental telemetry if enabled (#1492)

* Scan for i2c sensors in environmental telemetry if enabled

* Update TelemetrySensor.h

* Added surpression.

* Remove suppression and fix real bug

* Interrogate BME sensor id registers
This commit is contained in:
Ben Meadors
2022-06-05 09:50:06 -05:00
committed by GitHub
parent 4ab831c103
commit eafbef0c2f
17 changed files with 133 additions and 98 deletions

View File

@@ -45,10 +45,12 @@ MCP9808Sensor mcp9808Sensor;
int32_t EnvironmentTelemetryModule::runOnce()
{
#ifndef PORTDUINO
int32_t result = INT32_MAX;
/*
Uncomment the preferences below if you want to use the module
without having to configure it from the PythonAPI or WebUI.
*/
/*
moduleConfig.telemetry.environment_measurement_enabled = 1;
moduleConfig.telemetry.environment_screen_enabled = 1;
@@ -62,7 +64,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
if (!(moduleConfig.telemetry.environment_measurement_enabled ||
moduleConfig.telemetry.environment_screen_enabled)) {
// If this module is not enabled, and the user doesn't want the display screen don't waste any OSThread time on it
return (INT32_MAX);
return result;
}
if (firstTime) {
@@ -73,32 +75,33 @@ int32_t EnvironmentTelemetryModule::runOnce()
DEBUG_MSG("Environment Telemetry: Initializing\n");
// it's possible to have this module enabled, only for displaying values on the screen.
// therefore, we should only enable the sensor loop if measurement is also enabled
switch (moduleConfig.telemetry.environment_sensor_type) {
case TelemetrySensorType_DHT11:
case TelemetrySensorType_DHT12:
case TelemetrySensorType_DHT21:
case TelemetrySensorType_DHT22:
return dhtSensor.runOnce();
case TelemetrySensorType_DS18B20:
return dallasSensor.runOnce();
case TelemetrySensorType_BME280:
return bme280Sensor.runOnce();
case TelemetrySensorType_BME680:
return bme680Sensor.runOnce();
case TelemetrySensorType_MCP9808:
return mcp9808Sensor.runOnce();
default:
DEBUG_MSG("Environment Telemetry: Invalid sensor type selected; Disabling module");
return (INT32_MAX);
case TelemetrySensorType_DHT11:
case TelemetrySensorType_DHT12:
case TelemetrySensorType_DHT21:
case TelemetrySensorType_DHT22:
result = dhtSensor.runOnce();
break;
case TelemetrySensorType_DS18B20:
result = dallasSensor.runOnce();
break;
default:
DEBUG_MSG("Environment Telemetry: No sensor type specified; Checking for detected i2c sensors\n");
break;
}
if (hasSensor(TelemetrySensorType_BME680))
result = bme680Sensor.runOnce();
if (hasSensor(TelemetrySensorType_BME280))
result = bme280Sensor.runOnce();
if (hasSensor(TelemetrySensorType_MCP9808))
result = mcp9808Sensor.runOnce();
}
return (INT32_MAX);
return result;
} else {
// if we somehow got to a second run of this module with measurement disabled, then just wait forever
if (!moduleConfig.telemetry.environment_measurement_enabled)
return (INT32_MAX);
return result;
// this is not the first time OSThread library has called this function
// so just do what we intend to do on the interval
if (sensor_read_error_count > moduleConfig.telemetry.environment_read_error_count_threshold) {
@@ -114,7 +117,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
DEBUG_MSG("Environment Telemetry: DISABLED; The telemetry_module_environment_read_error_count_threshold has "
"been exceed: %d. Reads will not be retried until after device reset\n",
moduleConfig.telemetry.environment_read_error_count_threshold);
return (INT32_MAX);
return result;
} else if (sensor_read_error_count > 0) {
DEBUG_MSG("Environment Telemetry: There have been %d sensor read failures. Will retry %d more times\n",
@@ -124,23 +127,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
if (!sendOurTelemetry()) {
// if we failed to read the sensor, then try again
// as soon as we can according to the maximum polling frequency
switch (moduleConfig.telemetry.environment_sensor_type) {
case TelemetrySensorType_DHT11:
case TelemetrySensorType_DHT12:
case TelemetrySensorType_DHT21:
case TelemetrySensorType_DHT22:
return (DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
case TelemetrySensorType_DS18B20:
return (DS18B20_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
case TelemetrySensorType_BME280:
case TelemetrySensorType_BME680:
return (BME_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
case TelemetrySensorType_MCP9808:
return (MCP_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
default:
return (DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
}
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
}
return getIntervalOrDefaultMs(moduleConfig.telemetry.environment_update_interval);
@@ -245,29 +232,26 @@ bool EnvironmentTelemetryModule::sendOurTelemetry(NodeNum dest, bool wantReplies
DEBUG_MSG("Environment Telemetry: Read data\n");
switch (moduleConfig.telemetry.environment_sensor_type) {
case TelemetrySensorType_DS18B20:
if (!dallasSensor.getMeasurement(&m))
sensor_read_error_count++;
break;
case TelemetrySensorType_DHT11:
case TelemetrySensorType_DHT12:
case TelemetrySensorType_DHT21:
case TelemetrySensorType_DHT22:
if (!dhtSensor.getMeasurement(&m))
sensor_read_error_count++;
break;
case TelemetrySensorType_BME280:
bme280Sensor.getMeasurement(&m);
break;
case TelemetrySensorType_BME680:
bme680Sensor.getMeasurement(&m);
break;
case TelemetrySensorType_MCP9808:
mcp9808Sensor.getMeasurement(&m);
break;
default:
DEBUG_MSG("Environment Telemetry: No external sensor type selected; Only sending internal metrics\n");
case TelemetrySensorType_DS18B20:
if (!dallasSensor.getMeasurement(&m))
sensor_read_error_count++;
break;
case TelemetrySensorType_DHT11:
case TelemetrySensorType_DHT12:
case TelemetrySensorType_DHT21:
case TelemetrySensorType_DHT22:
if (!dhtSensor.getMeasurement(&m))
sensor_read_error_count++;
break;
default:
DEBUG_MSG("Environment Telemetry: No specified sensor type; Trying any detected i2c sensors\n");
}
if (hasSensor(TelemetrySensorType_BME280))
bme280Sensor.getMeasurement(&m);
if (hasSensor(TelemetrySensorType_BME680))
bme680Sensor.getMeasurement(&m);
if (hasSensor(TelemetrySensorType_MCP9808))
mcp9808Sensor.getMeasurement(&m);
DEBUG_MSG("Telemetry->time: %i\n", m.time);
DEBUG_MSG("Telemetry->barometric_pressure: %f\n", m.variant.environment_metrics.barometric_pressure);

View File

@@ -4,23 +4,28 @@
#include "BME280Sensor.h"
#include <Adafruit_BME280.h>
BME280Sensor::BME280Sensor() : TelemetrySensor {} {
BME280Sensor::BME280Sensor() : TelemetrySensor {}
{
}
int32_t BME280Sensor::runOnce() {
unsigned bme280Status;
// Default i2c address for BME280
bme280Status = bme280.begin(0x76);
if (!bme280Status) {
DEBUG_MSG("Could not find a valid BME280 sensor, check wiring, address, sensor ID!");
// TODO more verbose diagnostics
} else {
DEBUG_MSG("Telemetry: Opened BME280 on default i2c bus");
DEBUG_MSG("Init sensor: TelemetrySensorType_BME280\n");
if (!hasSensor(TelemetrySensorType_BME280)) {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
return BME_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
bme280Status = bme280.begin(nodeTelemetrySensorsMap[TelemetrySensorType_BME280]);
if (!bme280Status) {
DEBUG_MSG("Could not connect to any detected BME-280 sensor.\nRemoving from nodeTelemetrySensorsMap.\n");
nodeTelemetrySensorsMap[TelemetrySensorType_BME280] = 0;
} else {
DEBUG_MSG("Opened BME280 on default i2c bus\n");
}
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
bool BME280Sensor::getMeasurement(Telemetry *measurement) {
DEBUG_MSG("BME280Sensor::getMeasurement\n");
measurement->variant.environment_metrics.temperature = bme280.readTemperature();
measurement->variant.environment_metrics.relative_humidity = bme280.readHumidity();
measurement->variant.environment_metrics.barometric_pressure = bme280.readPressure() / 100.0F;

View File

@@ -2,8 +2,6 @@
#include "TelemetrySensor.h"
#include <Adafruit_BME280.h>
#define BME_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
class BME280Sensor : virtual public TelemetrySensor {
private:
Adafruit_BME280 bme280;

View File

@@ -4,18 +4,22 @@
#include "BME680Sensor.h"
#include <Adafruit_BME680.h>
BME680Sensor::BME680Sensor() : TelemetrySensor {} {
BME680Sensor::BME680Sensor() : TelemetrySensor {}
{
}
int32_t BME680Sensor::runOnce() {
unsigned bme680Status;
// Default i2c address for BME680
bme680Status = bme680.begin(0x76);
DEBUG_MSG("Init sensor: TelemetrySensorType_BME680\n");
if (!hasSensor(TelemetrySensorType_BME680)) {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
bme680Status = bme680.begin(nodeTelemetrySensorsMap[TelemetrySensorType_BME680]);
if (!bme680Status) {
DEBUG_MSG("Could not find a valid BME680 sensor, check wiring, address, sensor ID!");
// TODO more verbose TelemetrySensor
DEBUG_MSG("Could not connect to any detected BME-680 sensor.\nRemoving from nodeTelemetrySensorsMap.\n");
nodeTelemetrySensorsMap[TelemetrySensorType_BME680] = 0;
} else {
DEBUG_MSG("Telemetry: Opened BME680 on default i2c bus");
DEBUG_MSG("Opened BME680 on default i2c bus\n");
// Set up oversampling and filter initialization
bme680.setTemperatureOversampling(BME680_OS_8X);
bme680.setHumidityOversampling(BME680_OS_2X);
@@ -23,10 +27,11 @@ int32_t BME680Sensor::runOnce() {
bme680.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme680.setGasHeater(320, 150); // 320*C for 150 ms
}
return (BME_680_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
bool BME680Sensor::getMeasurement(Telemetry *measurement) {
DEBUG_MSG("BME680Sensor::getMeasurement\n");
measurement->variant.environment_metrics.temperature = bme680.readTemperature();
measurement->variant.environment_metrics.relative_humidity = bme680.readHumidity();
measurement->variant.environment_metrics.barometric_pressure = bme680.readPressure() / 100.0F;

View File

@@ -2,8 +2,6 @@
#include "TelemetrySensor.h"
#include <Adafruit_BME680.h>
#define BME_680_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
class BME680Sensor : virtual public TelemetrySensor {
private:
Adafruit_BME680 bme680;

View File

@@ -18,13 +18,14 @@ int32_t DHTSensor::runOnce()
dht->begin();
dht->read();
DEBUG_MSG("Telemetry: Opened DHT11/DHT12 on pin: %d\n", moduleConfig.telemetry.environment_sensor_pin);
DEBUG_MSG("Opened DHT11/DHT12 on pin: %d\n", moduleConfig.telemetry.environment_sensor_pin);
return (DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
bool DHTSensor::getMeasurement(Telemetry *measurement)
{
DEBUG_MSG("DHTSensor::getMeasurement\n");
if (!dht->read(true)) {
DEBUG_MSG("Telemetry: FAILED TO READ DATA\n");
return false;

View File

@@ -2,8 +2,6 @@
#include "TelemetrySensor.h"
#include <DHT.h>
#define DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
class DHTSensor : virtual public TelemetrySensor {
private:
DHT *dht = NULL;

View File

@@ -15,12 +15,13 @@ int32_t DallasSensor::runOnce()
ds18b20->begin();
ds18b20->setResolution(12);
ds18b20->requestTemperatures();
DEBUG_MSG("Telemetry: Opened DS18B20 on pin: %d\n", moduleConfig.telemetry.environment_sensor_pin);
return (DS18B20_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
DEBUG_MSG("Opened DS18B20 on pin: %d\n", moduleConfig.telemetry.environment_sensor_pin);
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
bool DallasSensor::getMeasurement(Telemetry *measurement)
{
DEBUG_MSG("DallasSensor::getMeasurement\n");
if (ds18b20->isConversionComplete()) {
measurement->variant.environment_metrics.temperature = ds18b20->getTempC();
measurement->variant.environment_metrics.relative_humidity = 0;

View File

@@ -3,8 +3,6 @@
#include <DS18B20.h>
#include <OneWire.h>
#define DS18B20_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
class DallasSensor : virtual public TelemetrySensor {
private:
OneWire *oneWire = NULL;

View File

@@ -4,25 +4,31 @@
#include "MCP9808Sensor.h"
#include <Adafruit_MCP9808.h>
MCP9808Sensor::MCP9808Sensor() : TelemetrySensor {} {
MCP9808Sensor::MCP9808Sensor() : TelemetrySensor {}
{
}
int32_t MCP9808Sensor::runOnce() {
unsigned mcp9808Status;
// Default i2c address for MCP9808
mcp9808Status = mcp9808.begin(0x18);
DEBUG_MSG("Init sensor: TelemetrySensorType_MCP9808\n");
if (!hasSensor(TelemetrySensorType_MCP9808)) {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
mcp9808Status = mcp9808.begin(nodeTelemetrySensorsMap[TelemetrySensorType_MCP9808]);
if (!mcp9808Status) {
DEBUG_MSG("Could not find a valid MCP9808 sensor, check wiring, address, sensor ID!");
DEBUG_MSG("Could not connect to detected MCP9808 sensor.\n Removing from nodeTelemetrySensorsMap.\n");
nodeTelemetrySensorsMap[TelemetrySensorType_MCP9808] = 0;
} else {
DEBUG_MSG("TelemetrySensor: Opened MCP9808 on default i2c bus");
DEBUG_MSG("TelemetrySensor: Opened MCP9808 on default i2c bus\n");
// Reduce resolution from 0.0625 degrees (precision) to 0.125 degrees (high).
mcp9808.setResolution(2);
}
return (MCP_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
return (DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
}
bool MCP9808Sensor::getMeasurement(Telemetry *measurement) {
DEBUG_MSG("MCP9808Sensor::getMeasurement\n");
measurement->variant.environment_metrics.temperature = mcp9808.readTempC();
return true;
}

View File

@@ -2,8 +2,6 @@
#include "TelemetrySensor.h"
#include <Adafruit_MCP9808.h>
#define MCP_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
class MCP9808Sensor : virtual public TelemetrySensor {
private:
Adafruit_MCP9808 mcp9808;

View File

@@ -1,8 +1,14 @@
#pragma once
#include "../mesh/generated/telemetry.pb.h"
#include "NodeDB.h"
#include "main.h"
#define DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
inline bool hasSensor(TelemetrySensorType sensorType) {
return sensorType < sizeof(nodeTelemetrySensorsMap) && nodeTelemetrySensorsMap[sensorType] > 0;
}
class TelemetrySensor
{
protected: