Combining 2 software serials

Hello, I have 2 software serial devices, a gps and pm sensor, I ma only seeing the reading from the pm sensor and I think it's because the serial ports are interfering. I looked at the Arduino documentation but I don't know how to append the sample code to my code. I have attached my code below if anyone who know how you would go about this please let me know. Thanks!

#include <TinyGPSPlus.h>
#include <SoftwareSerial.h>
#include <STM32SD.h>
#include "Adafruit_PM25AQI.h"
SoftwareSerial pmSerial(6, 5);
#ifndef SD_DETECT_PIN
#define SD_DETECT_PIN SD_DETECT_NONE
#endif
Adafruit_PM25AQI aqi = Adafruit_PM25AQI();

static const int RXPin = 9, TXPin = 10;
static const uint32_t GPSBaud = 9600;

uint32_t A[] = { A0, A1, A2};

TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);
File dataFile;

void setup()
{
  ss.begin(GPSBaud);
  Serial.begin(9600);
  while (!Serial) {
    ;
  }
  Serial.print("Starting...");
  delay(1000);
  pmSerial.begin(9600);
  
  if (! aqi.begin_UART(&pmSerial)) { // connect to the sensor over software serial 
    Serial.println("Could not find PM 2.5 sensor!");
    while (1) delay(10);
  }

  Serial.println("PM25 found!");
  Serial.print("Initializing SD card...");
  while (!SD.begin(SD_DETECT_PIN))
  {
    delay(10);
  }
  delay(100);
  Serial.println("card initialized.");
  dataFile = SD.open("datalog.csv", FILE_WRITE);
  if (dataFile) {
    dataFile.seek(dataFile.size());
  }
  else {
    Serial.println("error opening datalog.csv");
  }

}

void loop() {
  PM25_AQI_Data data;
  if (! aqi.read(&data)) {
    Serial.println("Could not read from AQI");
    delay(250);
    return;
  }

  #define VBATPIN A6
  float measuredvbat = analogRead(VBATPIN);
  measuredvbat *= 2;    // we divided by 2, so multiply back
  measuredvbat *= 3.3;  // Multiply by 3.3V, our reference voltage
  measuredvbat /= 1024; // convert to voltage
  Serial.print("VBat: " ); Serial.println(measuredvbat);

static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;

  printInt(gps.satellites.value(), gps.satellites.isValid(), 5);
  printFloat(gps.hdop.hdop(), gps.hdop.isValid(), 6, 1);
  printFloat(gps.location.lat(), gps.location.isValid(), 11, 6);
  printFloat(gps.location.lng(), gps.location.isValid(), 12, 6);
  printInt(gps.location.age(), gps.location.isValid(), 5);
  printDateTime(gps.date, gps.time);
  printFloat(gps.altitude.feet(), gps.altitude.isValid(), 7, 2);
  printFloat(gps.course.deg(), gps.course.isValid(), 7, 2);
  printFloat(gps.speed.kmph(), gps.speed.isValid(), 6, 2);
  printStr(gps.course.isValid() ? TinyGPSPlus::cardinal(gps.course.deg()) : "*** ", 6);

  unsigned long distanceKmToLondon =
    (unsigned long)TinyGPSPlus::distanceBetween(
      gps.location.lat(),
      gps.location.lng(),
      LONDON_LAT, 
      LONDON_LON) / 1000;
  printInt(distanceKmToLondon, gps.location.isValid(), 9);

  double courseToLondon =
    TinyGPSPlus::courseTo(
      gps.location.lat(),
      gps.location.lng(),
      LONDON_LAT, 
      LONDON_LON);

  printFloat(courseToLondon, gps.location.isValid(), 7, 2);

  const char *cardinalToLondon = TinyGPSPlus::cardinal(courseToLondon);

  printStr(gps.location.isValid() ? cardinalToLondon : "*** ", 6);

  printInt(gps.charsProcessed(), true, 6);
  printInt(gps.sentencesWithFix(), true, 10);
  printInt(gps.failedChecksum(), true, 9);
  Serial.println();
  
  smartDelay(1000);

  if (millis() > 5000 && gps.charsProcessed() < 10)
    Serial.println(F("No GPS data received: check wiring"));

  Serial.println("AQI reading success");
  Serial.println(" ");
  Serial.print(F("PM 1.0: ")); Serial.print(data.pm10_env);
  Serial.print(F("\t\tPM 2.5: ")); Serial.print(data.pm25_env);
  Serial.print(F("\t\tPM 10: ")); Serial.println(data.pm100_env);
  Serial.println(" ");
  
  if (dataFile) {
//PM Values
    char buffer[10];  // -32768 + 0
    sprintf(buffer, "%d,", data.pm10_env);
    dataFile.println(" ,");
    dataFile.print(buffer);
    Serial.print ("PM 1.0: "); Serial.println(buffer);
    sprintf(buffer, "%d,", data.pm25_env);
    dataFile.print(buffer);
    Serial.print ("PM 2.5: "); Serial.println(buffer);
    sprintf(buffer, "%d,", data.pm100_env);
    dataFile.print(buffer);
    Serial.print ("PM 10: "); Serial.println(buffer);
    dataFile.print(",");
    
// GPS Data
    String lt(gps.location.lat(), 8);
    dataFile.print(lt.c_str());
    dataFile.print(",");
    String lo(gps.location.lng(), 8);
    dataFile.print(lo.c_str());
    dataFile.print(",");
    String datemonth(gps.date.month());
    dataFile.print(datemonth.c_str());
    dataFile.print("/");
    String dateday(gps.date.day());
    dataFile.print(dateday.c_str());
    dataFile.print("/");
    String dateyear(gps.date.year());
    dataFile.print(dateyear.c_str());
    dataFile.print(",");
    
    if (gps.time.hour() < 10) dataFile.print("0");
    String timehour(gps.time.hour());
    dataFile.print(timehour.c_str());
    dataFile.print(":");
    if (gps.time.minute() < 10) dataFile.print("0");
    String timemin(gps.time.minute());
    dataFile.print(timemin.c_str());
    dataFile.print(":");
    if (gps.time.second() < 10) dataFile.print("0");
    String timesecond(gps.time.second());
    dataFile.print(timesecond.c_str());
    dataFile.print(",");
    

    String alt(gps.altitude.feet(),7);
    dataFile.print(alt.c_str());
    dataFile.print(",");

  
    
// Clean up
    dataFile.flush();
    Serial.println("");
    Serial.print("File Size: ");
    Serial.println(dataFile.size());
    if (dataFile.size() < 10) {
      Serial.println("ERROR LOW FILE SIZE");
    }
    Serial.println("-------------------------------");
  }
  delay(100);
}
static void smartDelay(unsigned long ms)
{
  unsigned long start = millis();
  do 
  {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);
}

