SoftwareSerial port not available?

I'm trying to send commands from a device via a SoftwareSerial port to the arduino to talk to command sensors which will then respond with data to be sent back to the peripheral. I'm having a bit of trouble getting the commands from the peripheral to the Arduino.

I have a pH sensor, which is selected by sending 'pH\r' to the Arduino from the peripheral. This is coming in fine, and the pH probe is 'selected' in the Arduino program. However, when I want to send a command to the selected pH probe to tell it to give me sensor data (the command is 'r\r'), The SoftwareSerial port on the Arduino is not showing that there is new data (the 'r\r' command to tell the pH sensor to update the sensor data) available on the SoftwareSerial port. You can see how I'm checking this below. I am also listening on the SoftwareSerial port and have tested that I am doing so.

PeripheralSerial.listen();
//if (PeripheralSerial.isListening()) {
   //Serial.println("PeripheralSerial is listening!");                             //debug to see if port is listening
//} 
while (PeripheralSerial.available()) {                                               //while a char is holding in the serial buffer
         Serial.println(PeripheralSerial.available());                              //debug to see if the PeripheralSerial port is available
         char inchar = (char)PeripheralSerial.read();                                  //get the new char
         Serial.println(inchar);
         inputstring += inchar;                                               //add it to the inputstring
         if (inchar == '\r') {
         input_stringcomplete = true;
         //Serial.print("set");
         Serial.println("set");                                                 //debug
         }                   //if the incoming character is a <CR>, set the flag
        }

Note that the input_stringcomplete flag needs to be set so that i can go into some if statements and select the correct probe to talk to.

if (input_stringcomplete){         //if a string from the PC has been received in its entirety 
  //Serial.print(inputstring);
  if(inputstring.equals("pH\r")){
    Serial.println(inputstring);  
    probe_select = 1;
    Serial.print(probe_select);           //debug
     }

And I'm checking to see that the input_stringcomplete flag is being reset (which it is).

...                                                      // after the probe has been selected and has sent data back to the peripheral
inputstring = "";
  input_stringcomplete = false;
  Serial.println(input_stringcomplete);
  }

I am not sure why the SoftwareSerial port is not seeing the second command. I don't know if it's something with the Arduino program or if it's with how I'm sending things from the peripheral. Does the serial port need to be shut down and reopened somehow before it can become available again? I haven't had problems with this in the past. I'm sending the first command (pH\r), wait a few seconds, then send the second command (r\r).

I checked to see if the correct commands are being sent to the arduino in a separate program like this:

//if (PeripheralSerial.available())
//    Serial.write(PeripheralSerial.read());  // to the hardware serial

and I'm seeing all of the commands come in, so I know they're being sent.

This program works fine if I just use the serial monitor. Why is the PeripheralSerial port not available?

It is very hard to find programming errors when shown only small snippets of code. For example, you didn't show he part of your sketch that fails to recognize the "r/r" message. You also didn't show the resulting debug messages that might point o a logic error.

Could you post a complete sketch that demonstrates the problem? Preferably with commented-out code removed, and the remainder formatted.

If the sketch contains a substantial amount of code not related to the problem then I suggest you create a simple test sketch containing the minimal code necessary to demonstrate the problem. Quite often the act of creating this will clarify the problem to the point that you can solve it for yourself, but in any case it reduces the amount of code we need to wade through.

Great advice, I'll get that up ASAP.

Here's the 'full' stripped down code.

#include <SoftwareSerial.h>                                                    //add the soft serial libray

#define rxpH 2                                                                //set the RX pin to pin 2
#define txpH 3 

SoftwareSerial pHserial(rxpH, txpH);
SoftwareSerial PeripheralSerial(8,9);

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
unsigned int probe_select = 0;

void setup(){                                                                //set up the hardware
     Serial.begin(38400);                                                      //set baud rate for the hardware serial port_0 to 38400
     pinMode(rxpH, INPUT);
     pinMode(txpH, OUTPUT);
     pHserial.begin(38400);                                                     //set baud rate for software serial port_2 to 38400
     PeripheralSerial.begin(19200);                                                     //set baud rate for software serial port_3 to 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
   }

