PMS5003 checksum error with ESP8266 AT commands

I have a circuit with 3 sensors (1 is PMS5003) and an ESP8266 WiFi module (the small esp-01 variant). The code works when it's just the 3 sensors but when I added the ESP module, the PMS5003 sensor gives me checksum errors (it still works tho/all the sensors work except that the PMS5003 gives me either high or low values).

My code works so that the detected values from the sensors are sent by the ESP module to a web server through WiFi. I'm using AT commands for that. I want it to update in real-time, or at least every 15 seconds. I think the checksum error is because of the timing (?) or perhaps because it's the Arduino board is reading responses/outputs from both the PMS5003 and ESP8266 (I seriously don't know). I tried to adjust the timeout value and that didn't work. I also tried removing the espData function (?) and integrating it separately into each AT command but that didn't work either. I'm a beginner so I don't entirely know how the code for the PMS5003 sensor works. Does anyone know how to remove the checksum errors? My entire code is shown below.

#include <SoftwareSerial.h>      
SoftwareSerial espSerial(2, 3);  
#define DEBUG true

#include <dht.h>
#define dht_apin A1  
dht DHT;
int temp; 
int humi; 

int co2; 

SoftwareSerial pmsSerial (4,5); 
#include <Wire.h>
int pm25;
int pm251;

String mySSID = "ssid";
String myPWD = "password"; 
String myAPI = "api key"; 
String myHOST = "api.thingspeak.com";
String myPORT = "80";


void setup(){
  Serial.begin(115200); 
  espSerial.begin(115200);
  
  delay(500);
  
  espData("AT+RST", 1000, DEBUG);  
  espData("AT+CWMODE=1", 1000, DEBUG);
  espData("AT+CWJAP=\""+ mySSID +"\",\""+ myPWD +"\"", 1000, DEBUG); 
  /*while(!espSerial.find("OK")) 
  {          
      //Wait for connection
  }*/
  delay(1500);
  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;
  }
  
  // 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];
  }

  /* for 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;
}

void loop(){
   DHT.read11(dht_apin);
    
    temp = DHT.temperature;
    humi = DHT.humidity;
    co2 = analogRead(A0);

    if (readPMSdata(&pmsSerial)){
      pm25 = data.particles_25um; 
    
    String sendData = "GET /update?api_key="+ myAPI +"&field1=" + co2 + "&field2=" + String(pm25) + "&field3="+ String(temp) + "&field4=" + String(humi);
    Serial.println(sendData);
    espData("AT+CIPMUX=1", 150, DEBUG);     
    espData("AT+CIPSTART=0,\"TCP\",\""+ myHOST +"\","+ myPORT,150, DEBUG);
    espData("AT+CIPSEND=0," +String(sendData.length()+4),150,DEBUG);  
    espSerial.find(">"); 
    espSerial.println(sendData);
    /*Serial.println("Values to be sent: ");
    Serial.println("Carbon Dioxide current value: " + String(co2) + "ppm");
    Serial.println("Particulate Matter 2.5 Particles: " + String(pm25) + "μg/m³");
    Serial.println("Particulate Matter 2.5 Environmental Value: " + String(pm251) + "μg/m³");
    Serial.println("Temperature current value: " + String(temp) + "°C");
    Serial.println("Humidity current value: " + String(humi) + "%");
    Serial.println(sendData);*/
     
    espData("AT+CIPCLOSE=0",150,DEBUG);

    delay(150);
  }
}

String espData(String command, const int timeout, boolean debug)
{
  Serial.print("AT Command ==> ");
  Serial.print(command);
  Serial.println("     ");
  
  String response = "";
  espSerial.println(command);
  long int time = millis();
  while ( (time + timeout) > millis())
  {
    while (espSerial.available())
    {
      char c = espSerial.read();
      response += c;
    }
  }
  /*if (debug)
  {
    Serial.print(response);
  }*/
  return response;
  Serial.println("Response" + response);
}

Feel free to ask questions cuz I seriously need help thank you!

Which Arduino board are you using? It looks like you may be having trouble using multiple instances of software serial simultaneously.

I'm using an Arduino Uno Rev3 board.

I tried this and the software serial port for the PMS5003 sensor is not 'listening'. Is it perhaps because I didn't connect the RX pin for it?

Pin 4 is the RX pin and has to be connected, if that is what you mean.

You have to cleanly separate the activities of reading the sensor and communicating with the esp8266 then explicitly use the appropriate listen() method ( @juraj's link ) before those activities to force Software Serial to respond to the correct device.

If you still have problems, show your current code.

The one connected to pin 4 is the TX pin of the PMS5003 sensor. The RX pin is supposedly connected to pin 5 but I didn't connect it because I don't need it + the tutorial I followed didn't connect it either.

Also, thank you, I will try that first.

You impied in the OP that it was all working before you added the ESP8266 so the wiring for the sensors should be correct. However, something is not clear here.

SoftwareSerial pmsSerial (4,5);  // 4=RXpin, 5=TXpin

Except under special circumstances, the pins labeled RX and TX are crossed over. That is the TX pin on the sensor is connected to the RX pin on the Arduino. In other words, the sensor transmits data to the receiving pin of the Arduino.

What do you mean? The connections for the RX and TX pins of the sensor are crossed over. So, that would be TX of the sensor to RX of the Arduino. Should it be the other way around?

Sorry. I've read it again and your description is clearer than I originally thought.
Yes, It should be:

Arduino pin 4 (RX) <--  PMS5003 (TX)
Arduino pin 5 (TX) -->  PMS5003 (RX)   (optional ?)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.