mirror of
https://github.com/meshtastic/firmware.git
synced 2025-07-31 02:45:41 +00:00
Add functional SCD4X
This commit is contained in:
parent
ec5a752078
commit
7305f1cccc
@ -22,6 +22,14 @@
|
|||||||
// Sensors
|
// Sensors
|
||||||
PMSA003ISensor pmsa003iSensor;
|
PMSA003ISensor pmsa003iSensor;
|
||||||
|
|
||||||
|
|
||||||
|
#if __has_include(<SensirionI2cScd4x.h>)
|
||||||
|
#include "Sensor/SCD4XSensor.h"
|
||||||
|
SCD4XSensor scd4xSensor;
|
||||||
|
#else
|
||||||
|
NullSensor scd4xSensor;
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "graphics/ScreenFonts.h"
|
#include "graphics/ScreenFonts.h"
|
||||||
|
|
||||||
int32_t AirQualityTelemetryModule::runOnce()
|
int32_t AirQualityTelemetryModule::runOnce()
|
||||||
@ -61,6 +69,9 @@ int32_t AirQualityTelemetryModule::runOnce()
|
|||||||
|
|
||||||
if (pmsa003iSensor.hasSensor())
|
if (pmsa003iSensor.hasSensor())
|
||||||
result = pmsa003iSensor.runOnce();
|
result = pmsa003iSensor.runOnce();
|
||||||
|
|
||||||
|
if (scd4xSensor.hasSensor())
|
||||||
|
result = scd4xSensor.runOnce();
|
||||||
}
|
}
|
||||||
|
|
||||||
// it's possible to have this module enabled, only for displaying values on the screen.
|
// it's possible to have this module enabled, only for displaying values on the screen.
|
||||||
@ -143,7 +154,7 @@ void AirQualityTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSta
|
|||||||
|
|
||||||
// Check if any telemetry field has valid data
|
// Check if any telemetry field has valid data
|
||||||
bool hasAny = m.has_pm10_standard || m.has_pm25_standard || m.has_pm100_standard || m.has_pm10_environmental || m.has_pm25_environmental ||
|
bool hasAny = m.has_pm10_standard || m.has_pm25_standard || m.has_pm100_standard || m.has_pm10_environmental || m.has_pm25_environmental ||
|
||||||
m.has_pm100_environmental;
|
m.has_pm100_environmental || m.has_co2;
|
||||||
|
|
||||||
if (!hasAny) {
|
if (!hasAny) {
|
||||||
display->drawString(x, currentY, "No Telemetry");
|
display->drawString(x, currentY, "No Telemetry");
|
||||||
@ -170,6 +181,9 @@ void AirQualityTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSta
|
|||||||
entries.push_back("PM2.5: " + String(m.pm25_standard) + "ug/m3");
|
entries.push_back("PM2.5: " + String(m.pm25_standard) + "ug/m3");
|
||||||
if (m.has_pm100_standard)
|
if (m.has_pm100_standard)
|
||||||
entries.push_back("PM10.0: " + String(m.pm100_standard) + "ug/m3");
|
entries.push_back("PM10.0: " + String(m.pm100_standard) + "ug/m3");
|
||||||
|
if (m.has_co2)
|
||||||
|
entries.push_back("CO2: " + String(m.co2, 0) + "ppm");
|
||||||
|
|
||||||
|
|
||||||
// === Show first available metric on top-right of first line ===
|
// === Show first available metric on top-right of first line ===
|
||||||
if (!entries.empty()) {
|
if (!entries.empty()) {
|
||||||
@ -210,6 +224,10 @@ bool AirQualityTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPack
|
|||||||
LOG_INFO(" | PM1.0(Environmental)=%i, PM2.5(Environmental)=%i, PM10.0(Environmental)=%i",
|
LOG_INFO(" | PM1.0(Environmental)=%i, PM2.5(Environmental)=%i, PM10.0(Environmental)=%i",
|
||||||
t->variant.air_quality_metrics.pm10_environmental, t->variant.air_quality_metrics.pm25_environmental,
|
t->variant.air_quality_metrics.pm10_environmental, t->variant.air_quality_metrics.pm25_environmental,
|
||||||
t->variant.air_quality_metrics.pm100_environmental);
|
t->variant.air_quality_metrics.pm100_environmental);
|
||||||
|
|
||||||
|
LOG_INFO(" | CO2=%i, CO2_T=%f, CO2_H=%f",
|
||||||
|
t->variant.air_quality_metrics.co2, t->variant.air_quality_metrics.co2_temperature,
|
||||||
|
t->variant.air_quality_metrics.co2_humidity);
|
||||||
#endif
|
#endif
|
||||||
// release previous packet before occupying a new spot
|
// release previous packet before occupying a new spot
|
||||||
if (lastMeasurementPacket != nullptr)
|
if (lastMeasurementPacket != nullptr)
|
||||||
@ -236,6 +254,11 @@ bool AirQualityTelemetryModule::getAirQualityTelemetry(meshtastic_Telemetry *m)
|
|||||||
hasSensor = true;
|
hasSensor = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (scd4xSensor.hasSensor()) {
|
||||||
|
valid = valid && scd4xSensor.getMetrics(m);
|
||||||
|
hasSensor = true;
|
||||||
|
}
|
||||||
|
|
||||||
return valid && hasSensor;
|
return valid && hasSensor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,11 +296,25 @@ bool AirQualityTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
|
|||||||
m.which_variant = meshtastic_Telemetry_air_quality_metrics_tag;
|
m.which_variant = meshtastic_Telemetry_air_quality_metrics_tag;
|
||||||
m.time = getTime();
|
m.time = getTime();
|
||||||
if (getAirQualityTelemetry(&m)) {
|
if (getAirQualityTelemetry(&m)) {
|
||||||
LOG_INFO("Send: pm10_standard=%u, pm25_standard=%u, pm100_standard=%u, \
|
|
||||||
|
bool hasAnyPM = m.variant.air_quality_metrics.has_pm10_standard || m.variant.air_quality_metrics.has_pm25_standard || m.variant.air_quality_metrics.has_pm100_standard || m.variant.air_quality_metrics.has_pm10_environmental || m.variant.air_quality_metrics.has_pm25_environmental ||
|
||||||
|
m.variant.air_quality_metrics.has_pm100_environmental;
|
||||||
|
|
||||||
|
if (hasAnyPM) {
|
||||||
|
LOG_INFO("Send: pm10_standard=%u, pm25_standard=%u, pm100_standard=%u, \
|
||||||
pm10_environmental=%u, pm25_environmental=%u, pm100_environmental=%u", \
|
pm10_environmental=%u, pm25_environmental=%u, pm100_environmental=%u", \
|
||||||
m.variant.air_quality_metrics.pm10_standard, m.variant.air_quality_metrics.pm25_standard, \
|
m.variant.air_quality_metrics.pm10_standard, m.variant.air_quality_metrics.pm25_standard, \
|
||||||
m.variant.air_quality_metrics.pm100_standard, m.variant.air_quality_metrics.pm10_environmental, \
|
m.variant.air_quality_metrics.pm100_standard, m.variant.air_quality_metrics.pm10_environmental, \
|
||||||
m.variant.air_quality_metrics.pm25_environmental, m.variant.air_quality_metrics.pm100_environmental);
|
m.variant.air_quality_metrics.pm25_environmental, m.variant.air_quality_metrics.pm100_environmental);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasAnyCO2 = m.variant.air_quality_metrics.has_co2 || m.variant.air_quality_metrics.has_co2_temperature || m.variant.air_quality_metrics.has_co2_humidity;
|
||||||
|
|
||||||
|
if (hasAnyCO2) {
|
||||||
|
LOG_INFO("Send: co2=%i, co2_t=%f, co2_rh=%f",
|
||||||
|
m.variant.air_quality_metrics.co2, m.variant.air_quality_metrics.co2_temperature,
|
||||||
|
m.variant.air_quality_metrics.co2_humidity);
|
||||||
|
}
|
||||||
|
|
||||||
meshtastic_MeshPacket *p = allocDataProtobuf(m);
|
meshtastic_MeshPacket *p = allocDataProtobuf(m);
|
||||||
p->to = dest;
|
p->to = dest;
|
||||||
@ -333,6 +370,11 @@ AdminMessageHandleResult AirQualityTelemetryModule::handleAdminMessageForModule(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (scd4xSensor.hasSensor()) {
|
||||||
|
result = scd4xSensor.handleAdminMessage(mp, request, response);
|
||||||
|
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
return result;
|
return result;
|
||||||
|
75
src/modules/Telemetry/Sensor/SCD4XSensor.cpp
Normal file
75
src/modules/Telemetry/Sensor/SCD4XSensor.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<SensirionI2cScd4x.h>)
|
||||||
|
|
||||||
|
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||||
|
#include "SCD4XSensor.h"
|
||||||
|
#include "TelemetrySensor.h"
|
||||||
|
#include <SensirionI2cScd4x.h>
|
||||||
|
|
||||||
|
#define SCD4X_NO_ERROR 0
|
||||||
|
|
||||||
|
SCD4XSensor::SCD4XSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SCD4X, "SCD4X") {}
|
||||||
|
|
||||||
|
int32_t SCD4XSensor::runOnce()
|
||||||
|
{
|
||||||
|
LOG_INFO("Init sensor: %s", sensorName);
|
||||||
|
if (!hasSensor()) {
|
||||||
|
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t error;
|
||||||
|
|
||||||
|
scd4x.begin(*nodeTelemetrySensorsMap[sensorType].second,
|
||||||
|
nodeTelemetrySensorsMap[sensorType].first);
|
||||||
|
|
||||||
|
delay(30);
|
||||||
|
// Ensure sensor is in clean state
|
||||||
|
error = scd4x.wakeUp();
|
||||||
|
if (error != SCD4X_NO_ERROR) {
|
||||||
|
LOG_INFO("Error trying to execute wakeUp()");
|
||||||
|
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop periodic measurement
|
||||||
|
error = scd4x.stopPeriodicMeasurement();
|
||||||
|
if (error != SCD4X_NO_ERROR) {
|
||||||
|
LOG_INFO("Error trying to stopPeriodicMeasurement()");
|
||||||
|
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO - Decide if using Periodic mesaurement or singleshot
|
||||||
|
// status = scd4x.startLowPowerPeriodicMeasurement();
|
||||||
|
|
||||||
|
if (!scd4x.startLowPowerPeriodicMeasurement()) {
|
||||||
|
status = 1;
|
||||||
|
} else {
|
||||||
|
status = 0;
|
||||||
|
}
|
||||||
|
return initI2CSensor();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SCD4XSensor::setup() {}
|
||||||
|
|
||||||
|
bool SCD4XSensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||||
|
{
|
||||||
|
uint16_t co2, error;
|
||||||
|
float temperature;
|
||||||
|
float humidity;
|
||||||
|
|
||||||
|
error = scd4x.readMeasurement(co2, temperature, humidity);
|
||||||
|
if (error != SCD4X_NO_ERROR || co2 == 0) {
|
||||||
|
LOG_DEBUG("Skipping invalid SCD4X measurement.");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
measurement->variant.air_quality_metrics.has_co2_temperature = true;
|
||||||
|
measurement->variant.air_quality_metrics.has_co2_humidity = true;
|
||||||
|
measurement->variant.air_quality_metrics.has_co2 = true;
|
||||||
|
measurement->variant.air_quality_metrics.co2_temperature = temperature;
|
||||||
|
measurement->variant.air_quality_metrics.co2_humidity = humidity;
|
||||||
|
measurement->variant.air_quality_metrics.co2 = co2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
23
src/modules/Telemetry/Sensor/SCD4XSensor.h
Normal file
23
src/modules/Telemetry/Sensor/SCD4XSensor.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<SensirionI2cScd4x.h>)
|
||||||
|
|
||||||
|
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||||
|
#include "TelemetrySensor.h"
|
||||||
|
#include <SensirionI2cScd4x.h>
|
||||||
|
|
||||||
|
class SCD4XSensor : public TelemetrySensor
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
SensirionI2cScd4x scd4x;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void setup() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SCD4XSensor();
|
||||||
|
virtual int32_t runOnce() override;
|
||||||
|
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user