added CO2 and VOC sensor
This commit is contained in:
14
.vscode/c_cpp_properties.json
vendored
14
.vscode/c_cpp_properties.json
vendored
@@ -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",
|
||||
""
|
||||
]
|
||||
|
||||
@@ -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
69
VOC_sensor.cpp
Normal 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
11
VOC_sensor.h
Normal 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
110
lcd.cpp
@@ -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
2
lcd.h
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "particles.h"
|
||||
#include "sensor.h"
|
||||
|
||||
void initLCD();
|
||||
void handleLCD();
|
||||
|
||||
11
main.cpp
11
main.cpp
@@ -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();
|
||||
}
|
||||
|
||||
5
mqtt.cpp
5
mqtt.cpp
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
33
sensor.cpp
33
sensor.cpp
@@ -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();
|
||||
}
|
||||
|
||||
58
sensor.h
58
sensor.h
@@ -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);
|
||||
Reference in New Issue
Block a user