0

PM2.5 Sensor Reading
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

PM2.5 Sensor Reading

by rumba on Mon Apr 15, 2019 9:47 am

Hi all,
I'm successfully connecting a PM2.5 Air Quality sensor to a Feather Huzzah and getting good readings using the Adafruit example code below. Only issue is it reads and Serial.prints every second. However I want it to give a reading every 10 seconds. I've tried to insert a delay and a timer in various places in the code, but I get a bunch of checksum errors and the output becomes unstable.

Can someone please point me in the right direction how to delay the reading? I realize I'm not quite understanding how the buffer or Stream is working. Thanks!

Code: Select all | TOGGLE FULL SIZE
// On Leonardo/Micro or others with hardware serial, use those!
// uncomment this line:
// #define pmsSerial Serial1

// For UNO and others without hardware serial, we must use software serial...
// pin #2 is IN from sensor (TX pin on sensor), leave pin #3 disconnected
// comment these two lines if using hardware serial
#include <SoftwareSerial.h>
SoftwareSerial pmsSerial(2, 3);

void setup() {
  // our debugging output
  Serial.begin(115200);

  // sensor baud rate is 9600
  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 (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);
    Serial.println("---------------------------------------");
  }
}

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;
}

rumba
 
Posts: 7
Joined: Thu Jul 12, 2007 12:02 am

Re: PM2.5 Sensor Reading

by franklin97355 on Mon Apr 15, 2019 12:19 pm

What happens when you try this?
Code: Select all | TOGGLE FULL SIZE
void loop() {
  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);
    Serial.println("---------------------------------------");
  }
delay(10000);
}

franklin97355
 
Posts: 20246
Joined: Mon Apr 21, 2008 2:33 pm
Location: Lacomb, OR.

Re: PM2.5 Sensor Reading

by rumba on Mon Apr 15, 2019 6:21 pm

When I do that it prints out one or two "checksum failure" in between readings. See image of Serial Monitor. And even though it continues to give readings I'd like to clean it up. btw, I commented out all the Particles readings except for one row so it's easier to see.
Attachments
Screen Shot 2019-04-15 at 6.09.14 PM.png
Screen Shot 2019-04-15 at 6.09.14 PM.png (90.53 KiB) Viewed 31 times

rumba
 
Posts: 7
Joined: Thu Jul 12, 2007 12:02 am

Re: PM2.5 Sensor Reading

by franklin97355 on Mon Apr 15, 2019 8:35 pm

Then try this
Code: Select all | TOGGLE FULL SIZE
void loop() {
  if (readPMSdata(&pmsSerial)) {
    // reading data was successful!
   if (millis() - long lastmillis >= 10000L {
      lastmillis = millis();
      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("---------------------------------------");
   }
  }
}
I'm not a coder so I'm just trying things.

franklin97355
 
Posts: 20246
Joined: Mon Apr 21, 2008 2:33 pm
Location: Lacomb, OR.

Please be positive and constructive with your questions and comments.