user40690: I working at air quality station. I measure particulate matter with PMS5003 and meteorological parameters with BME280. Everything seems to work just fine, but sometimes program hangs on checksum calculations.

I wonder if the problem lies either in my software or in hardware. Can anyone have a look at my code and tell me how I can improve it. Thanks in advance :)
Here's my code:

#include <Arduino.h>
#include <ESP8266WiFi.h>          //https://github.com/esp8266/Arduino

// needed for library
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>         //https://github.com/tzapu/WiFiManager
#include <PubSubClient.h>
#include <Wire.h>
#include <SPI.h>

// BME280 Sensor
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>


//Constants
#define TOKEN "TOKEN"
char thingsboardServer[] = "SERVER_ADDRESS";

// Settings for PMS5003
#define LENG 31  //0x42 + 31 bytes equal to 32 bytes
#define TIMEOUT 10000 //Microseconds to wait for PMS do wakeup

unsigned char buf[LENG];
char ergebnisstr[50];

struct dustvalues {
 unsigned int PM10Val=0; // Byte 4&5
 unsigned int PM2_5Val=0; // Byte 6&7
 unsigned int PM01Val=0; // Byte 8&9
 unsigned int Beyond03=0; // Byte 16&17
 unsigned int Beyond05=0; // Byte 18&19
 unsigned int Beyond1=0; // Byte 20&21
 unsigned int Beyond2_5=0; // Byte 22&23
 unsigned int Beyond5=0; //Byte 24&25
 unsigned int Beyond10=0; //Byte 26&27
};

struct dustvalues dustvalues1, dustvalues2;

//unsigned char gopassive[]={ 0x42, 0x4d, 0xe1, 0x00, 0x00, 0x01, 0x70 }; //don't need here
//unsigned char readinpassive[]={ 0x42, 0x4d, 0xe2, 0x00, 0x00, 0x01, 0x71 };
unsigned char gosleep[]={ 0x42, 0x4d, 0xe4, 0x00, 0x00, 0x01, 0x73 };
unsigned char gowakeup[]={ 0x42, 0x4d, 0xe4, 0x00, 0x01, 0x01, 0x74 };


// BME280 init
Adafruit_BME280 bme;

// Connection to PubSubClient
WiFiClient espClient;
PubSubClient client(espClient);

int status = WL_IDLE_STATUS;
unsigned long lastSend;

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

    wifiManager.autoConnect("AP", "pass");
    Serial.println("Connected to the network :)");
    delay(500);
    //  pins for RGB diode
    pinMode(12, OUTPUT);
    pinMode(13, OUTPUT);
    pinMode(14, OUTPUT);
    //BME280 sensor check
    if (! bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
    }
    // set server for MQTT PubSubClient Library
    client.setServer( thingsboardServer, 1883 );
    lastSend = 0;

}

void loop() {


    if (!client.connected()) {
    reconnect();
    }
    if ( millis() - lastSend > 30000 ) { // Update and send only after 1 seconds
    getpms5003();
    getAndSendTemperatureAndHumidityData();
    lastSend = millis();
    }
    client.loop();
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Connecting to ThingsBoard node ...");
    // Attempt to connect (clientId, username, password)
    if ( client.connect("Stacja3", TOKEN, NULL) ) {
      Serial.println( "[DONE]" );
    } else {
      Serial.print( "[FAILED] [ rc = " );
      Serial.print( client.state() );
      Serial.println( " : retrying in 5 seconds]" );
      // Wait 5 seconds before retrying
      delay( 5000 );
    }
  }
}

void getAndSendTemperatureAndHumidityData()
{
  Serial.println("Collecting temperature data.");

  // Reading temperature or humidity takes about 250 milliseconds!
  float humidity = bme.readHumidity();
  // Read temperature as Celsius (the default)
  float temperature = bme.readTemperature();

  float pressure = bme.readPressure() / 100.0;

  // Check if any reads failed and exit early (to try again).
  if (isnan(humidity) || isnan(temperature) || isnan(pressure)) {
    Serial.println("Failed to read from BME sensor!");
    return;
  }

  Serial.print("Humidity: ");
  Serial.print(humidity);
  Serial.print(" %\t");
  Serial.print("Temperature: ");
  Serial.print(temperature);
  Serial.print(" *C ");
  Serial.print("Pressure: ");
  Serial.print(pressure);
  Serial.print("hPa");

  String temperature1 = String(temperature);
  String humidity1 = String(humidity);
  String pressure1 = String(pressure);


  // Just debug messages
  Serial.print( "Sending temperature, humidity & pressure : [" );
  Serial.print( temperature1 ); Serial.print( "," );
  Serial.print( humidity1 ); Serial.print( "," );
  Serial.print( pressure1 );
  Serial.print( "]   -> " );

  // Prepare a JSON payload string
  String payload = "{";
  payload += "\"temperature\":"; payload += temperature1; payload += ",";
  payload += "\"humidity\":"; payload += humidity1;  payload += ",";
  payload += "\"pressure\":"; payload += pressure1;
  payload += "}";

  // Send payload
  char attributes[150];
  payload.toCharArray( attributes, 100 );
  client.publish( "v1/devices/me/telemetry", attributes );
  Serial.println( attributes );
}

