SoftwareSerial problems

Hello Arduino forums,
Forgive the wall of text, I want to be thorough in my problem.
I have 4 https://www.atlas-scientific.com/product_pages/embedded/ph.html ph stamps connected to a Mega. I am using SoftwareSerial to communicate.
If I use the basic code from atlas all four sensors work just fine, so my circuits are all built properly.
If I use the code (added below) and comment out 3 of the four functions to read the sensors they will each work when hooked up to the Mega.
My problem is when I hook up all 4 sensors they stop functioning. No LED on the pH stamp and no output to the serial monitor.
I am wondering if SoftwareSerial is particularly sensitive to crosstalk?

/*************************************************************************************
/Automatic pH Data Recovery
/Written by T & T
/Base of code taken from Atlast Scientific's test code
/Using the software serial header, the program reads pH values automatically
/and stores them in their own floats. Then using GET requests, the information
/is sent to a local server, and hosted online.
***********************************************************************************/
#include <SoftwareSerial.h>
#include <SPI.h>
#include <Ethernet.h>

//Ethernet Setup\\
byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0x64, 0xCB};
byte subnet[] = { 255, 255, 255, 0};
byte gateway[] = {142, 237, 42, 1};
IPAddress ip(142, 237, 42, 11);
IPAddress server(142, 237, 42, 10);

EthernetClient client; //defaulted to port 80

SoftwareSerial pHsensor1 (50, 51);                                             // 50 connects to TX on chip, 51 to RX
SoftwareSerial pHsensor2 (52, 53);                                             // 52 connects to TX on chip, 53 to RX
SoftwareSerial pHsensor3 (10, 11);                                             // 10 connects to TX on chip, 11 to RX
SoftwareSerial pHsensor4 (12, 13);                                             // 12 connects to TX on chip, 13 to RX
String inputstring = "";                                                       //a string to hold incoming data from the PC
String sensorstring = "";                                                      //a string to hold the data from the Atlas Scientific product
boolean input_stringcomplete = false;                                          //have we received all the data from the PC
boolean sensor_stringcomplete = false;                                         //have we received all the data from the Atlas Scientific product
float pHsense1, pHsense2, pHsense3, pHsense4;                                  // Converted values for the pH readings
char charBuf[10];                                                              // An array to hold the values 
int x, y, z, v;                                                                // Forloop counter variables

void setup(){                                                                  //set up the hardware
  Serial.begin(38400);
  Ethernet.begin(mac, ip);
    if(client.connect(server, 80)) 
      {
        Serial.println("Connection Successful");
        char serverSend[140];
        sprintf (serverSend, "GET /Arduino.php?soilph1=%d&soilph2=%d&soilph3=%d&waterph",pHsense1, pHsense2, pHsense3, pHsense4);
        client.print(serverSend);
        client.println("");
      }
     else
     { 
       Serial.println("Connection Failed yo");        
  pHsensor1.begin(38400);                                                     //set baud rate for software serial port_3 to 38400
  pHsensor2.begin(38400); 
  pHsensor3.begin(38400);
  pHsensor4.begin(38400);
  inputstring.reserve(5);                                                   //set aside some bytes for receiving data from the PC
  sensorstring.reserve(30);                                                 //set aside some bytes for receiving data from Atlas Scientific product
     
  sensorInitialize();
}
 
}
void loop()
 {                                                                              //here we go....
    pH1read();
    delay(5000);
    //pH2read();
    //delay(5000);
    //pH3read();
    //delay(5000);
    //pH4read();
    //delay(5000);
 }
 
void sensorInitialize()
 {
   Serial.println("Initializing...");
   delay(1000);
   for (x=0; x < 5; x++)
    {
      inputstring = "e\r";                                                             //Sets value to "c" and does a carrige return
      pHsensor1.print(inputstring);                                                     //Sends that value to the ph chip ROFL
      if (pHsensor1.available()>0)
        {
          char inchar = (char)pHsensor1.read();
          sensorstring += inchar;
          if(inchar == '\r') {sensor_stringcomplete = true;} 
        }
   } 
   x = 0;
   delay(1000); 
   delay(100);
   for (y = 0; y < 5; y++)
    {
      inputstring = "e\r";                                                             //Sets value to "c" and does a carrige return
      pHsensor2.print(inputstring);                                                     //Sends that value to the ph chip ROFL


      if (pHsensor2.available()>0)
        {
          char inchar = (char)pHsensor2.read();
          sensorstring += inchar;
          if(inchar == '\r') {sensor_stringcomplete = true;} 
        }
    }   
       y = 0;
       delay(1000);
   delay(100);
  for (z=0; z < 5; z++)
    {
      inputstring = "e\r";                                                             //Sets value to "c" and does a carrige return
      pHsensor3.print(inputstring);                                                     //Sends that value to the ph chip ROFL


      if (pHsensor3.available()>0)
        {
          char inchar = (char)pHsensor3.read();
          sensorstring += inchar;
          if(inchar == '\r') {sensor_stringcomplete = true;} 
        }        
    }
      z = 0;
      delay(1000);
   delay(100);
  for (v=0; v < 5; v++)
    {
      inputstring = "e\r";                                                             //Sets value to "c" and does a carrige return
      pHsensor4.print(inputstring);                                                     //Sends that value to the ph chip ROFL


      if (pHsensor4.available()>0)
        {
          char inchar = (char)pHsensor4.read();
          sensorstring += inchar;
          if(inchar == '\r') {sensor_stringcomplete = true;} 
        }  
    }
      v = 0;
      delay(1000);
Serial.println("Initializing done");
}

