PMS5003 Serial Output Data to SD Issues I'm trying to save the output of an air quality sensor to a SD card, but I'm having a few issues. 

The sensor I'm using is a Plantower PMS5003 which puts out its data via serial. I've heavily tweaked the example sketch from Adafruit (here) as I'd like to use the Low Power library to sleep the unit, take a sample and note the time, write it to SD, then return to sleep. 

I am getting the timestamp written no issue, but the data is coming out repeated as below:

22:13:10 - 34,55,61
22:13:18 - 34,55,61
22:13:27 - 34,55,61
22:13:36 - 34,55,61
22:13:44 - 34,55,61
22:13:53 - 34,55,61
22:14:1 - 34,55,61
22:14:10 - 34,55,61
22:14:18 - 34,55,61
22:14:27 - 34,55,61
22:14:35 - 34,55,61
22:14:44 - 34,55,61


The 8s timer appears to be working fine, but the repetition of data has me confused. I've tried adding delays and the like in case it was a lack of data but when I run that example sketch it comes screaming in over serial. 

I also ditched using the software serial as I couldn't get it to stop messing with the low power library, it wouldn't ever sleep. 

That and any general advice on the sketch is appreciated, it seems like its not the best way to accomplish this.

#include "LowPower.h"
#include &lt;SdFat.h&gt;
#include "RTClib.h"
#include &lt;Wire.h&gt;

SdFat SD;
RTC_DS3231 rtc;

File test;
String tString = "";
String sString = "";

void setup() {
  Serial.begin(9600);

  pinMode(10, OUTPUT);

  if (!rtc.begin()) while (1);

  if (!SD.begin(10)) while (1);
}

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() {
  //LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF, SPI_OFF, USART0_OFF, TWI_OFF);
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);


  DateTime now = rtc.now();
  test = SD.open("test.txt", FILE_WRITE);

  tString = String(now.hour()) + ":" + String(now.minute()) + ":" + String(now.second()) + " - ";

  readPMSdata(&amp;Serial);
  sString = String(data.pm10_standard) + "," + String(data.pm25_standard) + "," + String(data.pm100_standard);

if (test) {
  test.print(tString);
  test.println(sString);
  test.close();

  delay(250);
}
}

boolean readPMSdata(Stream *s) {
  if (! s-&gt;available()) {
    return false;
  }

  // Read a byte at a time until we get to the special '0x42' start-byte
  if (s-&gt;peek() != 0x42) {
    s-&gt;read();
    return false;
  }

  // Now read all 32 bytes
  if (s-&gt;available() &lt; 32) {
    return false;
  }

  uint8_t buffer[32];
  uint16_t sum = 0;
  s-&gt;readBytes(buffer, 32);

  // get checksum ready
  for (uint8_t i = 0; i &lt; 30; i++) {
    sum += buffer[i];
  }

  //debugging
  for (uint8_t i = 2; i &lt; 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 &lt; 15; i++) {
    buffer_u16[i] = buffer[2 + i * 2 + 1];
    buffer_u16[i] += (buffer[2 + i * 2] &lt;&lt; 8);
  }

  // put it into a nice struct :)
  memcpy((void *)&amp;data, (void *)buffer_u16, 30);

  if (sum != data.checksum) {
    Serial.println("Checksum failure");
    return false;
  }
  // success!
  return true;
}
There is a mismatch in the code.
The Arduino loop function assumes that readPMSdata needs to be called just once for valid data but the function readPMSdata itself assumes that it will be called over and over again until a enough bytes are received and are valid.

The solution is to let the Arduino loop call readPMSdata over and over again, until it has valid data. It returns true when it has valid data, so that can be used in a if statement.
This might cause troubles with the rest of the code in the loop. The delay(250); may no longer be used and I don't know the best place to go into sleep mode. Therefor I removed the powerdown.

void loop() {
  if( readPMSdata(&amp;Serial))        // call it many times to collect data
  {
    // there is valid data from the sensor
    DateTime now = rtc.now();
    test = SD.open("test.txt", FILE_WRITE);

    tString = String(now.hour()) + ":" + String(now.minute()) + ":" + String(now.second()) + " - ";

    sString = String(data.pm10_standard) + "," + String(data.pm25_standard) + "," + String(data.pm100_standard);

    if (test) {
      test.print(tString);
      test.println(sString);
      test.close();
  }
}