bool checkValue(byte *buf, byte leng){
    int receiveSum, checkSum;
    for(byte i = 0; i < (leng - 2); i++){
        receiveSum += int(buf[i]);
    }
    receiveSum += 0x42;
    checkSum = (buf[leng-2] << 8) + buf[leng-1];
    testCheckValue(receiveSum, checkSum);
    if(receiveSum == checkSum){
        return true;
    }
    return false;
}

void testCheckValue(int calc, int found){
    byte strSize = 64;
    char strOut[strSize];
    snprintf(strOut, strSize, "Checksum Calculated: %d\nChecksum Found: %d\n", calc, found);
    Serial.print(strOut);
}


unsigned int transmitPM(char HighB, char LowB, unsigned char *buf){
 unsigned int PMValue;
 PMValue=((buf[HighB]<<8)+buf[LowB]);
 return PMValue;
}


void getpms5003(void){
  unsigned char found=0;

  Serial.println("PMS5003 Wakeup: ");
  Serial.write(gowakeup,7);
  Serial.println();
  Serial.println("gowakeup ist out");
  delay(30000); //Stable data should be got at least 30 Second from wakeup (Datasheet!)
  while (found<2){
   delay(TIMEOUT);
   if(Serial.available()>0){
    if(Serial.find(0x42)){  //start to read when detect 0x42
     Serial.println("0x42 found");
     Serial.readBytes(buf,LENG);
     if (buf[0] == 0x4d){ //second byte should be 0x4D
       found++;
       if(checkValue(buf,LENG)){
        Serial.println("Checksum okay");

        if(found==1){
         dustvalues1.PM01Val=transmitPM(3,4,buf);
         dustvalues1.PM2_5Val=transmitPM(5,6,buf);
         dustvalues1.PM10Val=transmitPM(7,8,buf);

         if (dustvalues1.PM2_5Val <= 36) {
           // digtal write green pin
           digitalWrite(12, LOW);
           // digitalWrite(13, HIGH);
           digitalWrite(14, HIGH);
         }

         if ((dustvalues1.PM2_5Val > 36 ) && (dustvalues1.PM2_5Val <= 80)) {
           // diode change to yellow
           digitalWrite(12, LOW);
           // digitalWrite(13, HIGH);
           digitalWrite(14, LOW);
         }

         if(dustvalues1.PM2_5Val > 84) {
           // diode change to red
           digitalWrite(12, HIGH);
           // digitalWrite(13, HIGH);
           digitalWrite(14, LOW);
         }


         sprintf(ergebnisstr,"PM2.5:%4dug/m3\nPM10: %4dug/m3\n",dustvalues1.PM2_5Val,dustvalues1.PM10Val);
         Serial.println(ergebnisstr);
         Serial.flush();

         // Just debug messages
         Serial.print( "Sending air quality PM2.5 & PM10 values: [" );
         Serial.print( dustvalues1.PM2_5Val ); Serial.print( "," );
         Serial.print( dustvalues1.PM10Val);
         Serial.print( "]   -> " );

         // Prepare a JSON payload string
         String payload = "{";
         payload += "\"pm25\":"; payload += String(dustvalues1.PM2_5Val); payload += ",";
         payload += "\"pm10\":"; payload += String(dustvalues1.PM10Val);
         payload += "}";

         // Send payload
         char attributes[100];
         payload.toCharArray( attributes, 100 );
         client.publish( "v1/devices/me/telemetry", attributes );
         Serial.println( attributes );
       }
        if(found==2){
         dustvalues2.PM01Val=transmitPM(3,4,buf);
         dustvalues2.PM2_5Val=transmitPM(5,6,buf);
         dustvalues2.PM10Val=transmitPM(7,8,buf);
         sprintf(ergebnisstr,"PM1: %4dug/m3\nPM2.5:%4dug/m3\nPM10: %4dug/m3\n",dustvalues2.PM01Val,dustvalues2.PM2_5Val,dustvalues2.PM10Val);
         Serial.println(ergebnisstr);
         Serial.flush();
        }
      }else{
       Serial.println("Checksum not okay");
       Serial.flush();
       if(found>0)found--;
       delay(500);
      }
     }
   }
   }
   }

  found=0;
  Serial.println("PMS5003 - go to sleep");
  Serial.write(gosleep,7);
  Serial.println();
 }

