added CO2 and VOC sensor

This commit is contained in:
2021-07-26 16:37:49 +02:00
parent 618eaec73d
commit 9dfcbf0484
12 changed files with 347 additions and 53 deletions

View File

@@ -10,10 +10,15 @@
"includePath": [
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/include",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/Adafruit SGP30 Sensor",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/Adafruit SCD30",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/Adafruit BusIO",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/Wire/src",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/TJpg_Decoder/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/SD/src",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/RunningMedian",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/PubSubClient/src",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/Adafruit Unified Sensor",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/TFT_eSPI",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/SPIFFS/src",
@@ -82,6 +87,7 @@
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/fb_gfx",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/cores/esp32",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/variants/esp32",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/Adafruit GFX Library",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/AsyncUDP/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/AzureIoT/src",
@@ -104,7 +110,6 @@
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/WiFiClientSecure/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/WiFiProv/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/Wire/src",
"/Users/willemoldemans/.platformio/packages/tool-unity",
""
],
@@ -113,10 +118,15 @@
"path": [
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/include",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/Adafruit SGP30 Sensor",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/Adafruit SCD30",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/Adafruit BusIO",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/Wire/src",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/TJpg_Decoder/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/SD/src",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/RunningMedian",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/PubSubClient/src",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/Adafruit Unified Sensor",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/TFT_eSPI",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/SPIFFS/src",
@@ -185,6 +195,7 @@
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/fb_gfx",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/cores/esp32",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/variants/esp32",
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/Adafruit GFX Library",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/AsyncUDP/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/AzureIoT/src",
@@ -207,7 +218,6 @@
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/WiFiClientSecure/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/WiFiProv/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/Wire/src",
"/Users/willemoldemans/.platformio/packages/tool-unity",
""
]

View File

@@ -3,36 +3,53 @@
Adafruit_SCD30 scd30;
#define CO2_INTERVAL 120000 //ms
#define SCD30TEMPMAX 50
#define SDC30HUMMAX 100
#define SCD30CO2MAX 20000
#define SCD30MIN 0
uint8_t CO2_samples = 3600 / g_pms_report_period;
AQSSensor SCD30_temperature("Temperature", device_name, CO2_samples);
AQSSensor SCD30_Humidity("Humidity", device_name, CO2_samples);
AQSSensor SCD30_CO2("CO2", device_name, CO2_samples);
AQSSensor SCD30_temperature("Temperature", SCD30_temp, "degC", device_name, CO2_samples, SCD30MIN, SCD30TEMPMAX);
AQSSensor SCD30_Humidity("Humidity", SCD30_hum, "%RH", device_name, CO2_samples, SCD30MIN, SDC30HUMMAX);
AQSSensor SCD30_CO2("CO2", SCD30_co2, "PPM", device_name, CO2_samples, SCD30MIN, SCD30CO2MAX);
uint32_t CO2_lastUpdate = 0;
void initCO2sensor(void)
{
Serial.print("Init SCD30:");
if (!scd30.begin(true))
Serial.println("SCD30: init");
if (!scd30.begin())
{
Serial.println("Failed to find SCD30 device");
Serial.println("SCD30: Failed to find sensor");
}
else
{
//configure sensor
scd30.setMeasurementInterval(g_pms_report_period);
addSensorToList(&SCD30_temperature);
addSensorToList(&SCD30_Humidity);
addSensorToList(&SCD30_CO2);
addSensorToList(&SCD30_temperature);
addSensorToList(&SCD30_Humidity);
addSensorToList(&SCD30_CO2);
Serial.println(" OK");
//check callibration Mode
scd30.selfCalibrationEnabled(false);
scd30.read();
Serial.println("SCD30: init OK");
}
}
void handleCO2sensor(void)
{
uint32_t currentmillis = millis();
if (currentmillis - CO2_lastUpdate > CO2_INTERVAL)
if ((currentmillis - CO2_lastUpdate > (g_pms_report_period * 1000)) || (!CO2_lastUpdate) && (scd30.dataReady()))
{
if (!scd30.read())
{
Serial.println("SCD30: read error!");
return;
}
SCD30_temperature.set(uint32_t(scd30.temperature));
SCD30_Humidity.set(uint32_t(scd30.relative_humidity));
SCD30_CO2.set(uint32_t(scd30.CO2));
@@ -40,5 +57,7 @@ void handleCO2sensor(void)
SCD30_temperature.publish();
SCD30_Humidity.publish();
SCD30_CO2.publish();
CO2_lastUpdate = currentmillis;
}
}