static void printFloat(float val, bool valid, int len, int prec)
{
  if (!valid)
  {
    while (len-- > 1)
      Serial.print('*');
    Serial.print(' ');
  }
  else
  {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1); // . and -
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
      Serial.print(' ');
  }
  smartDelay(0);
}

static void printInt(unsigned long val, bool valid, int len)
{
  char sz[32] = "*****************";
  if (valid)
    sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i=strlen(sz); i<len; ++i)
    sz[i] = ' ';
  if (len > 0) 
    sz[len-1] = ' ';
  Serial.print(sz);
  smartDelay(0);
}

static void printDateTime(TinyGPSDate &d, TinyGPSTime &t)
{
  if (!d.isValid())
  {
    Serial.print(F("********** "));
  }
  else
  {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year());
    Serial.print(sz);
  }
  
  if (!t.isValid())
  {
    Serial.print(F("******** "));
  }
  else
  {
    char sz[32];
    sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second());
    Serial.print(sz);
  }

  printInt(d.age(), d.isValid(), 5);
  smartDelay(0);
}

static void printStr(const char *str, int len)
{
  int slen = strlen(str);
  for (int i=0; i<len; ++i)
    Serial.print(i<slen ? str[i] : ' ');
  smartDelay(0);
}

Which Arduino board are you using?

Only one instance of Software Serial can be listening at any time. You have to perform the switch in code. Your first stop should always be to check the library docs!

I did check this but I don't see where to implement what in my code

Which board are you using? I see a reference to STM32SD and what appears to be code for an SD card.

I am using the STMF405 Feather board. and yes that is code for the sd card data logging

would changing the baud rate for one of them fix it?

Not familiar with that board, but it looks like it has multiple hardware serial ports.

So can I wire one to software serial and one to hardware serial and run it at the same time?

Lookup the pinout of the STMF405 Feather board

You will find there on wich IO-pins you can access the second and the third hardware-UART.

best regards Stefan

even when i tried developing a device that used the serial interface i developed the code using an Arduino Mega which has 4 serial interfaces. this allowed me to use the primary interface to upload and debug the code.