My hardware:

PMS 5003 Datasheet - http://www.aqmd.gov/docs/default-source/aq-spec/resources-page/plantower-pms5003-manual_v2-3.pdf

user32827: Cited from the documentation

Check code=Start character1+ Start character2+……..+data13 Low 8 bits

Please try to change the code as follows:
...
bool checkValue(byte *buf, byte leng){
    int receiveSum, checkSum;
    receiveSum += 0x42;
    for(byte i = 0; i < (leng - 2); i++){
        receiveSum += int(buf[i]);
        receiveSum = receiveSum & 0xFFFF;
    }

    checkSum = (buf[leng-2] << 8) + buf[leng-1];
    testCheckValue(receiveSum, checkSum);
    if(receiveSum == checkSum){
        return true;
    }
    return false;
}
...

Or use the updated code by the same author :PMS7003-on-Particle

40690: <p>I working at air quality station. I measure particulate matter with PMS5003 and meteorological parameters with BME280. Everything seems to work just fine, but sometimes program hangs on checksum calculations.</p>

<p><a href="https://i.stack.imgur.com/GPzMM.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/GPzMM.png" alt="enter image description here"></a></p>

<p>I wonder if the problem lies either in my software or in hardware. Can anyone have a look at my code and tell me how I can improve it. Thanks in advance :)</p>

<p>Here's my code:
</p>

<pre class="lang-cpp prettyprint-override"><code>#include &lt;Arduino.h&gt;
#include &lt;ESP8266WiFi.h&gt;          //https://github.com/esp8266/Arduino

// needed for library
#include &lt;DNSServer.h&gt;
#include &lt;ESP8266WebServer.h&gt;
#include &lt;WiFiManager.h&gt;         //https://github.com/tzapu/WiFiManager
#include &lt;PubSubClient.h&gt;
#include &lt;Wire.h&gt;
#include &lt;SPI.h&gt;

// BME280 Sensor
#include &lt;Adafruit_Sensor.h&gt;
#include &lt;Adafruit_BME280.h&gt;


//Constants
#define TOKEN "TOKEN"
char thingsboardServer[] = "SERVER_ADDRESS";

// Settings for PMS5003
#define LENG 31  //0x42 + 31 bytes equal to 32 bytes
#define TIMEOUT 10000 //Microseconds to wait for PMS do wakeup

unsigned char buf[LENG];
char ergebnisstr[50];

struct dustvalues {
 unsigned int PM10Val=0; // Byte 4&amp;5
 unsigned int PM2_5Val=0; // Byte 6&amp;7
 unsigned int PM01Val=0; // Byte 8&amp;9
 unsigned int Beyond03=0; // Byte 16&amp;17
 unsigned int Beyond05=0; // Byte 18&amp;19
 unsigned int Beyond1=0; // Byte 20&amp;21
 unsigned int Beyond2_5=0; // Byte 22&amp;23
 unsigned int Beyond5=0; //Byte 24&amp;25
 unsigned int Beyond10=0; //Byte 26&amp;27
};

struct dustvalues dustvalues1, dustvalues2;

//unsigned char gopassive[]={ 0x42, 0x4d, 0xe1, 0x00, 0x00, 0x01, 0x70 }; //don't need here
//unsigned char readinpassive[]={ 0x42, 0x4d, 0xe2, 0x00, 0x00, 0x01, 0x71 };
unsigned char gosleep[]={ 0x42, 0x4d, 0xe4, 0x00, 0x00, 0x01, 0x73 };
unsigned char gowakeup[]={ 0x42, 0x4d, 0xe4, 0x00, 0x01, 0x01, 0x74 };


// BME280 init
Adafruit_BME280 bme;

// Connection to PubSubClient
WiFiClient espClient;
PubSubClient client(espClient);

