Is there a way to detect if a SoftwareSerial port is open and ready?

Hey guys,

Is there a way to detect if a SoftwareSerial port is open and ready? In case of the hardware serial ports, we can use the command:

if (Serial) // for Arduino Leonardo. For Arduino Uno, replace Serial with Serial1
{
// your code comes here
}

Is there an equivalent code for the SoftwareSerial ports?

Or is there method to detect if the port is open without checking the content of the buffer?

Thank you in advance for your suggestion or solution.

Cheers

It will be open when you have done a SoftwareSerial.begin(). You can use SoftwareSerial.available() to check if there is anything to be read.

It will be open when you have done a SoftwareSerial.begin(). You can use SoftwareSerial.available() to check if there is anything to be read.

Thanks for the reply dxw00d,
Well, may be haven't been clear with my question. Here is my problem:

I want to detect if SoftwareSerial can send data to an available and valid comport on PC. Because the PC serial port might not open yet. The SoftwareSerial might send data to PC, but the port on PC is not yet ready; It could being used by other application or even not yet exist (for example the cable could be not plugged yet)

elexy:
if (Serial) // for Arduino Leonardo. For Arduino Uno, replace Serial with Serial1

That only works on the Leo. The Uno doesn't have a Serial1 and can't tell anyway.

What do you mean if it's "up and ready?" Do you mean if begin() was called? I suppose that could be a useful feature. It doesn't exist for HardwareSerial and I seriously doubt it for softwareserial.

There is no way to tell if another side is ready to receive data without it telling you. That's a limitation of the serial protocol. Of course, getting your application to tell you when it's ready is trivial.

What do you mean if it's "up and ready?" Do you mean if begin() was called? I suppose that could be a useful feature. It doesn't exist for HardwareSerial and I seriously doubt it for softwareserial.

There is no way to tell if another side is ready to receive data without it telling you. That's a limitation of the serial protocol. Of course, getting your application to tell you when it's ready is trivial.

Thank your for the reply. And you are right the Uno doesn't have a Serial1. My bad :smiley:

Well, that was what I was afraid off. I mean there might be no way to know if the com port on my pc is ready to receive data. It would be nice if it is possible that Arduino sends data only if the com port on the other end is open ready. I otherwise Arduino sends data without knowing if there is any recipient.
I have menu which must be sent ONLY once by Arduino and ONLY if the com port on PC is open.

cheers.

If you can control the PC side, your best option is for the Arduino to send an 'are you ready' message, and see if the PC responds with 'yes'. If it does, then send your actual data.

If you can control the PC side, your best option is for the Arduino to send an 'are you ready' message, and see if the PC responds with 'yes'. If it does, then send your actual data.

Thanks. That is indeed one possibility.

At the PC side I have a home brew comport monitoring application which I wrote using C#, so I have control on the port. The disadvantage of your suggestion is that I have to make this monitoring application specific and to react the "are you ready" message from Arduino.

But I appreciate your idea; and I might have no other choice than modifying my comport monitoring application for the PC side XD

Thanks.

Why not just do nothing until you receive data from the PC?


Rob

Graynomad:
Why not just do nothing until you receive data from the PC?


Rob

Because the OP wants to send to the PC, not receive from it.

I guess so, but if there's a program running on the PC it can send a few bytes to tell the Arduino it's there, like what you suggested but the other way around, ie the Arduino doesn't pro-actively do anything.

