I am relatively new to Arduino, being a longtime thinkerer I am used to searching for answers before posting, unfortunately in this case I believe my lack of understanding in c++ is getting the best of me and hence I ask for your help on the code for my air monitor project.
I am using an Arduino Uno, trying to run at the same time 5 sensors>
So far I have gotten to work the scd30 and the bmp 280 simultaneously, but when i try to merge the code for the pms i got an error (or i get for the sensor to print but with 0 as the only value).
I have connected the SCD30 to SCA and SDL, the BMP280 to A4 and A5, the PMS to 3 and 2 and the zp01 to A0 and A1.
I still need to connect and program the MQ131, my process has been to first check if i can run them individually then try to compile, if you have any suggestions on how to correctly due this I will reallly appreciate it.
My idea if sucesfull is to later move it to an esp32 board.
#include <SoftwareSerial.h>
SoftwareSerial pmsSerial(2, 3);
#include <Adafruit_SCD30.h>
#include <Adafruit_BMP280.h>
#include"AirQuality.h"
#include"Arduino.h"
AirQuality airqualitysensor;
int current_quality = -1;
#include <Wire.h>
#include <SPI.h>
#define BMP_SCK (13)
#define BMP_MISO (12)
#define BMP_MOSI (11)
#define BMP_CS (10;)
Adafruit_BMP280 bmp;// I2C
Adafruit_SCD30 scd30;
void setup(void) {
Serial.begin(115200);
airqualitysensor.init(A0);
Serial.println("Adafruit SCD30, BMP280 Y pms");
// Try to initialize!
if (!bmp.begin()) {
Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
while (1);
}
if (!scd30.begin()) {
Serial.println("Failed to find SCD30 chip");
while (1) {
delay(10);
}
if (!scd30.startContinuousMeasurement()) {
Serial.println("Failed to set ambient pressure offset");
while (1) {
}
}
Serial.print("Ambient pressure offset: ");
Serial.print(scd30.getAmbientPressureOffset());
Serial.println(" mBar");
}
Serial.println("SCD30 Found!");
// if (!scd30.setMeasurementInterval(10)){
// Serial.println("Failed to set measurement interval");
// while(1){ delay(10);}
// }
Serial.print("Measurement Interval: ");
Serial.print(scd30.getMeasurementInterval());
Serial.println(" seconds");
pmsSerial.begin(9600);
}
struct pms5003data {
uint16_t framelen;
uint16_t pm10_standard, pm25_standard, pm100_standard;
uint16_t pm10_env, pm25_env, pm100_env;
uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
uint16_t unused;
uint16_t checksum;
};
struct pms5003data data;
void loop()
{
;
(scd30.dataReady()) {
Serial.println("Data available!");
scd30.startContinuousMeasurement(bmp.readPressure() / 100);
if (!scd30.read()) {
Serial.println("Error reading sensor data");
return;
}
Serial.println("---------------------------------------");
Serial.print("SCD30Temperature: ");
Serial.print(scd30.temperature);
Serial.println(" degrees C");
Serial.print(F("BMP280Temperature = "));
Serial.print(bmp.readTemperature());
Serial.println(" *C");
Serial.print("Relative Humidity: ");
Serial.print(scd30.relative_humidity);
Serial.println(" %");
Serial.print(F("Pressure = "));
Serial.print(bmp.readPressure() / 100);
Serial.println(" mBar");
Serial.print("CO2: ");
Serial.print(scd30.CO2, 3);
Serial.println(" ppm");
Serial.print(F("Approx altitude = "));
Serial.print(bmp.readAltitude(1013.25)); /* Adjusted to local forecast! */
Serial.println(" m");
Serial.print(scd30.getAmbientPressureOffset());
Serial.println(" mBar");
};
}
if (readPMSdata(&pmsSerial)) {
// reading data was successful!
Serial.println();
Serial.println("---------------------------------------");
Serial.println("Concentration Units (standard)");
Serial.print("PM 1.0: "); Serial.print(data.pm10_standard);
Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_standard);
Serial.print("\t\tPM 10: "); Serial.println(data.pm100_standard);
Serial.println("---------------------------------------");
Serial.println("Concentration Units (environmental)");
Serial.print("PM 1.0: "); Serial.print(data.pm10_env);
Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_env);
Serial.print("\t\tPM 10: "); Serial.println(data.pm100_env);
Serial.println("---------------------------------------");
Serial.print("Particles > 0.3um / 0.1L air:"); Serial.println(data.particles_03um);
Serial.print("Particles > 0.5um / 0.1L air:"); Serial.println(data.particles_05um);
Serial.print("Particles > 1.0um / 0.1L air:"); Serial.println(data.particles_10um);
Serial.print("Particles > 2.5um / 0.1L air:"); Serial.println(data.particles_25um);
Serial.print("Particles > 5.0um / 0.1L air:"); Serial.println(data.particles_50um);
Serial.print("Particles > 10.0 um / 0.1L air:"); Serial.println(data.particles_100um);
current_quality = airqualitysensor.slope();
}
}
if (current_quality >= 0)// if a valid data returned.
{
if (current_quality == 0)
Serial.println("High pollution! Force signal active");
else if (current_quality == 1)
Serial.println("High pollution!");
else if (current_quality == 2)
Serial.println("Low pollution!");
else if (current_quality == 3)
Serial.println("Fresh air");
}
}
ISR(TIMER2_OVF_vect)
{
if (airqualitysensor.counter == 122) //set 2 seconds as a detected duty
{
airqualitysensor.last_vol = airqualitysensor.first_vol;
airqualitysensor.first_vol = analogRead(A0);
airqualitysensor.counter = 0;
airqualitysensor.timer_index = 1;
PORTB = PORTB ^ 0x20;
}
else
{
airqualitysensor.counter++;
}
}
}
boolean readPMSdata(Stream *s) {
if (! s->available()) {
return false;
}
// Read a byte at a time until we get to the special '0x42' start-byte
if (s->peek() != 0x42) {
s->read();
return false;
}
// Now read all 32 bytes
if (s->available() < 32) {
return false;
}
uint8_t buffer[32];
uint16_t sum = 0;
s->readBytes(buffer, 32);
// get checksum ready
for (uint8_t i = 0; i < 30; i++) {
sum += buffer[i];
}
/* debugging
for (uint8_t i=2; i<32; i++) {
Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
}
Serial.println();
*/
// The data comes in endian'd, this solves it so it works on all platforms
uint16_t buffer_u16[15];
for (uint8_t i = 0; i < 15; i++) {
buffer_u16[i] = buffer[2 + i * 2 + 1];
buffer_u16[i] += (buffer[2 + i * 2] << 8);
}
// put it into a nice struct :)
memcpy((void *)&data, (void *)buffer_u16, 30);
if (sum != data.checksum) {
Serial.println("Checksum failure");
return false;
}
// success!
return true;
}
If you Auto Format your code in the IDE part of it looks like this
Serial.println(" mBar");
};
}
if (readPMSdata(&pmsSerial))
{
// reading data was successful!
Serial.println();
Serial.println("---------------------------------------");
which shows that you have code starting with the if that is on the left margin and, hence, outside of a function. This is caused by the preceding } which is the end of the loop() function and should presumably not be there
However, the loop() function looks a mess.
void loop()
{
;
(scd30.dataReady())
What on Earth is that all about ?
Why the semicolon and the second { ?
Thanks for your help Helli, I really appreciate it,
Excuse the mess I have no background in coding, I auto formated and try to eliminate de extra semicolon, now I am getting that the data is not declared for if (readPMSdata(&pmsSerial)) {. I beleive it is declared in the second line of the code. How can i troubleshoot this>
#include <SoftwareSerial.h>
SoftwareSerial pmsSerial(2, 3);
#include <Adafruit_SCD30.h>
#include <Adafruit_BMP280.h>
#include"AirQuality.h"
#include"Arduino.h"
AirQuality airqualitysensor;
int current_quality = -1;
#include <Wire.h>
#include <SPI.h>
#define BMP_SCK (13)
#define BMP_MISO (12)
#define BMP_MOSI (11)
#define BMP_CS (10;)
Adafruit_BMP280 bmp;// I2C
Adafruit_SCD30 scd30;
void setup(void) {
Serial.begin(115200);
airqualitysensor.init(A0);
Serial.println("Adafruit SCD30, BMP280 Y pms");
// Try to initialize!
if (!bmp.begin()) {
Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
while (1);
}
if (!scd30.begin()) {
Serial.println("Failed to find SCD30 chip");
while (1) {
delay(10);
}
if (!scd30.startContinuousMeasurement()) {
Serial.println("Failed to set ambient pressure offset");
while (1) {
}
}
Serial.print("Ambient pressure offset: ");
Serial.print(scd30.getAmbientPressureOffset());
Serial.println(" mBar");
}
Serial.println("SCD30 Found!");
// if (!scd30.setMeasurementInterval(10)){
// Serial.println("Failed to set measurement interval");
// while(1){ delay(10);}
// }
Serial.print("Measurement Interval: ");
Serial.print(scd30.getMeasurementInterval());
Serial.println(" seconds");
pmsSerial.begin(9600);
}
struct pms5003data {
uint16_t framelen;
uint16_t pm10_standard, pm25_standard, pm100_standard;
uint16_t pm10_env, pm25_env, pm100_env;
uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
uint16_t unused;
uint16_t checksum;
};
struct pms5003data data;
void loop()
{
if (scd30.dataReady()) {
Serial.println("Data available!");
scd30.startContinuousMeasurement(bmp.readPressure() / 100);
if (!scd30.read())
Serial.println("Error reading sensor data");
return;
Serial.println("---------------------------------------");
Serial.print("SCD30Temperature: ");
Serial.print(scd30.temperature);
Serial.println(" degrees C");
Serial.print(F("BMP280Temperature = "));
Serial.print(bmp.readTemperature());
Serial.println(" *C");
Serial.print("Relative Humidity: ");
Serial.print(scd30.relative_humidity);
Serial.println(" %");
Serial.print(F("Pressure = "));
Serial.print(bmp.readPressure() / 100);
Serial.println(" mBar");
Serial.print("CO2: ");
Serial.print(scd30.CO2, 3);
Serial.println(" ppm");
Serial.print(F("Approx altitude = "));
Serial.print(bmp.readAltitude(1013.25)); /* Adjusted to local forecast! */
Serial.println(" m");
Serial.print(scd30.getAmbientPressureOffset());
Serial.println(" mBar");
}
if (readPMSdata(&pmsSerial)) {
// reading data was successful!
Serial.println();
Serial.println("---------------------------------------");
Serial.println("Concentration Units (standard)");
Serial.print("PM 1.0: "); Serial.print(data.pm10_standard);
Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_standard);
Serial.print("\t\tPM 10: "); Serial.println(data.pm100_standard);
Serial.println("---------------------------------------");
Serial.println("Concentration Units (environmental)");
Serial.print("PM 1.0: "); Serial.print(data.pm10_env);
Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_env);
Serial.print("\t\tPM 10: "); Serial.println(data.pm100_env);
Serial.println("---------------------------------------");
Serial.print("Particles > 0.3um / 0.1L air:"); Serial.println(data.particles_03um);
Serial.print("Particles > 0.5um / 0.1L air:"); Serial.println(data.particles_05um);
Serial.print("Particles > 1.0um / 0.1L air:"); Serial.println(data.particles_10um);
Serial.print("Particles > 2.5um / 0.1L air:"); Serial.println(data.particles_25um);
Serial.print("Particles > 5.0um / 0.1L air:"); Serial.println(data.particles_50um);
Serial.print("Particles > 10.0 um / 0.1L air:"); Serial.println(data.particles_100um);
current_quality = airqualitysensor.slope();
}
if (current_quality >= 0)// if a valid data returned.
{
if (current_quality == 0)
Serial.println("High pollution! Force signal active");
else if (current_quality == 1)
Serial.println("High pollution!");
else if (current_quality == 2)
Serial.println("Low pollution!");
else if (current_quality == 3)
Serial.println("Fresh air");
}
ISR(TIMER2_OVF_vect)
{
if (airqualitysensor.counter == 122) //set 2 seconds as a detected duty
{
airqualitysensor.last_vol = airqualitysensor.first_vol;
airqualitysensor.first_vol = analogRead(A0);
airqualitysensor.counter = 0;
airqualitysensor.timer_index = 1;
PORTB = PORTB ^ 0x20;
}
else
{
airqualitysensor.counter++;
}
}
boolean readPMSdata(Stream *s) {
if (! s->available()) {
return false;
}
// Read a byte at a time until we get to the special '0x42' start-byte
if (s->peek() != 0x42) {
s->read();
return false;
}
// Now read all 32 bytes
if (s->available() < 32) {
return false;
}
uint8_t buffer[32];
uint16_t sum = 0;
s->readBytes(buffer, 32);
// get checksum ready
for (uint8_t i = 0; i < 30; i++) {
sum += buffer[i];
}
/* debugging
for (uint8_t i=2; i<32; i++) {
Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
}
Serial.println();
*/
// The data comes in endian'd, this solves it so it works on all platforms
uint16_t buffer_u16[15];
for (uint8_t i = 0; i < 15; i++) {
buffer_u16[i] = buffer[2 + i * 2 + 1];
buffer_u16[i] += (buffer[2 + i * 2] << 8);
}
// put it into a nice struct :)
memcpy((void *)&data, (void *)buffer_u16, 30);
if (sum != data.checksum) {
Serial.println("Checksum failure");
return false;
}
// success!
return true;
}
};
Thank you Bill and AWOL
Here is the full error message:
Arduino: 1.8.13 (Windows 10), Board: "Arduino Uno"
C:\x\x\Documents\Arduino\sketch_mar10a\sketch_mar10a.ino: In function 'void loop()':
sketch_mar10a:98:7: error: 'readPMSdata' was not declared in this scope
if (readPMSdata(&pmsSerial)) {
^~~~~~~~~~~
In file included from C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:30:0,
from C:\Users\x\Documents\Arduino\libraries\Adafruit_SCD30/Adafruit_SCD30.h:19,
from C:\Users\x\Documents\Arduino\sketch_mar10a\sketch_mar10a.ino:3:
sketch_mar10a:133:3: error: expected unqualified-id before string constant
ISR(TIMER2_OVF_vect)
^
sketch_mar10a:134:3: error: a function-definition is not allowed here before '{' token
{
^
sketch_mar10a:149:35: error: a function-definition is not allowed here before '{' token
boolean readPMSdata(Stream * s) {
^
exit status 1
'readPMSdata' was not declared in this scope
This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
You will help yourself out a lot if you stick with the same method of doing anything. You can follow any number of "style guides" to help but it's a lot more important to be consistent. Just in setup alone, you have 3 different "patterns" for essentially initializing the first 3 sensors.
if (!bmp.begin()) {
Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
while (1);
}
if (!scd30.begin()) {
Serial.println("Failed to find SCD30 chip");
while (1) {
delay(10);
}
if (!scd30.startContinuousMeasurement()) {
Serial.println("Failed to set ambient pressure offset");
while (1) {
}
}
basically, one by one you initialize the sensor or print some string and then enter a never-ending loop, except because the second one adds a 10 second delay to that loop and you miss the closing brace, the third sensor initialize now only executes (hypothetically in an otherwise perfect world that doesn't exist) if the second sensor fails to....
If you structured your code so that the values returned by all sensor setup methods were evaluated together and 1 error message and 1 infinite loop, you would have a lot less "junk structure" to trudge through. Junk structure is all the "if something fails" code that when the program is actually working never gets executed, but feels so important to new coders.
if (!bmp.begin() && !scd30.begin() && !scd30.startContinuousMeasurement()) {
Serial.println("Houston, we have a problem. Preventing the shit from hitting the fan.");
while (1) ;
}
Wow guys,
You have been super helpful, I tried to clean some of the code and ran into memory issues( hence so many annotations, but now im stuck at meassurement interval on the serial monitor. I commented the Air Quality sensor section and PMS as I am now trying to get the SCD30 readings as a first step.
#include <SoftwareSerial.h>
SoftwareSerial pmsSerial(2, 3);
#include <Adafruit_SCD30.h>
#include <Adafruit_BMP280.h>
#include"AirQuality.h"
#include"Arduino.h"
AirQuality airqualitysensor;
int current_quality = -1;
#include <Wire.h>
#include <SPI.h>
#define BMP_SCK (13)
#define BMP_MISO (12)
#define BMP_MOSI (11)
#define BMP_CS (10;)
Adafruit_BMP280 bmp;// I2C
Adafruit_SCD30 scd30;
void setup(void) {
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println("SCD30, BMP280 & pms");
//airqualitysensor.init(A0);
// Try to initialize!
if (!bmp.begin() && !scd30.begin() && !scd30.startContinuousMeasurement()) {
Serial.println("Houston, we have a problem.");
delay(10);
}
/*Serial.print("Ambient pressure offset: ");
Serial.print(scd30.getAmbientPressureOffset());
delay(20);
Serial.println(" mBar");
Serial.println("SCD30 Found!");*/
Serial.print("Ambient pressure offset: ");
Serial.print(scd30.getAmbientPressureOffset());
Serial.println(" mBar");
Serial.print("Measurement Interval: ");
Serial.print(scd30.getMeasurementInterval());
Serial.println(" seconds");
delay(10);
pmsSerial.begin(9600);
}
/*struct pms5003data {
uint16_t framelen;
uint16_t pm10_standard, pm25_standard, pm100_standard;
uint16_t pm10_env, pm25_env, pm100_env;
uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
uint16_t unused;
uint16_t checksum;
};
struct pms5003data data;
boolean readPMSdata(Stream * s) {
if (! s->available()) {
return false;
}
// Read a byte at a time until we get to the special '0x42' start-byte
if (s->peek() != 0x42) {
s->read();
return false;
}
// Now read all 32 bytes
if (s->available() < 32) {
return false;
}
uint8_t buffer[32];
uint16_t sum = 0;
s->readBytes(buffer, 32);
// get checksum ready
for (uint8_t i = 0; i < 30; i++) {
sum += buffer[i];
}
//debugging
for (uint8_t i = 2; i < 32; i++) {
Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
}
Serial.println();
// The data comes in endian'd, this solves it so it works on all platforms
uint16_t buffer_u16[15];
for (uint8_t i = 0; i < 15; i++) {
buffer_u16[i] = buffer[2 + i * 2 + 1];
buffer_u16[i] += (buffer[2 + i * 2] << 8);
}
// put it into a nice struct :)
memcpy((void *)&data, (void *)buffer_u16, 30);
f (sum != data.checksum) {
Serial.println("Checksum failure");
return false;
}
// success!
return true;
}*/
void loop()
{
if (scd30.dataReady()) {
Serial.println("Data available SCD30");
if (!bmp.readPressure()) {
Serial.println("Error reading sensor data BMP 280");
return;
}
scd30.startContinuousMeasurement(bmp.readPressure() / 100);
if (!scd30.read()) {
Serial.println("Error reading sensor data");
return;
}
}
/* if (!readPMSdata(&pmsSerial)) {
Serial.println("Error reading sensor data PMS");
return ;
}*/
Serial.println("---------------------------------------");
Serial.print("SCD30Temperature: ");
Serial.print(scd30.temperature);
Serial.println(" degrees C");
Serial.print(F("BMP280Temperature = "));
Serial.print(bmp.readTemperature());
Serial.println(" *C");
Serial.print("Relative Humidity: ");
Serial.print(scd30.relative_humidity);
Serial.println(" %");
Serial.print(F("Pressure = "));
Serial.print(bmp.readPressure() / 100);
Serial.println(" mBar");
Serial.print("CO2: ");
Serial.print(scd30.CO2, 3);
Serial.println(" ppm");
Serial.print(F("Approx altitude = "));
Serial.print(bmp.readAltitude(1013.25)); /* Adjusted to local forecast! */
Serial.println(" m");
Serial.print(scd30.getAmbientPressureOffset());
Serial.println(" mBar");
Serial.println();
Serial.println("---------------------------------------");
/*Serial.println("Concentration Units (standard)");
Serial.print("PM 1.0: "); Serial.print(data.pm10_standard);
Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_standard);
Serial.print("\t\tPM 10: "); Serial.println(data.pm100_standard);
Serial.println("---------------------------------------");
Serial.println("Concentration Units (environmental)");
Serial.print("PM 1.0: "); Serial.print(data.pm10_env);
Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_env);
Serial.print("\t\tPM 10: "); Serial.println(data.pm100_env);
Serial.println("---------------------------------------");
Serial.print("Particles > 0.3um / 0.1L air:"); Serial.println(data.particles_03um);
Serial.print("Particles > 0.5um / 0.1L air:"); Serial.println(data.particles_05um);
Serial.print("Particles > 1.0um / 0.1L air:"); Serial.println(data.particles_10um);
Serial.print("Particles > 2.5um / 0.1L air:"); Serial.println(data.particles_25um);
Serial.print("Particles > 5.0um / 0.1L air:"); Serial.println(data.particles_50um);
Serial.print("Particles > 10.0 um / 0.1L air:"); Serial.println(data.particles_100um);
}*/
/* current_quality = airqualitysensor.slope();
if (current_quality >= 0)// if a valid data returned.
{
if (current_quality == 0)
Serial.println("High pollution! Force signal active");
else if (current_quality == 1)
Serial.println("High pollution!");
else if (current_quality == 2)
Serial.println("Low pollution!");
else if (current_quality == 3)
Serial.println("Fresh air");
}
}
ISR(TIMER2_OVF_vect)
{
if (airqualitysensor.counter == 122) //set 2 seconds as a detected duty
{
airqualitysensor.last_vol = airqualitysensor.first_vol;
airqualitysensor.first_vol = analogRead(A0);
airqualitysensor.counter = 0;
airqualitysensor.timer_index = 1;
PORTB = PORTB ^ 0x20;
}
else
{
airqualitysensor.counter++;
}
}*/
}
Can you help me identify why is the program not displaying information?
Monitor shows:
16:54:01.491 -> SCD30, BMP280 & pms
16:54:01.583 -> Ambient pressure offset: ⸮5908 mBar
16:54:01.583 -> Measurement Interval:
And does not run the loop or print anymore data
You have a lot of Serial.prints which can delay the loop.
Check out my Arduino Serial I/O for the Real World which covers this problem and shows you how to measure the time it takes your loop to run hence the measurement interval.
Although your immediate problem looks to be a different one.
Dear Forum,
Your help has been crucial on my project, I have got it to work and Read 3 of the sensors however I beleive I have an issue synching the PMS Sensor and the SCD30, so I am asking for your help on suggesting how can I code a Delay that makes sure data is only collected when available?
#include <SoftwareSerial.h>
SoftwareSerial pmsSerial(2, 3);
#include <Adafruit_SCD30.h>
#include <Adafruit_BMP280.h>
#include"AirQuality.h"
#include"Arduino.h"
AirQuality airqualitysensor;
int current_quality = -1;
#include <Wire.h>
#include <SPI.h>
#define BMP_SCK (13)
#define BMP_MISO (12)
#define BMP_MOSI (11)
#define BMP_CS (10;)
Adafruit_BMP280 bmp;// I2C
Adafruit_SCD30 scd30;
void setup(void) {
Serial.begin(115200);
while (!Serial);
Serial.println("SCD30, BMP280 & pms");
delay(100);
//airqualitysensor.init(A0);
// Try to initialize!
if (bmp.begin() && scd30.begin() && scd30.startContinuousMeasurement()) {
delay(200);
Serial.println("Failed to initialize");
};
Serial.print("Ambient pressure offset: ");
Serial.print(scd30.getAmbientPressureOffset());
Serial.println(" mBar");
Serial.print("Measurement Interval: ");
Serial.print(scd30.getMeasurementInterval());
Serial.println(" seconds");
pmsSerial.begin(9600);
}
struct pms5003data {
uint16_t framelen;
uint16_t pm10_standard, pm25_standard, pm100_standard;
uint16_t pm10_env, pm25_env, pm100_env;
uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
uint16_t unused;
uint16_t checksum;
};
struct pms5003data data;
boolean readPMSdata(Stream * s) {
if (! s->available()) {
return false;
}
// Read a byte at a time until we get to the special '0x42' start-byte
if (s->peek() != 0x42) {
s->read();
return false;
}
// Now read all 32 bytes
if (s->available() < 32) {
return false;
}
uint8_t buffer[32];
uint16_t sum = 0;
s->readBytes(buffer, 32);
// get checksum ready
for (uint8_t i = 0; i < 30; i++) {
sum += buffer[i];
}
//debugging
/*for (uint8_t i = 2; i < 32; i++) {
Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
}
Serial.println();*/
// The data comes in endian'd, this solves it so it works on all platforms
uint16_t buffer_u16[15];
for (uint8_t i = 0; i < 15; i++) {
buffer_u16[i] = buffer[2 + i * 2 + 1];
buffer_u16[i] += (buffer[2 + i * 2] << 8);
}
// put it into a nice struct :)
memcpy((void *)&data, (void *)buffer_u16, 30);
delay(200);
if (sum != data.checksum) {
Serial.println("Checksum failure");
return false;
}
// success!
return true;
};
void loop()
{
if (scd30.dataReady()) {
Serial.println("Data available SCD30");
if (!bmp.readPressure()) {
Serial.println("Error reading sensor data BMP 280");
return;
}
scd30.startContinuousMeasurement(bmp.readPressure() / 100);
if (!scd30.read()) {
Serial.println("Error setting pressure offset");
return;
}
}
if (!readPMSdata(&pmsSerial)) {
Serial.println("Error reading sensor data PMS");
return ;
}
Serial.println("---------------------------------------");
Serial.print("SCD30Temperature: ");
Serial.print(scd30.temperature);
Serial.println(" degrees C");
Serial.print(F("BMP280Temperature = "));
Serial.print(bmp.readTemperature());
Serial.println(" *C");
Serial.print("Relative Humidity: ");
Serial.print(scd30.relative_humidity);
Serial.println(" %");
Serial.print(F("Pressure = "));
Serial.print(bmp.readPressure() / 100);
Serial.println(" mBar");
Serial.print("CO2: ");
Serial.print(scd30.CO2, 3);
Serial.println(" ppm");
Serial.print(F("Approx altitude = "));
Serial.print(bmp.readAltitude(1013.25)); /* Adjusted to local forecast! */
Serial.println(" m");
Serial.print(scd30.getAmbientPressureOffset());
Serial.println(" mBar");
Serial.println();
Serial.println("---------------------------------------");
Serial.println("Concentration Units (standard)");
Serial.print("PM 1.0: "); Serial.print(data.pm10_standard);
Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_standard);
Serial.print("\t\tPM 10: "); Serial.println(data.pm100_standard);
Serial.println("---------------------------------------");
Serial.println("Concentration Units (environmental)");
Serial.print("PM 1.0: "); Serial.print(data.pm10_env);
Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_env);
Serial.print("\t\tPM 10: "); Serial.println(data.pm100_env);
Serial.println("---------------------------------------");
Serial.print("Particles > 0.3um / 0.1L air:"); Serial.println(data.particles_03um);
Serial.print("Particles > 0.5um / 0.1L air:"); Serial.println(data.particles_05um);
Serial.print("Particles > 1.0um / 0.1L air:"); Serial.println(data.particles_10um);
Serial.print("Particles > 2.5um / 0.1L air:"); Serial.println(data.particles_25um);
Serial.print("Particles > 5.0um / 0.1L air:"); Serial.println(data.particles_50um);
Serial.print("Particles > 10.0 um / 0.1L air:"); Serial.println(data.particles_100um);
Serial.println("---------------------------------------");
delay(2000);
}
/* current_quality = airqualitysensor.slope();
if (current_quality >= 0)// if a valid data returned.
{
if (current_quality == 0)
Serial.println("High pollution! Force signal active");
else if (current_quality == 1)
Serial.println("High pollution!");
else if (current_quality == 2)
Serial.println("Low pollution!");
else if (current_quality == 3)
Serial.println("Fresh air");
}
}
ISR(TIMER2_OVF_vect)
{
if (airqualitysensor.counter == 122) //set 2 seconds as a detected duty
{
airqualitysensor.last_vol = airqualitysensor.first_vol;
airqualitysensor.first_vol = analogRead(A0);
airqualitysensor.counter = 0;
airqualitysensor.timer_index = 1;
PORTB = PORTB ^ 0x20;
}
else
{
airqualitysensor.counter++;
}
}*/
As you can see In the monitor (attached a file) the sensors post but only aftr a couple of seconds:
Your help is much appreciated