int status = WL_IDLE_STATUS;
unsigned long lastSend;

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

    wifiManager.autoConnect("AP", "pass");
    Serial.println("Connected to the network :)");
    delay(500);
    //  pins for RGB diode
    pinMode(12, OUTPUT);
    pinMode(13, OUTPUT);
    pinMode(14, OUTPUT);
    //BME280 sensor check
    if (! bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
    }
    // set server for MQTT PubSubClient Library
    client.setServer( thingsboardServer, 1883 );
    lastSend = 0;

}

void loop() {


    if (!client.connected()) {
    reconnect();
    }
    if ( millis() - lastSend &gt; 30000 ) { // Update and send only after 1 seconds
    getpms5003();
    getAndSendTemperatureAndHumidityData();
    lastSend = millis();
    }
    client.loop();
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Connecting to ThingsBoard node ...");
    // Attempt to connect (clientId, username, password)
    if ( client.connect("Stacja3", TOKEN, NULL) ) {
      Serial.println( "[DONE]" );
    } else {
      Serial.print( "[FAILED] [ rc = " );
      Serial.print( client.state() );
      Serial.println( " : retrying in 5 seconds]" );
      // Wait 5 seconds before retrying
      delay( 5000 );
    }
  }
}

void getAndSendTemperatureAndHumidityData()
{
  Serial.println("Collecting temperature data.");

  // Reading temperature or humidity takes about 250 milliseconds!
  float humidity = bme.readHumidity();
  // Read temperature as Celsius (the default)
  float temperature = bme.readTemperature();

  float pressure = bme.readPressure() / 100.0;

  // Check if any reads failed and exit early (to try again).
  if (isnan(humidity) || isnan(temperature) || isnan(pressure)) {
    Serial.println("Failed to read from BME sensor!");
    return;
  }

  Serial.print("Humidity: ");
  Serial.print(humidity);
  Serial.print(" %\t");
  Serial.print("Temperature: ");
  Serial.print(temperature);
  Serial.print(" *C ");
  Serial.print("Pressure: ");
  Serial.print(pressure);
  Serial.print("hPa");

  String temperature1 = String(temperature);
  String humidity1 = String(humidity);
  String pressure1 = String(pressure);


  // Just debug messages
  Serial.print( "Sending temperature, humidity &amp; pressure : [" );
  Serial.print( temperature1 ); Serial.print( "," );
  Serial.print( humidity1 ); Serial.print( "," );
  Serial.print( pressure1 );
  Serial.print( "]   -&gt; " );

  // Prepare a JSON payload string
  String payload = "{";
  payload += "\"temperature\":"; payload += temperature1; payload += ",";
  payload += "\"humidity\":"; payload += humidity1;  payload += ",";
  payload += "\"pressure\":"; payload += pressure1;
  payload += "}";

  // Send payload
  char attributes[150];
  payload.toCharArray( attributes, 100 );
  client.publish( "v1/devices/me/telemetry", attributes );
  Serial.println( attributes );
}

bool checkValue(byte *buf, byte leng){
    int receiveSum, checkSum;
    for(byte i = 0; i &lt; (leng - 2); i++){
        receiveSum += int(buf[i]);
    }
    receiveSum += 0x42;
    checkSum = (buf[leng-2] &lt;&lt; 8) + buf[leng-1];
    testCheckValue(receiveSum, checkSum);
    if(receiveSum == checkSum){
        return true;
    }
    return false;
}

void testCheckValue(int calc, int found){
    byte strSize = 64;
    char strOut[strSize];
    snprintf(strOut, strSize, "Checksum Calculated: %d\nChecksum Found: %d\n", calc, found);
    Serial.print(strOut);
}


unsigned int transmitPM(char HighB, char LowB, unsigned char *buf){
 unsigned int PMValue;
 PMValue=((buf[HighB]&lt;&lt;8)+buf[LowB]);
 return PMValue;
}