69
VOC_sensor.cpp Normal file
View File

@@ -0,0 +1,69 @@
#include "VOC_sensor.h"
Adafruit_SGP30 sgp;
uint8_t VOC_samples = 3600 / g_pms_report_period;
#define VOC_MIN 0
#define VOC_MAX 10000
#define VOC_INTERVAL 120000 //ms
uint32_t lastVOCtime = 0;
//sensors
AQSSensor SGP30_tvoc("TVOC", SGP30_TVOC, "ppb", device_name, VOC_samples, VOC_MIN, VOC_MAX);
AQSSensor SGP30_eco2("eCO2", SGP30_eCO2, "ppm", device_name, VOC_samples, VOC_MIN, VOC_MAX);
AQSSensor SGP30_rawh2("Raw_H2", SGP30_rawH2, "#", device_name, VOC_samples, VOC_MIN, VOC_MAX);
AQSSensor SGP30_rawethanol("Raw_Ethanol", SGP30_rawEthanol, "#", device_name, VOC_samples, VOC_MIN, VOC_MAX);
void initVOCsensor(void)
{
Serial.println("VOCSensor: Init SGP30: ");
if (!sgp.begin())
{
Serial.println("VOCSensor: Init Failed (SGP30 not found)");
}
else
{
Serial.printf("VOCSensor: serial =0x%X%X%X\n", sgp.serialnumber[0], sgp.serialnumber[1], sgp.serialnumber[2]);
addSensorToList(&SGP30_tvoc);
addSensorToList(&SGP30_eco2);
addSensorToList(&SGP30_rawh2);
addSensorToList(&SGP30_rawethanol);
sgp.IAQmeasure();
sgp.IAQmeasureRaw();
Serial.println("VOCSensor: Init OK");
}
}
void handleVOCsensor(void)
{
uint32_t timenow = millis();
if ((timenow - lastVOCtime > VOC_INTERVAL) || !lastVOCtime)
{
if (!sgp.IAQmeasure())
{
Serial.println("VOCSensor: Measurement failed");
return;
}
SGP30_tvoc.set(sgp.TVOC);
SGP30_eco2.set(sgp.eCO2);
SGP30_tvoc.publish();
SGP30_eco2.publish();
if (!sgp.IAQmeasureRaw())
{
Serial.println("VOCSensor: Raw Measurement failed");
return;
}
SGP30_rawethanol.set(sgp.rawEthanol);
SGP30_rawh2.set(sgp.rawH2);
SGP30_rawethanol.publish();
SGP30_rawh2.publish();
lastVOCtime = timenow;
}
}

11
VOC_sensor.h Normal file
View File

@@ -0,0 +1,11 @@
#pragma once
#include "Arduino.h"
#include "config.h"
#include "sensor.h"
#include "Adafruit_SGP30.h"
void initVOCsensor(void);
void handleVOCsensor(void);

110
lcd.cpp
View File