void pH1read()
 {
   pHsensor1.listen();
   delay(100);
   for (x = 0; x < 20; x++)
    {
      Serial.println(x);
      inputstring = "r\r";                                                             //Sets value to "c" and does a carrige return
      pHsensor1.print(inputstring);                                                     //Sends that value to the ph chip ROFL
      while (pHsensor1.available()>0)
        {
        char inchar = (char)pHsensor1.read();
        sensorstring += inchar;
        if(inchar == '\r') {sensor_stringcomplete = true;} 
        }


   if (sensor_stringcomplete){                                                   //if a string from the Atlas Scientific product has been recived in its entierty 
      Serial.println("-Raw pH Sensor1 Data-");
      Serial.println(sensorstring);                                            //send that string to to the PC's serial monitor
      sensorstring.toCharArray(charBuf, 10);
      pHsense1 = atof(charBuf);                                                //Converts the array called charBuf into a float called pHsense1
      Serial.println("-ph Sensor1 Float-");
      Serial.println(pHsense1);                                                //Prints the float value
      Serial.println("");
      sensorstring = "";                                                     //clear the string:
        if (sensor_stringcomplete == true)
        {
          pHsensor1.flush();
          Serial.println("Buffer 1 has been cleared");
          Serial.println("-------------------------");
        }
      sensor_stringcomplete = false;                                       //reset the flage used to tell if we have recived a completed string from the Atlas Scientific product
      break;
      }
    if (pHsensor1.overflow())
        {
          Serial.println("Buffer 1 overflow occured");
        } 
  delay (1000);
    }
    sensorstring = "";
    inputstring = ""; 
    x = 0;
 }

I left out the code for the functions that check probes 2~4 as they are the same as probe1.
Any help would be appreciated.

So on further testing using 12 or 50 as Rx and 13 as Tx work. However using 10, 11, 51, 52, 53 as Rx do not work.

You have 4 hardware serial ports on the Mega. Why do you need 4 software serial instances, too?

You are aware, are you not, that only one SoftwareSerial instance can be listening at once? You are aware, are you not, that you must actively make an instance listen()? Your code doesn't seem to reflect that.

You are aware, are you not, that only some pins on the Mega support pin change interrupts, and that only those pins can be used for SoftwareSerial instances?

This is a small part of a much larger project, the hardware ports are unavailable.

void pH1read()
 {
   pHsensor1.listen();

"I left out the code for the functions that check probes 2~4 as they are the same as probe1." ^^^ This shows the listen() call and states that the other 3 instances are called the same way.

"So on further testing using 12 or 50 as Rx and 13 as Tx work. However using 10, 11, 51, 52, 53 as Rx do not work." As you can see here Paul my problem is that contrary to the SoftwareSerial library, the listed pins are not working. This has been tested on two seperate megas.

After much trial and error we have found only two pins that work as Rx 12 and 50. While Only 10, 11 and 13 are working Tx.

This is a small part of a much larger project

It's time to talk, then, about that "much larger project". Are you using any SPI devices? If so, that will remove 10, 51, 52, and 53 from the pool of usable pins. The EthernetClient instance suggests that you are.

The Tx pin doesn't have to support pin change interrupts, since interrupts are not involved in sending data using SoftwareSerial. Only input is interrupt based.

      inputstring = "e\r";                                                             //Sets value to "c" and does a carrige return

No, it doesn't. Comments that don't match the code should be fixed or deleted. Why is the string to be sent called inputstring. Is the incoming data stored in outputstring?

sensorInitialize() does not call listen() for any instances of the SoftwareSerial class. Therefore, whichever instance is listening is the only one for which available() might possibly return non-zero.

I'm on my way in to the lab now, I will add more detail when I get there. As far as the initialize function goes we removed the listen() call from it because it seemed to send data through all four soft port fine. Yes the outcoming data is being stored in outputstring.

As to the question of available pins. If I understand correctly any digital pin can be set as Tx? I ask because I "believe" we tried that with a known Rx pin and pin 26 as Tx(I was beyond exhausted at this point so I could be wrong). Also, the softwareSerial Library states that pins 62, 63, etc. are also available, I searched for about an hour for a pin layout showing which physical pins those numbers corresponded to with no luck.

And yes, the comments are not all perfect, sorry.

Oh, about the SPI situation. If that library is set in the code will that automatically block the pins you mentioned? Or do they have to have physical devices in them to block them out? We are testing on a clean board with no ethernetshield. Holy crap that's probably our problem.

If I understand correctly any digital pin can be set as Tx?

Any pin that is not otherwise used.

Also, the softwareSerial Library states that pins 62, 63, etc. are also available, I searched for about an hour for a pin layout showing which physical pins those numbers corresponded to with no luck.

The analog pins can be used as digital pins. The numbering continues up from the last digital pin, so analog 0 is 54, analog 1 is 55, etc.

We are testing on a clean board with no ethernetshield.

But, you are initializing the SPI hardware by using the EthernetClient class. That removes 10, 51, 52, and 53 from the available set of pins.

Thankyou PaulS,
I think you just solved my problem. I’ll post my results when I’m done testing. :grin:

So the ethernet client was the culprit here. (Or rather my mistake of no noticing the pin allocation for it :blush: ).
For anyone referencing this thread with softwareSerial problems “Pins” 62 through 69 correspond to Analogue pins A8 to A15.

String inputstring = "";

The String class is not stable, better use null terminated char array's

robtillaart: String inputstring = "";

The String class is not stable, better use null terminated char array's

Yes, now that we have a working setup we will be looking at tightening up all the code.