i added jumpers on the final device to disable it allowing me to program the device. and i wasn't able to directly debug the device which happen to use an RS-485 interface. the RS-485 interface allowed me to monitor messages which helped test it.

I tried changing the code to hardware serial but it gave me this error (Error compiling for board Generic STM32F4 series.). Here is my code...

/* Test sketch for Adafruit PM2.5 sensor with UART or I2C */

#include "Adafruit_PM25AQI.h"

// If your PM2.5 is UART only, 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 pmSerial(6, 5);

Adafruit_PM25AQI aqi = Adafruit_PM25AQI();

void setup() {
  // Wait for serial monitor to open
  Serial.begin(115200);
  while (!Serial) delay(10);

  Serial.println("Adafruit PMSA003I Air Quality Sensor");

  // Wait one second for sensor to boot up!
  delay(1000);

  // If using serial, initialize it and set baudrate before starting!
  // Uncomment one of the following
  Serial1.begin(115200);
  //pmSerial.begin(9600);

  // There are 3 options for connectivity!
  //if (! aqi.begin_I2C()) {      // connect to the sensor over I2C
  if (! aqi.begin_UART(&Serial1)) { // connect to the sensor over hardware serial
  //if (! aqi.begin_UART(&pmSerial)) { // connect to the sensor over software serial 
    Serial.println("Could not find PM 2.5 sensor!");
    while (1) delay(10);
  }

  Serial.println("PM25 found!");
}

void loop() {
  PM25_AQI_Data data;
  
  if (! aqi.read(&data)) {
    Serial.println("Could not read from AQI");
    delay(500);  // try again in a bit!
    return;
  }
  Serial.println("AQI reading success");

  Serial.println();
  Serial.println(F("---------------------------------------"));
  Serial.println(F("Concentration Units (standard)"));
  Serial.println(F("---------------------------------------"));
  Serial.print(F("PM 1.0: ")); Serial.print(data.pm10_standard);
  Serial.print(F("\t\tPM 2.5: ")); Serial.print(data.pm25_standard);
  Serial.print(F("\t\tPM 10: ")); Serial.println(data.pm100_standard);
  Serial.println(F("Concentration Units (environmental)"));
  Serial.println(F("---------------------------------------"));
  Serial.print(F("PM 1.0: ")); Serial.print(data.pm10_env);
  Serial.print(F("\t\tPM 2.5: ")); Serial.print(data.pm25_env);
  Serial.print(F("\t\tPM 10: ")); Serial.println(data.pm100_env);
  Serial.println(F("---------------------------------------"));
  Serial.print(F("Particles > 0.3um / 0.1L air:")); Serial.println(data.particles_03um);
  Serial.print(F("Particles > 0.5um / 0.1L air:")); Serial.println(data.particles_05um);
  Serial.print(F("Particles > 1.0um / 0.1L air:")); Serial.println(data.particles_10um);
  Serial.print(F("Particles > 2.5um / 0.1L air:")); Serial.println(data.particles_25um);
  Serial.print(F("Particles > 5.0um / 0.1L air:")); Serial.println(data.particles_50um);
  Serial.print(F("Particles > 10 um / 0.1L air:")); Serial.println(data.particles_100um);
  Serial.println(F("---------------------------------------"));
  

  delay(1000);
}

The error message certainly provided more information than that. Why not tell us everything? Post the complete error message.

Here it is...
Arduino: 1.8.19 (Mac OS X), Board: "Generic STM32F4 series, Adafruit Feather STM32F405, STM32CubeProgrammer (DFU), Enabled (generic 'Serial'), CDC (generic 'Serial' supersede U(S)ART), Low/Full Speed, Smallest (-Os default), None, Newlib Nano (default)"

/Users/name/Library/Arduino15/packages/STMicroelectronics/tools/xpack-arm-none-eabi-gcc/10.3.1-2.3/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: sketch/PMS5003TEST.ino.cpp.o: in function setup': PMS5003TEST.ino.cpp:(.text.setup+0x68): undefined reference to Serial1'
collect2: error: ld returned 1 exit status
Multiple libraries were found for "Adafruit_PM25AQI.h"
Used: /Users/name/Documents/Arduino/libraries/Adafruit_PM25AQI-master
Not used: /Users/name/Documents/Arduino/libraries/Adafruit_PM25_AQI_Sensor
exit status 1
Error compiling for board Generic STM32F4 series.

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

That seems pretty clear, no?
Looking at Adafruit's Guide:

image

Thank you this worked

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