@@ -36,6 +36,8 @@
TFT_eSPI tft = TFT_eSPI();
TFT_eSprite needle = TFT_eSprite(&tft); // Sprite object for needle
TFT_eSprite spr = TFT_eSprite(&tft); // Sprite for meter reading
TFT_eSprite nameSpr = TFT_eSprite(&tft);
TFT_eSprite unitSpr = TFT_eSprite(&tft);
// Jpeg image array attached to this sketch
#include "dial.h"
@@ -46,6 +48,7 @@ TFT_eSprite spr = TFT_eSprite(&tft); // Sprite for meter reading
uint16_t *tft_buffer;
bool buffer_loaded = false;
uint16_t spr_width = 0;
uint16_t name_spr_width = 0;
void createNeedle(void);
void plotNeedle(int16_t angle, uint16_t ms_delay);
@@ -99,9 +102,16 @@ void initLCD()
spr.pushSprite(DIAL_CENTRE_X - spr_width / 2, DIAL_CENTRE_Y - spr.fontHeight() / 2);
// Plot the label text
tft.setTextColor(TFT_WHITE, bg_color);
tft.setTextDatum(MC_DATUM);
tft.drawString("(PM2.5 ug/m3)", DIAL_CENTRE_X, DIAL_CENTRE_Y + 48, 2);
nameSpr.setTextFont(3);
name_spr_width = nameSpr.textWidth("Temperature");
nameSpr.createSprite(name_spr_width, nameSpr.fontHeight() * 2 + 2);
nameSpr.fillSprite(bg_color);
nameSpr.setTextColor(TFT_WHITE, bg_color);
nameSpr.setTextDatum(MC_DATUM);
nameSpr.setTextPadding(name_spr_width);
nameSpr.drawString("Sensor Name", name_spr_width / 2, nameSpr.fontHeight() / 2);
nameSpr.drawString("Unit", name_spr_width / 2, nameSpr.fontHeight() / 2 * 3 + 2); nameSpr.pushSprite(DIAL_CENTRE_X - name_spr_width / 2, DIAL_CENTRE_Y + 40, 2);
nameSpr.pushSprite(DIAL_CENTRE_X - name_spr_width / 2, DIAL_CENTRE_Y + 40, 2);
// Define where the needle pivot point is on the TFT before
// creating the needle so boundary calculation is correct
@@ -120,11 +130,101 @@ void initLCD()
// =======================================================================================
// Loop
// =======================================================================================
enum DISPLAY_STATE
{
DISPLAY_PM1P0,
DISPLAY_PM2P5,
DISPLAY_PM10P0,
DISPLAY_TEMP,
DISPLAY_HUM,
DISPLAY_CO2,
DISPLAY_LAST
};
DISPLAY_STATE displaystate = DISPLAY_PM1P0;
uint32_t display_last_update = 0;
#define MAXGUAGE 240
#define MINGUAGE 0
#define DISPLAY_ROTATE 10 //sec
void handleLCD()
{
static uint32_t value;
static uint16_t angle;
DISPLAY_STATE displaystate_next = DISPLAY_PM1P0;
sensor_e nextSensor = AE_1P0;
switch (displaystate)
{
case DISPLAY_PM1P0:
{
nextSensor = AE_1P0;
displaystate_next = DISPLAY_PM2P5;
}
break;
case DISPLAY_PM2P5:
{
nextSensor = AE_2P5;
displaystate_next = DISPLAY_PM10P0;
}
break;
case DISPLAY_PM10P0:
{
nextSensor = AE_10P0;
displaystate_next = DISPLAY_TEMP;
}
break;
case DISPLAY_TEMP:
{
nextSensor = SCD30_temp;
displaystate_next = DISPLAY_HUM;
}
break;
case DISPLAY_HUM:
{
nextSensor = SCD30_hum;
displaystate_next = DISPLAY_CO2;
}
break;
case DISPLAY_CO2:
{
nextSensor = SCD30_hum;
displaystate_next = DISPLAY_PM1P0;
}
break;
case DISPLAY_LAST:
default:
{
displaystate_next = DISPLAY_PM1P0;
}
break;
}
//rotate display
uint32_t timenow = millis();
if (timenow - display_last_update > (DISPLAY_ROTATE * 1000))
{
displaystate = displaystate_next;
display_last_update = timenow;
Serial.println("LCD next State");
}
//calculate value to angle
uint16_t angle = map(getLCDvalue(),0,50,0,240);
plotNeedle(angle,15, getLCDvalue());
AQSSensor *sensor = getSensor(nextSensor);
if (sensor == NULL)
{
Serial.println("LCD: getSensor=NULL!");
return;
}
angle = map(value, sensor->getMin(), sensor->getMax(), MINGUAGE, MAXGUAGE);
plotNeedle(angle, 15, value);
nameSpr.drawString(sensor->getName().c_str(), name_spr_width / 2, nameSpr.fontHeight() / 2);
nameSpr.drawString(sensor->getUnit().c_str(), name_spr_width / 2, nameSpr.fontHeight() / 2 * 3 + 2);
nameSpr.pushSprite(DIAL_CENTRE_X - name_spr_width / 2, DIAL_CENTRE_Y + 40, 2);
}
// =======================================================================================

