Accessing multiple sensor data by serial communication using Arduino Software Serial Library

I am trying to read serial data from two sensors: PMS5003, for particulate matter measurement parameters; and Neo-6M GPS module for GPS location data using Arduino UNO micro-controller Board.
I have tried to fetch the data from these two sensors individually and it successfully working but the problem is arising when I am trying to read data from both the sensors at the same time, it is printing every value of the parameters as "0", defined in my function: displayData(). When I am commenting out "gpsSerial.begin(9600);", it is printing PMS5003 sensor values correctly. And When I am commenting out "pmsSerial.begin(9600);", it is printing GPS values correctly. I want to read data from both sensors at the same time. Please suggest to me the right direction for this. Thank you.

Following is the code:

#include <TinyGPS++.h>
TinyGPSPlus gps;

#include <SoftwareSerial.h>
const int RX1 = 4;
const int TX1 = 5;
const int RX2 = 2;
const int TX2 = 3;

SoftwareSerial gpsSerial(RX1,TX1);
SoftwareSerial pmsSerial(RX2,TX2);

uint16_t pm_10 = 0;
uint16_t pm_25 = 0;
uint16_t pm_100 = 0;

double glat = 0;
double glng = 0;
 
void setup() {
  // our debugging output
  Serial.begin(115200);
 
  //sensor baud rates
  gpsSerial.begin(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() { 
  
  gpsSerial.listen();
  
  while(gpsSerial.available() > 0) {
  
    //Serial.println("GPS Available!!!");
    if (gps.encode(gpsSerial.read()))
    {
      if (gps.location.isValid())
      {
        glat = gps.location.lat();
        glng = gps.location.lng(); 
      }
      else
      {
        Serial.println("Location : Not Available.");
      }
    }
  }
  
  pmsSerial.listen();
  
  while (pmsSerial.available() > 0) {

      Serial.println("PMS Available!!!");
      if (readPMSdata(&pmsSerial)) 
      {
        pm_10 = data.pm10_env;
        pm_25 = data.pm25_env;
        pm_100 = data.pm100_env;
        
      }
  }

  delay(500);
  displayData();
}

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];
  }
  
  // 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 displayData() {
  Serial.print("Latitude: ");
  Serial.println(glat);
  Serial.print("Longitude: ");
  Serial.println(glng);
  Serial.print("PM10: ");
  Serial.println(pm_10);
  Serial.print("PM25: ");
  Serial.println(pm_25);
  Serial.print("PM100: ");
  Serial.println(pm_100);
  Serial.println();
  Serial.println();
}

Welcome to the forum.

The Arduino Uno is great for timing, to control leds and relays. It is not good for your project.

The SoftwareSerial is a great library, but it should be used as a last resort. It takes over the Arduino Uno and there not much else that the sketch can do. It can not listen to two Serial ports at the same time.

A GPS module gives a lot of data, the Arduino Uno has only little SRAM.

There are many options, here are a few:

  • A Arduino Mega 2560 has some more memory and three spare hardware Serial ports.
  • A Arduino MKR Zero has one spare Serial port. It should be possible to activate a second Serial port, but that seems to be hard. I don't know the current status for that.
  • Some Teensy boards have extra Serial ports.
  • The ESP32 has two spare Serial ports.
  • The Raspberry Pi Pico has extra Serial ports. Some problems are reported. I don't know the current status.
  • The Arduino Leonardo (or Micro or Pro Micro) has a spare Serial port. If you add AltSoftSerial to that, then you can deal with two serial ports reasonably well. But I have doubts about the small amount of SRAM.

In your sketch there is a delay of 500ms. When reading serial data, the sketch should never wait. It should read the data as soon as data arrives.

If you want both serial interfaces working,and bufferning data, at the same time, use an Arduino with multiple hardware serial ports.

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