void getpms5003(void){
  unsigned char found=0;

  Serial.println("PMS5003 Wakeup: ");
  Serial.write(gowakeup,7);
  Serial.println();
  Serial.println("gowakeup ist out");
  delay(30000); //Stable data should be got at least 30 Second from wakeup (Datasheet!)
  while (found&lt;2){
   delay(TIMEOUT);
   if(Serial.available()&gt;0){
    if(Serial.find(0x42)){  //start to read when detect 0x42
     Serial.println("0x42 found");
     Serial.readBytes(buf,LENG);
     if (buf[0] == 0x4d){ //second byte should be 0x4D
       found++;
       if(checkValue(buf,LENG)){
        Serial.println("Checksum okay");

        if(found==1){
         dustvalues1.PM01Val=transmitPM(3,4,buf);
         dustvalues1.PM2_5Val=transmitPM(5,6,buf);
         dustvalues1.PM10Val=transmitPM(7,8,buf);

         if (dustvalues1.PM2_5Val &lt;= 36) {
           // digtal write green pin
           digitalWrite(12, LOW);
           // digitalWrite(13, HIGH);
           digitalWrite(14, HIGH);
         }

         if ((dustvalues1.PM2_5Val &gt; 36 ) &amp;&amp; (dustvalues1.PM2_5Val &lt;= 80)) {
           // diode change to yellow
           digitalWrite(12, LOW);
           // digitalWrite(13, HIGH);
           digitalWrite(14, LOW);
         }

         if(dustvalues1.PM2_5Val &gt; 84) {
           // diode change to red
           digitalWrite(12, HIGH);
           // digitalWrite(13, HIGH);
           digitalWrite(14, LOW);
         }


         sprintf(ergebnisstr,"PM2.5:%4dug/m3\nPM10: %4dug/m3\n",dustvalues1.PM2_5Val,dustvalues1.PM10Val);
         Serial.println(ergebnisstr);
         Serial.flush();

         // Just debug messages
         Serial.print( "Sending air quality PM2.5 &amp; PM10 values: [" );
         Serial.print( dustvalues1.PM2_5Val ); Serial.print( "," );
         Serial.print( dustvalues1.PM10Val);
         Serial.print( "]   -&gt; " );

         // Prepare a JSON payload string
         String payload = "{";
         payload += "\"pm25\":"; payload += String(dustvalues1.PM2_5Val); payload += ",";
         payload += "\"pm10\":"; payload += String(dustvalues1.PM10Val);
         payload += "}";

         // Send payload
         char attributes[100];
         payload.toCharArray( attributes, 100 );
         client.publish( "v1/devices/me/telemetry", attributes );
         Serial.println( attributes );
       }
        if(found==2){
         dustvalues2.PM01Val=transmitPM(3,4,buf);
         dustvalues2.PM2_5Val=transmitPM(5,6,buf);
         dustvalues2.PM10Val=transmitPM(7,8,buf);
         sprintf(ergebnisstr,"PM1: %4dug/m3\nPM2.5:%4dug/m3\nPM10: %4dug/m3\n",dustvalues2.PM01Val,dustvalues2.PM2_5Val,dustvalues2.PM10Val);
         Serial.println(ergebnisstr);
         Serial.flush();
        }
      }else{
       Serial.println("Checksum not okay");
       Serial.flush();
       if(found&gt;0)found--;
       delay(500);
      }
     }
   }
   }
   }

  found=0;
  Serial.println("PMS5003 - go to sleep");
  Serial.write(gosleep,7);
  Serial.println();
 }
</code></pre>

<p>My hardware:</p>

<p><a href="https://i.stack.imgur.com/WPIi6.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/WPIi6.jpg" alt="enter image description here"></a></p>

<p>PMS 5003 Datasheet - <a href="http://www.aqmd.gov/docs/default-source/aq-spec/resources-page/plantower-pms5003-manual_v2-3.pdf" rel="nofollow noreferrer">http://www.aqmd.gov/docs/default-source/aq-spec/resources-page/plantower-pms5003-manual_v2-3.pdf</a></p>
 32827: <p>Cited from the documentation</p>

<blockquote>
  <p>Check code=Start character1+ Start character2+……..+data13 Low 8 bits</p>
</blockquote>

<p>Please try to change the code as follows:</p>



<pre class="lang-c prettyprint-override"><code>...
bool checkValue(byte *buf, byte leng){
    int receiveSum, checkSum;
    receiveSum += 0x42;
    for(byte i = 0; i &lt; (leng - 2); i++){
        receiveSum += int(buf[i]);
        receiveSum = receiveSum &amp; 0xFFFF;
    }

    checkSum = (buf[leng-2] &lt;&lt; 8) + buf[leng-1];
    testCheckValue(receiveSum, checkSum);
    if(receiveSum == checkSum){
        return true;
    }
    return false;
}
...
</code></pre>

<p>Or use the updated code by the same author :<a href="https://github.com/MartyMacGyver/PMS7003-on-Particle/blob/master/pms7003-photon-demo-1/pms7003-photon-demo-1.ino" rel="nofollow noreferrer">PMS7003-on-Particle</a></p>
