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": [ "includePath": [
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/include", "/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",
"/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/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/TJpg_Decoder/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/SD/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/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/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/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/SPI/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/SPIFFS/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/tools/sdk/include/fb_gfx",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/cores/esp32", "/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/cores/esp32",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/variants/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/ArduinoOTA/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/AsyncUDP/src", "/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/AsyncUDP/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/AzureIoT/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/WebServer/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/WiFiClientSecure/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/WiFiProv/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/Wire/src",
"/Users/willemoldemans/.platformio/packages/tool-unity", "/Users/willemoldemans/.platformio/packages/tool-unity",
"" ""
], ],
@@ -113,10 +118,15 @@
"path": [ "path": [
"/Users/willemoldemans/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/include", "/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",
"/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/Documents/PROJECTEN/AQS-main/Firmware/PM25SensorESP32/.pio/libdeps/esp32/TJpg_Decoder/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/SD/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/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/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/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/SPI/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/SPIFFS/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/tools/sdk/include/fb_gfx",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/cores/esp32", "/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/cores/esp32",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/variants/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/ArduinoOTA/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/AsyncUDP/src", "/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/AsyncUDP/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/AzureIoT/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/WebServer/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/WiFiClientSecure/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/WiFiProv/src",
"/Users/willemoldemans/.platformio/packages/framework-arduinoespressif32/libraries/Wire/src",
"/Users/willemoldemans/.platformio/packages/tool-unity", "/Users/willemoldemans/.platformio/packages/tool-unity",
"" ""
] ]

View File