2
lcd.h
View File

@@ -1,7 +1,7 @@
#pragma once
#include "Arduino.h"
#include "particles.h"
#include "sensor.h"
void initLCD();
void handleLCD();

View File

@@ -36,9 +36,10 @@
/*--------------------------- Modules ------------------------------------*/
#include "lcd.h"
#include "mqtt.h"
#include "sensor.h"
#include "particles.h"
#include "CO2_sensor.h"
#include "sensor.h"
#include "VOC_sensor.h"
#include "button.h"
/*--------------------------- Program ---------------------------------------*/
@@ -52,12 +53,15 @@ void setup()
Serial.print("Air Quality Sensor starting up, v");
Serial.println(VERSION);
digitalWrite(5, false);
initWifi();
initMQTT();
initSensor();
initParticles();
initCO2sensor();
initLCD();
initVOCsensor();
//initLCD();
initButtons();
}
@@ -68,8 +72,9 @@ void loop()
{
handleParticles();
handleCO2sensor();
handleVOCsensor();
handleButtons();
handleSensor();
handleLCD();
//handleLCD();
handleMQTT();
}

View File

@@ -137,6 +137,11 @@ void handleMQTT(void)
if (!client.connected())
{
reconnectMqtt();
if(!client.connected())
{
Serial.print("OK");
}
Serial.println("");
}
}
client.loop(); // Process any outstanding MQTT messages

View File