void loop(){                                                                   //here we go....

PeripheralSerial.listen();
while (PeripheralSerial.available()) {                                               //while a char is holding in the serial buffer
         char inchar = (char)PeripheralSerial.read();                                  //get the new char
         inputstring += inchar;                                               //add it to the sensorString
         if (inchar == '\r') {
         input_stringcomplete = true;
         }                   //if the incoming character is a <CR>, set the flag
        }
if (input_stringcomplete){         //if a string from the PC has been recived in its entierty 
  if(inputstring.equals("pH\r")){
    probe_select = 1;
    Serial.print(probe_select);
     }
   else {
      switch(probe_select){
       case 1:{
         pHserial.print(inputstring);
         break;
       }
      }
     }
 inputstring = "";
 input_stringcomplete = false;
  }
  
switch(probe_select){
  case 1:{
    pHserial.listen();
    while (pHserial.available()) {                                               //while a char is holding in the serial buffer
         
         char inchar = (char)pHserial.read();                                  //get the new char
         sensorstring += inchar;                                               //add it to the sensorString
         if (inchar == '\r') {sensor_stringcomplete = true;}                   //if the incoming character is a <CR>, set the flag
         }
     break;  
     }
}
if (sensor_stringcomplete){                                                   //if a string from the Atlas Scientific product has been recived in its entierty 
      Serial.println(sensorstring);                                            //send that string to to the PC's serial monitor
      PeripheralSerial.listen();
      PeripheralSerial.print(sensorstring);
      sensorstring = "";                                                       //clear the string:
      sensor_stringcomplete = false;                                           //reset the flage used to tell if we have recived a completed string from the Atlas Scientific product
      }
  
}

I should also mention that I'm talking to my pH probe using another sofwareSerial port.

If using multiple software serial ports, only one can receive data at a time. There are methods that allow you to control this such as listen() and isListening()

See http://arduino.cc/en/Reference/SoftwareSerial

accidentally deleted one of the 'listen()' lines from my stripped down code. I believe I am already listening on each port when it is needed, but perhaps not doing something right with it?

It looks to me as if you are enabling each SoftwareSerial port immediately before you try to read from it. I don't think that will work. SoftwareSerial doesn't receive data at the point you call listen() or available() or read(). The port is enabled when you call listen(), and will receive and buffer any data that arrives from then on; the available() and read() methods let you find out whether it has got any data buffered, and retrieve it. If you call listen() for a different SoftwareSerial then this one will stop receiving.

I think what you need is a state machine which listens to the peripheral serial and waits until it recognises a command, then executes the command. A command that requires a response from a sensor would be executed by enabling the sensor's serial port (and hence disabling the peripheral's port), sending the command to it and waiting until response was received or a timeout occurred. Then the peripheral's serial port would be enabled (hence disabling the sensor's serial port) and you are back to the starting point.

It is inherent in this architecture that only one serial port is enabled at a time and while the sketch is waiting for a response from a sensor, it will ignore any subsequent input from the peripheral.

I haven't used it, but I understand there's an alternative SoftwareSerial library and I seem to remember that one of the improvements is that it allows multiple ports to be enabled simultaneously. If you believe you need this capability, I suggest you have look for that and see whether it does what you need.

I haven't used it, but I understand there's an alternative SoftwareSerial library and I seem to remember that one of the improvements is that it allows multiple ports to be enabled simultaneously. If you believe you need this capability, I suggest you have look for that and see whether it does what you need.

If you are thinking of AltSoftSerial, its reason for being was to deal with the interrupt hogging that SoftwareSerial (by necessity) causes. It gets around the issue by using two specific pins, not ANY two pins. Given that, it's hard to imagine how you could use two instances of AltSoftSerial.

PeterH's suggestion to use AltSoftSerial worked! I put my peripheral on the AltSoftSerial port (as PaulS mentioned, it's only on two specific pins) in order to keep that serial port open all the time. This kept me from missing data coming in from it. I left my sensors on SoftwareSerial ports and used them only when I need to. As PaulS mentioned, this isn't a generalizable solution, but in the case where you need one dedicated port and have complete control over the communication via the other two ports on your arduino, using one AltSoftSerial and two (or more) SoftwareSerial ports will work apparently.

Thanks guys!