@@ -3,36 +3,53 @@
Adafruit_SCD30 scd30; Adafruit_SCD30 scd30;
#define CO2_INTERVAL 120000 //ms #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; uint8_t CO2_samples = 3600 / g_pms_report_period;
AQSSensor SCD30_temperature("Temperature", device_name, CO2_samples); AQSSensor SCD30_temperature("Temperature", SCD30_temp, "degC", device_name, CO2_samples, SCD30MIN, SCD30TEMPMAX);
AQSSensor SCD30_Humidity("Humidity", device_name, CO2_samples); AQSSensor SCD30_Humidity("Humidity", SCD30_hum, "%RH", device_name, CO2_samples, SCD30MIN, SDC30HUMMAX);
AQSSensor SCD30_CO2("CO2", device_name, CO2_samples); AQSSensor SCD30_CO2("CO2", SCD30_co2, "PPM", device_name, CO2_samples, SCD30MIN, SCD30CO2MAX);
uint32_t CO2_lastUpdate = 0; uint32_t CO2_lastUpdate = 0;
void initCO2sensor(void) void initCO2sensor(void)
{ {
Serial.print("Init SCD30:"); Serial.println("SCD30: init");
if (!scd30.begin(true)) 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_temperature);
addSensorToList(&SCD30_Humidity); addSensorToList(&SCD30_Humidity);
addSensorToList(&SCD30_CO2); addSensorToList(&SCD30_CO2);
Serial.println(" OK"); //check callibration Mode
scd30.selfCalibrationEnabled(false);
scd30.read();
Serial.println("SCD30: init OK");
}
} }
void handleCO2sensor(void) void handleCO2sensor(void)
{ {
uint32_t currentmillis = millis(); uint32_t currentmillis = millis();
if ((currentmillis - CO2_lastUpdate > (g_pms_report_period * 1000)) || (!CO2_lastUpdate) && (scd30.dataReady()))
if (currentmillis - CO2_lastUpdate > CO2_INTERVAL)
{ {
if (!scd30.read())
{
Serial.println("SCD30: read error!");
return;
}
SCD30_temperature.set(uint32_t(scd30.temperature)); SCD30_temperature.set(uint32_t(scd30.temperature));
SCD30_Humidity.set(uint32_t(scd30.relative_humidity)); SCD30_Humidity.set(uint32_t(scd30.relative_humidity));
SCD30_CO2.set(uint32_t(scd30.CO2)); SCD30_CO2.set(uint32_t(scd30.CO2));
@@ -40,5 +57,7 @@ void handleCO2sensor(void)
SCD30_temperature.publish(); SCD30_temperature.publish();
SCD30_Humidity.publish(); SCD30_Humidity.publish();
SCD30_CO2.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_eSPI tft = TFT_eSPI();
TFT_eSprite needle = TFT_eSprite(&tft); // Sprite object for needle TFT_eSprite needle = TFT_eSprite(&tft); // Sprite object for needle
TFT_eSprite spr = TFT_eSprite(&tft); // Sprite for meter reading 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 // Jpeg image array attached to this sketch
#include "dial.h" #include "dial.h"
@@ -46,6 +48,7 @@ TFT_eSprite spr = TFT_eSprite(&tft); // Sprite for meter reading
uint16_t *tft_buffer; uint16_t *tft_buffer;
bool buffer_loaded = false; bool buffer_loaded = false;
uint16_t spr_width = 0; uint16_t spr_width = 0;
uint16_t name_spr_width = 0;
void createNeedle(void); void createNeedle(void);
void plotNeedle(int16_t angle, uint16_t ms_delay); 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); spr.pushSprite(DIAL_CENTRE_X - spr_width / 2, DIAL_CENTRE_Y - spr.fontHeight() / 2);
// Plot the label text // Plot the label text
tft.setTextColor(TFT_WHITE, bg_color); nameSpr.setTextFont(3);
tft.setTextDatum(MC_DATUM); name_spr_width = nameSpr.textWidth("Temperature");
tft.drawString("(PM2.5 ug/m3)", DIAL_CENTRE_X, DIAL_CENTRE_Y + 48, 2); 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 // Define where the needle pivot point is on the TFT before
// creating the needle so boundary calculation is correct // creating the needle so boundary calculation is correct
@@ -120,11 +130,101 @@ void initLCD()
// ======================================================================================= // =======================================================================================
// Loop // 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() 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 //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 #pragma once
#include "Arduino.h" #include "Arduino.h"
#include "particles.h" #include "sensor.h"
void initLCD(); void initLCD();
void handleLCD(); void handleLCD();

View File

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

View File

@@ -137,6 +137,11 @@ void handleMQTT(void)
if (!client.connected()) if (!client.connected())
{ {
reconnectMqtt(); reconnectMqtt();
if(!client.connected())
{
Serial.print("OK");
}
Serial.println("");
} }
} }
client.loop(); // Process any outstanding MQTT messages 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_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_WAKING_UP 1 // Laser and fan on, not ready yet
#define PMS_STATE_READY 2 // Warmed up, ready to give data #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; uint8_t g_pms_state = PMS_STATE_WAKING_UP;
uint32_t g_pms_state_start = 0; // Timestamp when PMS state last changed 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; uint8_t samples = 3600 / g_pms_report_period;
AQSSensor g_pm1p0_sp("SP_1P0", device_name, samples); // name enum unit device name samples/h, min, max
AQSSensor g_pm2p5_sp("SP_2P5", device_name, samples); AQSSensor g_pm1p0_sp("SP_1P0", SP_1P0, "", device_name, samples, PSMMIN, PMSMAX);
AQSSensor g_pm10p0_sp("SP_10P0", device_name, samples); 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", device_name, samples); AQSSensor g_pm1p0_ae("AE_1P0", AE_1P0, "ug/m3", device_name, samples, PSMMIN, PMSMAX);
AQSSensor g_pm2p5_ae("AE_2P5", device_name, samples); AQSSensor g_pm2p5_ae("AE_2P5", AE_2P5, "ug/m3", device_name, samples, PSMMIN, PMSMAX);
AQSSensor g_pm10p0_ae("AE_10P0", device_name, samples); 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_pm0p3_ppd("PPD_0P3", device_name, samples); AQSSensor g_pm0p5_ppd("PPD_0P5", PPD_0P5, "", device_name, samples, PSMMIN, PPDMAX);
AQSSensor g_pm0p5_ppd("PPD_0P5", device_name, samples); AQSSensor g_pm1p0_ppd("PPD_1P0", PPD_1P0, "", device_name, samples, PSMMIN, PPDMAX);
AQSSensor g_pm1p0_ppd("PPD_1P0", device_name, samples); AQSSensor g_pm2p5_ppd("PPD_2P5", PPD_2P5, "", device_name, samples, PSMMIN, PPDMAX);
AQSSensor g_pm2p5_ppd("PPD_2P5", device_name, samples); AQSSensor g_pm5p0_ppd("PPD_5P0", PPD_5P0, "", device_name, samples, PSMMIN, PPDMAX);
AQSSensor g_pm5p0_ppd("PPD_5P0", device_name, samples); AQSSensor g_pm10p0_ppd("PPD_10P0",PPD_10P0, "", device_name, samples, PSMMIN, PPDMAX);
AQSSensor g_pm10p0_ppd("PPD_10P0", device_name, samples);
void PMS_publishSensors(void ); void PMS_publishSensors(void );
@@ -62,7 +64,6 @@ uint32_t getLCDvalue(void)
void PMS_publishSensors(void ) void PMS_publishSensors(void )
{ {
String message_string;
/* Report PM1.0 AE value */ /* Report PM1.0 AE value */
g_pm1p0_ae.publish(); g_pm1p0_ae.publish();
@@ -87,7 +88,7 @@ void PMS_publishSensors(void )
void initParticles( void ) void initParticles( void )
{ {
Serial.print("initPMS:"); Serial.println("PMS: Init");
// Open a connection to the PMS and put it into passive mode // 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 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 pms.activeMode(); // Tell PMS to stop sending data automatically
@@ -98,7 +99,7 @@ void initParticles( void )
PMS_AddSensors(); 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))) 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 // It's time to wake up the sensor
Serial.println("Waking up sensor"); Serial.println("PMS: Waking up sensor");
pms.wakeUp(); pms.wakeUp();
g_pms_state_start = time_now; g_pms_state_start = time_now;
g_pms_state = PMS_STATE_WAKING_UP; g_pms_state = PMS_STATE_WAKING_UP;
@@ -170,4 +171,5 @@ void handleParticles( void )
g_pms_state = PMS_STATE_ASLEEP; g_pms_state = PMS_STATE_ASLEEP;
} }
} }
} }