@@ -10,6 +10,9 @@ char g_command_topic[50]; // MQTT topic for receiving commands
#define PMS_STATE_ASLEEP 0 // Low power mode, laser and fan off
#define PMS_STATE_WAKING_UP 1 // Laser and fan on, not ready yet
#define PMS_STATE_READY 2 // Warmed up, ready to give data
#define PMSMAX 50
#define PSMMIN 0
#define PPDMAX 2000
uint8_t g_pms_state = PMS_STATE_WAKING_UP;
uint32_t g_pms_state_start = 0; // Timestamp when PMS state last changed
@@ -18,20 +21,19 @@ uint8_t g_pms_ppd_readings_taken = 0; // 0/1: whether PPD readings have been tak
uint8_t samples = 3600 / g_pms_report_period;
AQSSensor g_pm1p0_sp("SP_1P0", device_name, samples);
AQSSensor g_pm2p5_sp("SP_2P5", device_name, samples);
AQSSensor g_pm10p0_sp("SP_10P0", device_name, samples);
AQSSensor g_pm1p0_ae("AE_1P0", device_name, samples);
AQSSensor g_pm2p5_ae("AE_2P5", device_name, samples);
AQSSensor g_pm10p0_ae("AE_10P0", device_name, samples);
AQSSensor g_pm0p3_ppd("PPD_0P3", device_name, samples);
AQSSensor g_pm0p5_ppd("PPD_0P5", device_name, samples);
AQSSensor g_pm1p0_ppd("PPD_1P0", device_name, samples);
AQSSensor g_pm2p5_ppd("PPD_2P5", device_name, samples);
AQSSensor g_pm5p0_ppd("PPD_5P0", device_name, samples);
AQSSensor g_pm10p0_ppd("PPD_10P0", device_name, samples);
// name enum unit device name samples/h, min, max
AQSSensor g_pm1p0_sp("SP_1P0", SP_1P0, "", device_name, samples, PSMMIN, PMSMAX);
AQSSensor g_pm2p5_sp("SP_2P5", SP_2P5, "", device_name, samples, PSMMIN, PMSMAX);
AQSSensor g_pm10p0_sp("SP_10P0", SP_10P0, "", device_name, samples, PSMMIN, PMSMAX);
AQSSensor g_pm1p0_ae("AE_1P0", AE_1P0, "ug/m3", device_name, samples, PSMMIN, PMSMAX);
AQSSensor g_pm2p5_ae("AE_2P5", AE_2P5, "ug/m3", device_name, samples, PSMMIN, PMSMAX);
AQSSensor g_pm10p0_ae("AE_10P0", AE_10P0, "ug/m3", device_name, samples, PSMMIN, PMSMAX);
AQSSensor g_pm0p3_ppd("PPD_0P3", PPD_0P3, "", device_name, samples, PSMMIN, PPDMAX);
AQSSensor g_pm0p5_ppd("PPD_0P5", PPD_0P5, "", device_name, samples, PSMMIN, PPDMAX);
AQSSensor g_pm1p0_ppd("PPD_1P0", PPD_1P0, "", device_name, samples, PSMMIN, PPDMAX);
AQSSensor g_pm2p5_ppd("PPD_2P5", PPD_2P5, "", device_name, samples, PSMMIN, PPDMAX);
AQSSensor g_pm5p0_ppd("PPD_5P0", PPD_5P0, "", device_name, samples, PSMMIN, PPDMAX);
AQSSensor g_pm10p0_ppd("PPD_10P0",PPD_10P0, "", device_name, samples, PSMMIN, PPDMAX);
void PMS_publishSensors(void );
@@ -62,7 +64,6 @@ uint32_t getLCDvalue(void)
void PMS_publishSensors(void )
{
String message_string;
/* Report PM1.0 AE value */
g_pm1p0_ae.publish();
@@ -87,7 +88,7 @@ void PMS_publishSensors(void )
void initParticles( void )
{
Serial.print("initPMS:");
Serial.println("PMS: Init");
// Open a connection to the PMS and put it into passive mode
Serial2.begin(PMS_BAUD_RATE, SERIAL_8N1, PMS_RX_PIN, PMS_TX_PIN); // Connection for PMS5003
pms.activeMode(); // Tell PMS to stop sending data automatically
@@ -98,7 +99,7 @@ void initParticles( void )
PMS_AddSensors();
Serial.println(" OK");
Serial.println("PMS: Init OK");
}
@@ -112,7 +113,7 @@ void handleParticles( void )
if (time_now - g_pms_state_start >= ((g_pms_report_period * 1000) - (g_pms_warmup_period * 1000)))
{
// It's time to wake up the sensor
Serial.println("Waking up sensor");
Serial.println("PMS: Waking up sensor");
pms.wakeUp();
g_pms_state_start = time_now;
g_pms_state = PMS_STATE_WAKING_UP;
@@ -170,4 +171,5 @@ void handleParticles( void )
g_pms_state = PMS_STATE_ASLEEP;
}
}
}
}

View File

@@ -22,7 +22,7 @@ lib_deps =
robtillaart/RunningMedian
bodmer/Tjpg_decoder
adafruit/Adafruit SCD30
adafruit/Adafruit BusIO
adafruit/Adafruit BusIO
[env:esp32]
platform = espressif32
@@ -32,4 +32,4 @@ monitor_speed = 115200
lib_deps =
${common.lib_deps_builtin}
${common.lib_deps}
adafruit/Adafruit SGP30 Sensor@^2.0.0

