Data at Serial Port Avaliable

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am interfacing a GSM modem via Arduino at Serial port 2.

I have seen that responses fron GSM modem are subject to time. Sometime its response are fast and sometime it are slow. I  have a code like below which checks for response from GSM modem based upon a user configurable timeout value:

    sendATcommand(str_at_cmd, str_ok, 500);


    int8_t sendATcommand(char* ATcommand, char* expected_answer, unsigned int timeout)
    {
        uint8_t x=0;
        char response[100];
        unsigned long previous;
        int answer = 0;
        memset(response, '\0', 100);
        answer = 0;;
        delay(100);
        ClearSerialData(); // read and flush all data
        debug_println(ATcommand);
        Serial2.println(ATcommand);
        delay(200);
        x = 0;
        previous = millis();
        do {
           if(Serial2.available() > 0){    
           response[x] = Serial2.read();
           delay(100);
           debug_print(response[x]);
           response[++x] = '\0';
           if (strstr(response, expected_answer) != NULL)    
           {
               debug_print("\nAnswer Mathced");
               answer = 1;
           }
           }
        }while((answer == 0) && ((millis() - previous) < timeout));   
        debug_println("\nReturning from AT Command");
        return answer;
    }

I was never able to set the correct timeout value - as at random test it failed once or twice and not received 100% success.

My question if I change the code like below

    while(Serial2.available() > 0){    
       response[x] = Serial2.read();
       delay(100);
       debug_print(response[x]);
       response[++x] = '\0';
       if (strstr(response, expected_answer) != NULL)    
       {
           debug_print("\nAnswer Mathced");
           answer = 1;
       }
    }

So when does Serial2.available() method returns <= 0 value. Is my above code correct - this way I overcome the timeout issue and all my GSM responses are being read - are there scenarios that I will end up in infinite loop?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

prakash_prasad wrote:
when does Serial2.available() method returns <= 0 value.

Is that not answered in the Arduino documentation...?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
while(Serial2.available() > 0){    
       response[x] = Serial2.read();
       delay(100);

 Why do you wait 100 ms after receiving a character?

 A receiver buffer overflow may happen.

 

Please try this version:

 

int8_t sendATcommand(char* ATcommand, char* expected_answer, unsigned int timeout)
{
  uint8_t x = 0;
  char response[100];
  unsigned long previous;
  int answer = 0;
  memset(response, '\0', 100);
  answer = 0;;
  delay(100);
  ClearSerialData(); // read and flush all data
  debug_println(ATcommand);
  Serial2.println(ATcommand);
  //delay(200);                                      <<<<<<
  x = 0;
  previous = millis();
  do {
    if (Serial2.available() > 0) {
      response[x] = Serial2.read();
      //delay(100);                                 <<<<<<
      debug_print(response[x]);
      response[++x] = '\0';
      if (strstr(response, expected_answer) != NULL)
      {
        debug_print("\nAnswer Mathced");
        answer = 1;
      }
    }
  } while ((answer == 0) && ((millis() - previous) < timeout));
  debug_println("\nReturning from AT Command");
  return answer;
}

    2) Serial.available() return number of characters received.  0 means: no character received.  Never returns values < 0

        if (Serial.available())     means:   if  (number_of_characters_received > 0) for example:

 

    


index=0;
start=millis();
while ((millis()-start)<1000)){
  n=Serial.available();  
  for (int i=0; i<n; i++) {
    recbuffer[index++]=Serial.read();
    recbuffer [ index ] = 0;
  }
}

// test the answer now

Last Edited: Tue. Mar 17, 2015 - 02:38 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for your valuable inputs I  agree that I am putting un-necessary delays in my code which can cause issues - but then I have found that if I probe very fast I loose characters / response, the condition 


Serial2.available()

fails at times since I am receiving response from a public network after some delay. May be in your case the n/w is fast which is not in my case here. Hence if I do not put any delay I am always times out after receiving some partial response. Actually I feel it is completely based upon how you n/w provider service is and our code settings should be based upon that.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

prakash_prasad wrote:

Thanks for your valuable inputs I  agree that I am putting un-necessary delays in my code which can cause issues - but then I have found that if I probe very fast I loose characters / response, the condition 


Serial2.available()

fails at times since I am receiving response from a public network after some delay. May be in your case the n/w is fast which is not in my case here. Hence if I do not put any delay I am always times out after receiving some partial response. Actually I feel it is completely based upon how you n/w provider service is and our code settings should be based upon that.

It doesn't fail. If it returns 0 it means there is no data available at that moment, which is not a failure. So you need to wait until there is data (and read it when there is data) or until time runs out. heweb showed you a simple way to do that.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That's exactly I am doing in my below code now. A little bit modified now and agree with other code posted in this thread:

 

int8_t sendATcommand(char* ATcommand, char* expected_answer, unsigned int timeout)
{
...............................
    while(1)
    {
    while((numbytes = GPRS.available())>0) {
      while (numbytes) { 
          numbytes -- ;
          temp = GPRS.read();
          if(temp >= 32 && temp < 127)
          {
            response[x] = char(temp);
            debug_print(response[x]);
            response[++x] = '\0';
            prev_time = millis();
          }
          if (answer == 0 && strstr(response, expected_answer) != NULL)    
          {
              answer = 1;
              break;
          }
       }
    }
    if ( answer == 1 || (unsigned long)(millis() - prev_time) >= timeout)
      break;
   } 
.........................
}

 

Please correct me in case I am wrong

Last Edited: Tue. Mar 17, 2015 - 05:57 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

>>>>  debug_print(response[x]);

 

makes  a delay per received character.

For a moment think of a delay of one second. Then at 19200 baud (about 2000 characters per second)

within this second 2000 characters are sent, when you display the first received character ==> Buffer overrun.

 

Well, your debug_print may be much faster, but the caused delays produces some risks.

For instance if   debug_print  uses (another) Serial line with same baudrate a little delay per character

will sum up to a delay time not acceptable - sometimes after 100 or more received characters!

I have produced a bug like that by myself.

 

i often use 1000000 baud which would require a  debug_print time of less than 10us !!!

 

Some tests are ok as long as they are much faster than the transfertime of one character.

 

Again: No output until:

   1) tests show: ready

or

  2) timeout

 

All characters received are in response[] buffer and you can analyzse them  after you got the whole response.