176 lines
5.7 KiB
C++
176 lines
5.7 KiB
C++
#include "particles.h"
|
|
|
|
// Particulate matter sensor
|
|
|
|
PMS pms(Serial2);
|
|
PMS::DATA g_data;
|
|
|
|
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 3000
|
|
uint8_t g_pms_state = PMS_STATE_WAKING_UP;
|
|
|
|
uint32_t g_pms_state_start = 0; // Timestamp when PMS state last changed
|
|
uint8_t g_pms_readings_taken = 0; // 0/1: whether any readings have been taken
|
|
uint8_t g_pms_ppd_readings_taken = 0; // 0/1: whether PPD readings have been taken
|
|
|
|
uint8_t samples = 3600 / g_pms_report_period;
|
|
|
|
// 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 );
|
|
|
|
|
|
void PMS_AddSensors( void )
|
|
{
|
|
addSensorToList(&g_pm1p0_sp);
|
|
addSensorToList(&g_pm2p5_sp);
|
|
addSensorToList(&g_pm10p0_sp);
|
|
|
|
addSensorToList(&g_pm1p0_ae);
|
|
addSensorToList(&g_pm2p5_ae);
|
|
addSensorToList(&g_pm10p0_ae);
|
|
|
|
addSensorToList(&g_pm0p3_ppd);
|
|
addSensorToList(&g_pm0p5_ppd);
|
|
addSensorToList(&g_pm1p0_ppd);
|
|
addSensorToList(&g_pm2p5_ppd);
|
|
addSensorToList(&g_pm5p0_ppd);
|
|
addSensorToList(&g_pm10p0_ppd);
|
|
}
|
|
|
|
uint32_t getLCDvalue(void)
|
|
{
|
|
return g_pm2p5_ae.value();
|
|
}
|
|
|
|
|
|
void PMS_publishSensors(void )
|
|
{
|
|
|
|
/* Report PM1.0 AE value */
|
|
g_pm1p0_ae.publish();
|
|
g_pm2p5_ae.publish();
|
|
g_pm10p0_ae.publish();
|
|
|
|
g_pm1p0_sp.publish();
|
|
g_pm2p5_sp.publish();
|
|
g_pm10p0_sp.publish();
|
|
|
|
if (1 == g_pms_ppd_readings_taken)
|
|
{
|
|
/* Report PM0.3 PPD value */
|
|
g_pm0p3_ppd.publish();
|
|
g_pm0p5_ppd.publish();
|
|
g_pm1p0_ppd.publish();
|
|
g_pm2p5_ppd.publish();
|
|
g_pm5p0_ppd.publish();
|
|
g_pm10p0_ppd.publish();
|
|
}
|
|
}
|
|
|
|
void initParticles( void )
|
|
{
|
|
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
|
|
delay(100);
|
|
pms.wakeUp(); // Tell PMS to wake up (turn on fan and laser)
|
|
|
|
//Serial2.begin(PMS_BAUD_RATE, SERIAL_8N1, PMS_RX_PIN, PMS_TX_PIN);
|
|
|
|
PMS_AddSensors();
|
|
|
|
Serial.println("PMS: Init OK");
|
|
|
|
}
|
|
|
|
void handleParticles( void )
|
|
{
|
|
uint32_t time_now = millis();
|
|
|
|
// Check if we've been in the sleep state for long enough
|
|
if (PMS_STATE_ASLEEP == g_pms_state)
|
|
{
|
|
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("PMS: Waking up sensor");
|
|
pms.wakeUp();
|
|
g_pms_state_start = time_now;
|
|
g_pms_state = PMS_STATE_WAKING_UP;
|
|
}
|
|
}
|
|
|
|
// Check if we've been in the waking up state for long enough
|
|
if (PMS_STATE_WAKING_UP == g_pms_state)
|
|
{
|
|
if (time_now - g_pms_state_start >= (g_pms_warmup_period * 1000))
|
|
{
|
|
g_pms_state_start = time_now;
|
|
g_pms_state = PMS_STATE_READY;
|
|
}
|
|
}
|
|
|
|
// Put the most recent values into globals for reference elsewhere
|
|
if (PMS_STATE_READY == g_pms_state)
|
|
{
|
|
//pms.requestRead();
|
|
if (pms.readUntil(g_data))
|
|
{
|
|
g_pm1p0_sp.set(g_data.PM_SP_UG_1_0);
|
|
g_pm2p5_sp.set(g_data.PM_SP_UG_2_5);
|
|
g_pm10p0_sp.set(g_data.PM_SP_UG_10_0);
|
|
|
|
g_pm1p0_ae.set(g_data.PM_AE_UG_1_0);
|
|
g_pm2p5_ae.set(g_data.PM_AE_UG_2_5);
|
|
g_pm10p0_ae.set(g_data.PM_AE_UG_10_0);
|
|
|
|
// This condition below should NOT be required, but currently I get all
|
|
// 0 values for the PPD results every second time. This check only updates
|
|
// the global values if there is a non-zero result for any of the values:
|
|
if (g_data.PM_TOTALPARTICLES_0_3 + g_data.PM_TOTALPARTICLES_0_5 + g_data.PM_TOTALPARTICLES_1_0 + g_data.PM_TOTALPARTICLES_2_5 + g_data.PM_TOTALPARTICLES_5_0 + g_data.PM_TOTALPARTICLES_10_0 != 0)
|
|
{
|
|
g_pm0p3_ppd.set(g_data.PM_TOTALPARTICLES_0_3);
|
|
g_pm0p5_ppd.set(g_data.PM_TOTALPARTICLES_0_5);
|
|
g_pm1p0_ppd.set(g_data.PM_TOTALPARTICLES_1_0);
|
|
g_pm2p5_ppd.set(g_data.PM_TOTALPARTICLES_2_5);
|
|
g_pm5p0_ppd.set(g_data.PM_TOTALPARTICLES_5_0);
|
|
g_pm10p0_ppd.set(g_data.PM_TOTALPARTICLES_10_0);
|
|
g_pms_ppd_readings_taken = 1;
|
|
}
|
|
else
|
|
{
|
|
Serial.println("PMS: zero's issue");
|
|
}
|
|
pms.sleep();
|
|
|
|
// Report the new values
|
|
PMS_publishSensors();
|
|
|
|
g_pms_readings_taken = 1;
|
|
g_pms_state_start = time_now;
|
|
g_pms_state = PMS_STATE_ASLEEP;
|
|
}
|
|
}
|
|
}
|
|
|