It does still need the PC code to be changed, but all it has to do is spit out a few bytes when it starts, you could almost ignore the values on the Arduino (although it's more robust to check them) and not transmit until you see something.


Rob

True. Have the PC send out a ping byte occasionally, which would allow it to remain generic, as the OP wants.

Unless the Arduino has been modified, opening the serial portresets the Arduino. The code to perform handshaking with the PC can be put in setup.

If the PC application sends data to the Arduino, it needs to be sure to wait long enough, after opening the serial port, for the Arduino to reset, before sending data.

If the PC simply responds when the Arduino initiates handshaking, the Arduino should not wait forever for a response. The PC application needs to return a response within the time that the Arduino is waiting for a response.

Hello guys,

Well, I have written some code as some of you have suggested and it works good. But it is not yet completed at all.

Here is my code below. Please don't hesitate to give comments, suggestions and remarks. I am new in this and want learn more:-) Thank you all for the help :slight_smile:

/*
I use bluetooth dongle and BlueSMiRF-Gold from Sparkfun.
As soon as the pc ComPort is open, my application sends the word "Coffee" automatically to
inform Arduino that the port is open. Then Arduino will send me its task list (the menu)
But I can also type "Coffee" on the application and send it to get the menu from Arduino.
*/

#include <SoftwareSerial.h>

#define rxBtPin 14
#define txBtPin 15

SoftwareSerial BTport = SoftwareSerial(rxBtPin, txBtPin);
bool pcPortReady = false;

void setup()
{
BTport.begin(9600);
delay(1000);
pinMode(rxBtPin, INPUT);
pinMode(txBtPin, OUTPUT);
}

void loop()
{
if (pcPortReady == true) // if the ComPort of PC port is already open I can send command to Arduino do something for me
{
if (BTport.available() != 0)
{
char incomingByte = BTport.read();

switch(incomingByte) // Depending on the incoming character, decide what to do.
{
case 'W': //closeCurtain(); // not implemented yet
break;
case 'w': //openCurtain(); // not implemented yet
break;
case 'L': //lightOn(); // not implemented yet
break;
case 'l': //lightOff(); // not implemented yet
break;
case 'A': // setAlarm(); // not implemented yet
break;
case 'a': //resetAlarm(); // not implemented yet
break;

default:
break;
}
}
}
// if the ComPort of PC port is NOT open, program comes always here.
// If Aruino gets "coffee' from PC ComPort, that means the ComPort is open.
else
{
String pcPortIsReady;
if (BTport.available() != 0)
{
pcPortIsReady = constructText();
}

// if Arduio gets "coffee" from ComPort of the PC, it means PC port is ready. Then Arduino can send the menu to PC
if (pcPortIsReady == "Coffee")
{
showMenu(); // Now the PC port is open. And arduino will send me it's task list (the menu)
pcPortReady = true;
}

// In case the ComPort buffer is not empty, make it empty.
while (BTport.available() > 0)
{
BTport.read();
}
}
}

void showMenu()
{
BTport.println("W : Close Curtains");
BTport.println("w : Open Curtains");
BTport.println("L : Turn on Light");
BTport.println("l : Turn off Light");
BTport.println("A : Set alarm");
BTport.println("a : Reset Alarm");
}

String constructText() // make a string from the chars in the serial buffer
{
String msg;
byte incomingByte;
delay(1000);

while (BTport.available() != 0)
{
byte len = BTport.available(); // Determine number of chars in serial buffer
for (byte i=0; i < len; i++)
{
incomingByte = BTport.read(); // Read a byte from serial buffer
if (incomingByte != 10) // Carriage return
msg = msg + (char)incomingByte; // construct a string from chars in the serial buffer
}
return(msg);
}
}

Use [code ] tags like I am.

#define rxBtPin 14     
#define txBtPin 15

It's the C++ way to use const int or const byte to define constants

SoftwareSerial BTport =  SoftwareSerial(rxBtPin, txBtPin);

That technically works but the correct way is to do this:

SoftwareSerial BTport(rxBtPin, txBtPin);
  delay(1000);

Why?

  pinMode(rxBtPin, INPUT);   
  pinMode(txBtPin, OUTPUT);

These are unnecessary I think

   else  
    {     
      String pcPortIsReady;
      if (BTport.available() != 0)
      { 
          pcPortIsReady = constructText();   
      }
      
      // if Arduio gets "coffee" from ComPort of the PC, it means PC port is ready. Then Arduino can send the menu to PC 
      if (pcPortIsReady == "Coffee") 
      { 
        showMenu();    // Now the PC port is open. And arduino will send me it's task list (the menu) 
        pcPortReady = true;  
      }

Using the String class can cause you some hurt. It makes things a tiny bit easier, but It can also case weird bugs when it fragments the heap. You can easily go without it here if you learn the most basic of the c string functions (which are no harder to use than any other...)

      // In case the ComPort buffer is not empty, make it empty. 
      while (BTport.available() > 0) 
      {
         BTport.read();          
      }

What if the computer had sent good data by this point and you throw it away?

void showMenu()
{
  BTport.println("W : Close Curtains"); 
  BTport.println("w : Open Curtains");
  BTport.println("L : Turn on Light");
  BTport.println("l : Turn off Light");
  BTport.println("A : Set alarm"); 
  BTport.println("a : Reset Alarm"); 
}

You might want to put those in PROGMEM with the F macro. Easy and saves you quite a bit of RAM

String constructText()  // make a string from the chars in the serial buffer
{  
  String msg; 
  byte incomingByte;    
  delay(1000);
  
  while (BTport.available() != 0)
  { 
    byte len = BTport.available();	      // Determine number of chars in serial buffer
    for (byte i=0; i < len; i++)
    {
      incomingByte = BTport.read();        // Read a byte from serial buffer                 
      if (incomingByte != 10)     	      // Carriage return
         msg = msg + (char)incomingByte;       // construct a string from chars in the serial buffer     
    }      
    return(msg);     
  }
}

Get rid of the String class

Hey WizenedEE,

Thank you very much for your suggestions and comments. I appreciate it really. After all I want to learn making a better and compact codes:)

SoftwareSerial BTport(rxBtPin, txBtPin);

Is indeed much better.

About the declaration: in Arduino tutorials it is usually written as #define instead of cons. I wonder why!

Now, I am going to optimize my code :slight_smile: But I have to figure out how I replace the String class and use some char arrays or something like that. And I will put the menu list in PROGMEM. It is great :slight_smile:

in Arduino tutorials it is usually written as #define instead of cons. I wonder why!

I use both, I think the advantage to using a const is that the compiler has a type to work with and can therefore generate an error if it's used incorrectly. With the #define it's purely a text substitution to no error checking is possible.

Also with constant values it's traditional to put them in UPPER CASE so you know at a glance they are constants and not some variable you have to track down to see where it gets changed.


Rob