View File

@@ -1,6 +1,5 @@
#include "sensor.h"
std::vector<AQSSensor*> sensorList;
void publishAll(void);
@@ -17,7 +16,7 @@ void reportToSerial(void)
void addSensorToList(AQSSensor* sensor)
{
sensorList.push_back(sensor);
Serial.printf("AQSSensor: added %s", sensor->getName().c_str());
Serial.printf("sensor: added %s\n", sensor->getName().c_str());
}
@@ -27,16 +26,40 @@ void publishAll(void)
{
sensor->print();
sensor->publishMQTT();
sensor->published();
}
}
void initSensor(void)
{
Serial.print("InitSensor:");
Serial.println(" OK");
Serial.println("Sensor: Init");
Serial.println("Sensor: Init OK");
}
void handleSensor(void)
{
publishAll();
}
}
AQSSensor* getSensor(sensor_e sensor)
{
for(auto && thissensor : sensorList)
{
if(thissensor->getSensor() == sensor)
{
return thissensor;
}
}
return NULL;
}
uint32_t getSensorValue(sensor_e sensor)
{
AQSSensor *thissensor = getSensor(sensor);
if(thissensor == NULL)
{
Serial.println("Sensor: failed to get sensor");
return 999;
}
return thissensor->value();
}

View File

@@ -3,21 +3,57 @@
#include "Arduino.h"
#include "mqtt.h"
enum sensor_e
{
//PMS sensors
SP_1P0,
SP_2P5,
SP_10P0,
AE_1P0,
AE_2P5,
AE_10P0,
PPD_0P3,
PPD_0P5,
PPD_1P0,
PPD_2P5,
PPD_5P0,
PPD_10P0,
SCD30_temp,
SCD30_hum,
SCD30_co2,
SGP30_TVOC,
SGP30_eCO2,
SGP30_rawH2,
SGP30_rawEthanol,
sensor_last
};
class AQSSensor
{
char _topic[50];
char _topic_1h[50];
char _topic_24h[255];
const String _name;
const sensor_e _sensor;
const String _unit;
uint32_t _value;
RunningMedian _average1h;
RunningMedian _average24h;
bool _publish = false;
const uint32_t _scaleMin;
const uint32_t _scaleMax;
public:
AQSSensor(String name, String deviceID, uint8_t avgSamples) : _name(name),
_average1h(avgSamples),
_average24h(avgSamples * 24)
AQSSensor(String name, sensor_e sensor, String unit,
String deviceID, uint8_t avgSamples,
uint32_t scaleMin, uint32_t scaleMax)
: _name(name),
_sensor(sensor),
_unit(unit),
_average1h(avgSamples),
_average24h(avgSamples * 24),
_scaleMin(scaleMin),
_scaleMax(scaleMax)
{
sprintf(_topic, "Sensors/%s/%s", deviceID.c_str(), name.c_str());
sprintf(_topic_1h, "Sensors/%s/%s/1h/", deviceID.c_str(), name.c_str());
@@ -34,6 +70,11 @@ public:
return _name;
}
void published(void)
{
_publish = false;
}
void publishMQTT(void)
{
if (_publish == true)
@@ -58,13 +99,22 @@ public:
{
if (_publish)
{
Serial.printf("sensor:%s = %d\n", _name.c_str(), _value);
Serial.printf("sensor: report: %s = %d\n", _name.c_str(), _value);
}
}
sensor_e getSensor(void) { return _sensor; }
String getUnit(void) { return _unit;}
uint32_t getMin(void) { return _scaleMin; }
uint32_t getMax(void) { return _scaleMax; }
};
void addSensorToList(AQSSensor *sensor);
void reportToSerial(void);
AQSSensor *getSensor(sensor_e sensor);
uint32_t getSensorValue(sensor_e sensor);
void initSensor(void);
void handleSensor(void);