View File

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

View File

@@ -1,6 +1,5 @@
#include "sensor.h" #include "sensor.h"
std::vector<AQSSensor*> sensorList; std::vector<AQSSensor*> sensorList;
void publishAll(void); void publishAll(void);
@@ -17,7 +16,7 @@ void reportToSerial(void)
void addSensorToList(AQSSensor* sensor) void addSensorToList(AQSSensor* sensor)
{ {
sensorList.push_back(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->print();
sensor->publishMQTT(); sensor->publishMQTT();
sensor->published();
} }
} }
void initSensor(void) void initSensor(void)
{ {
Serial.print("InitSensor:"); Serial.println("Sensor: Init");
Serial.println(" OK"); Serial.println("Sensor: Init OK");
} }
void handleSensor(void) void handleSensor(void)
{ {
publishAll(); 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 "Arduino.h"
#include "mqtt.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 class AQSSensor
{ {
char _topic[50]; char _topic[50];
char _topic_1h[50]; char _topic_1h[50];
char _topic_24h[255]; char _topic_24h[255];
const String _name; const String _name;
const sensor_e _sensor;
const String _unit;
uint32_t _value; uint32_t _value;
RunningMedian _average1h; RunningMedian _average1h;
RunningMedian _average24h; RunningMedian _average24h;
bool _publish = false; bool _publish = false;
const uint32_t _scaleMin;
const uint32_t _scaleMax;
public: public:
AQSSensor(String name, String deviceID, uint8_t avgSamples) : _name(name), AQSSensor(String name, sensor_e sensor, String unit,
_average1h(avgSamples), String deviceID, uint8_t avgSamples,
_average24h(avgSamples * 24) 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, "Sensors/%s/%s", deviceID.c_str(), name.c_str());
sprintf(_topic_1h, "Sensors/%s/%s/1h/", 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; return _name;
} }
void published(void)
{
_publish = false;
}
void publishMQTT(void) void publishMQTT(void)
{ {
if (_publish == true) if (_publish == true)
@@ -58,13 +99,22 @@ public:
{ {
if (_publish) 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 addSensorToList(AQSSensor *sensor);
void reportToSerial(void); void reportToSerial(void);
AQSSensor *getSensor(sensor_e sensor);
uint32_t getSensorValue(sensor_e sensor);
void initSensor(void); void initSensor(void);
void handleSensor(void); void handleSensor(void);