Little coding help needed please.

Hello all.

Hope someone can help here. Below is a small part of my sketch am coding that reads serial data of ASCII characters bigger then the space character untill a > character is received then subroutine exits. But if byte i gets to 16 before a > character is received the subroutine also exits. Works well.

So my problem now is that what if this subroutine is called but no device is attached/goes faulty? My tests show that my sketch hangs inside this subroutine.

What i would like todo and think is the right way to go is to add a bailout function after lets say 10 seconds. Could someone help me implement this into the subroutine below? Am just not sure how todo it and if the millis() would be a good answer. Would be much grateful.

byte STN_read(char *str)
{
  int temp;
  byte i = 0;
  
  unsigned long time_out = millis();
  
  while((temp = SoftwareSerial.read()) != '>' && time_out <= 3000)
  {
    if(temp >= ' ')
    str[i++] = temp;
    if(i >= 16)
    return 0; //Read is probably bad.
  }
  str[i] = '\0';
  return 1; //Read is probably good.
}

Thanks all.

Use the SoftwareSerial.available() method to check if serial data is available. If not exit the subroutine without doing anything.

byte STN_read(char *str)
{
  int temp;
  byte i = 0;
  byte retVal;
  
  unsigned long time_out = millis();
  
  retVal = 1;
  if (SoftwareSerial.available() > 0) 
  {
    while((temp = SoftwareSerial.read()) != '>' && time_out <= 3000)
    {
      if(temp >= ' ')
      str[i++] = temp;
      if(i >= 16)
        retVal=0;
    }
    str[i] = '\0';
  } else
    retVal = 0;
  return(retVal);
}

A couple things…

You’re trying to read data when there isn’t any data, you should only be reading data if there actually is something to be read.

unsigned long time_out = millis();
  
  while((temp = SoftwareSerial.read()) != '>' && time_out <= 3000)

So only run the while loop within the first three seconds after reset/power-up? Wouldn’t you want to be checking the time elapsed which is the current time minus the time you started?

Also, why use a while loop at all? Why not just check for an available byte. If there is one, check if it’s the stop byte. If so, parse the data and reset. If not, copy the character in the buffer and move on. That way, you don’t hang your code up in between receiving characters.

What my thinking is Arrch is if for some reason the IC am talking to fails my sketch will not hang inside that subroutine so i can set a error flag for it.

Thanks for the replies so far people.

  1. millis() returns a big number. You can only subtract a previous value to get a timespan as timeout value.

  2. Usually Serial.read() returns -1, because the next character is not yet available. (That's why it's defined to return an int, instead of a byte or char. )

I understand your request that STN_read() should not return until either a) a timeout happened, b) buffer is full ( probably bad data ) c) an ending character has been received within the allowed period ( returning success )

If timeout covers the whole period since start of that function (no matter if a few or no data at all arrived) the required modifications are rather easy.

Pavilion1984: What my thinking is Arrch is if for some reason the IC am talking to fails my sketch will not hang inside that subroutine so i can set a error flag for it.

Using if's instead of whiles will prevent your subroutine from hanging. Error catching could also be implemented without stalling your program with while loops.

Using if's instead of whiles will prevent your subroutine from hanging. Error catching could also be implemented without stalling your program with while loops.

I understand your thinking with the if's instead but am new to Arduino/C and this is my first sketch so still learning and don't know how todo it with just if statements. I thought a while statement was the best way.

I understand Pavilion1984 wants to "hang" in that function, max until a timeout happened.

Thus, a while is a good approach.

Usually there are more error possibilities than you can actively check for. A function with a reasonable timeout is pretty robust. It will always return, no matter which error condition causes no or bad data.

Of course, while waiting for data you can't do much, except interrupt handling : no button responses, display updates, etc.

Some good advice is coming here so thanks. As you can see i already have some error checking going on with the byte i counter and further on in my code i have header checking of the received data that is all working well. I don't want to wait in this subroutine for data that is not gonna come so my sketch can make a error flag and move on or bailout and try again. Maybe the puting it all inside a

if (SoftwareSerial.available() > 0)

statement is the best way to stop this from happening if the IC am reading fails?

Yes

if (SoftwareSerial.avaiIable())  
{ 
   byte success = STN_read(buffer);
   // ...
} 
else 
{ 
  // do other stuff
}

limits the “hanging” time to the period while data is arriving.

However, inside STN_Read() you will anyway have to cover the case that there’s not yet all data arrived …