Hi Particle community,
I've been reattempting to work with the Particle Air Quality Kit after purchasing it two years ago. As I work to achieve the goal of getting the data through an API call, I'm having some challenges. I'm able to see the variables through the API call, yet I'm receiving the results as "Int32" instead of the data. I thought the Particle.variable needs to be in the void loop() section, but that doesn't seem to be correct.
I would greatly appreciate it if someone could help me with this code process and let me know what I'm doing incorrectly. I reviewed the documentation and searched a number of posts, yet I'm not code proficient enough to understand what I'm doing wrong. Even if you can point me to a section in the docs to read on this to provide some guidance, this would be great.
Here's the original code I'm using with the addition of the code I added for the Particle.variable for temp, humidity, and pressure, listed as "//* Publish variables for API calls":
/*
* Project env-sensor-kit
* Description: Basic Tutorial project for the Particle Envrionmental Sensor Kit
* Author: Brandon Satrom <brandon@particle.io>
* Date: 09/16/2019
*/
#include "Particle.h"
SYSTEM_THREAD(ENABLED);
#include "Air_Quality_Sensor.h"
#include "Adafruit_BME280.h"
#include "SeeedOLED.h"
#include "JsonParserGeneratorRK.h"
#define AQS_PIN A2
#define DUST_SENSOR_PIN D4
#define SENSOR_READING_INTERVAL 30000
AirQualitySensor aqSensor(AQS_PIN);
Adafruit_BME280 bme;
unsigned long lastInterval;
unsigned long lowpulseoccupancy = 0;
unsigned long last_lpo = 0;
unsigned long duration;
float ratio = 0;
float concentration = 0;
int getBMEValues(int &temp, int &humidity, int &pressure);
void getDustSensorReadings();
String getAirQuality();
void createEventPayload(int temp, int humidity, int pressure, String airQuality);
void updateDisplay(int temp, int humidity, int pressure, String airQuality);
void setup()
{
Serial.begin(9600);
delay(50);
// Configure the dust sensor pin as an input
pinMode(DUST_SENSOR_PIN, INPUT);
if (aqSensor.init())
{
Serial.println("Air Quality Sensor ready.");
}
else
{
Serial.println("Air Quality Sensor ERROR!");
}
Wire.begin();
SeeedOled.init();
SeeedOled.clearDisplay();
SeeedOled.setNormalDisplay();
SeeedOled.setPageMode();
SeeedOled.setTextXY(2, 0);
SeeedOled.putString("Particle");
SeeedOled.setTextXY(3, 0);
SeeedOled.putString("Air Quality");
SeeedOled.setTextXY(4, 0);
SeeedOled.putString("Monitor");
if (bme.begin())
{
Serial.println("BME280 Sensor ready.");
}
else
{
Serial.println("BME280 Sensor ERROR!");
}
lastInterval = millis();
}
void loop()
{
int temp, pressure, humidity;
duration = pulseIn(DUST_SENSOR_PIN, LOW);
lowpulseoccupancy = lowpulseoccupancy + duration;
if ((millis() - lastInterval) > SENSOR_READING_INTERVAL)
{
String quality = getAirQuality();
Serial.printlnf("Air Quality: %s", quality.c_str());
getBMEValues(temp, pressure, humidity);
Serial.printlnf("Temp: %d", temp);
Serial.printlnf("Pressure: %d", pressure);
Serial.printlnf("Humidity: %d", humidity);
getDustSensorReadings();
updateDisplay(temp, humidity, pressure, quality);
createEventPayload(temp, humidity, pressure, quality);
lowpulseoccupancy = 0;
lastInterval = millis();
}
//* Publish variables for API calls
Particle.variable("Humidity2", humidity); //make humidity available via variable
Particle.variable("Temperature2", temp); //make temperature available via variable
Particle.variable("Pressure2", pressure); //make pressure available via variable
}
String getAirQuality()
{
int quality = aqSensor.slope();
String qual = "None";
if (quality == AirQualitySensor::FORCE_SIGNAL)
{
qual = "Danger";
}
else if (quality == AirQualitySensor::HIGH_POLLUTION)
{
qual = "High Pollution";
}
else if (quality == AirQualitySensor::LOW_POLLUTION)
{
qual = "Low Pollution";
}
else if (quality == AirQualitySensor::FRESH_AIR)
{
qual = "Fresh Air";
}
return qual;
}
int getBMEValues(int &temp, int &pressure, int &humidity)
{
temp = (int)bme.readTemperature();
pressure = (int)(bme.readPressure() / 100.0F);
humidity = (int)bme.readHumidity();
return 1;
}
void getDustSensorReadings()
{
// This particular dust sensor returns 0s often, so let's filter them out by making sure we only
// capture and use non-zero LPO values for our calculations once we get a good reading.
if (lowpulseoccupancy == 0)
{
lowpulseoccupancy = last_lpo;
}
else
{
last_lpo = lowpulseoccupancy;
}
ratio = lowpulseoccupancy / (SENSOR_READING_INTERVAL * 10.0); // Integer percentage 0=>100
concentration = 1.1 * pow(ratio, 3) - 3.8 * pow(ratio, 2) + 520 * ratio + 0.62; // using spec sheet curve
Serial.printlnf("LPO: %d", lowpulseoccupancy);
Serial.printlnf("Ratio: %f%%", ratio);
Serial.printlnf("Concentration: %f pcs/L", concentration);
}
void createEventPayload(int temp, int humidity, int pressure, String airQuality)
{
JsonWriterStatic<256> jw;
{
JsonWriterAutoObject obj(&jw);
jw.insertKeyValue("temp", temp);
jw.insertKeyValue("humidity", humidity);
jw.insertKeyValue("pressure", pressure);
jw.insertKeyValue("air-quality", airQuality);
if (lowpulseoccupancy > 0)
{
jw.insertKeyValue("dust-lpo", lowpulseoccupancy);
jw.insertKeyValue("dust-ratio", ratio);
jw.insertKeyValue("dust-concentration", concentration);
}
}
Particle.publish("env-vals", jw.getBuffer(), PRIVATE);
}
void updateDisplay(int temp, int humidity, int pressure, String airQuality)
{
SeeedOled.clearDisplay();
SeeedOled.setTextXY(0, 3);
SeeedOled.putString(airQuality);
SeeedOled.setTextXY(2, 0);
SeeedOled.putString("Temp: ");
SeeedOled.putNumber(temp);
SeeedOled.putString("C");
SeeedOled.setTextXY(3, 0);
SeeedOled.putString("Humidity: ");
SeeedOled.putNumber(humidity);
SeeedOled.putString("%");
SeeedOled.setTextXY(4, 0);
SeeedOled.putString("Press: ");
SeeedOled.putNumber(pressure);
SeeedOled.putString(" hPa");
if (concentration > 1)
{
SeeedOled.setTextXY(5, 0);
SeeedOled.putString("Dust: ");
SeeedOled.putNumber(concentration); // Will cast our float to an int to make it more compact
SeeedOled.putString(" pcs/L");
}
}
Thank you in advance for any advice!