Text still garbage, another buffer overflow?

While using my GPRS shield (Seeed Studio v1.4), Any idea why I am getting "Last-Modified: Mon, 1" c" catMtame." garbled text? There are 100 char fail-safes in place...

Any light you can shed on this would be very much appreciated, thanks in advance.

AT+CIPSEND=62
GET / HTTP/1.1
Host: www.microsoft.com
Connection: close


SEND OK
HTTP/1.1 200 OK
Cache-Control: no-cache
Last-Modified: Mon, 1" c" catMtame.
CLOSED

Code:

#include <SoftwareSerial.h>
SoftwareSerial mySerial(7, 8);
char response[100];

void setup() {

    Serial.begin(115200);    // HUMAN COM
    mySerial.begin(19200);    // SOFTWARE COM   
    power_on();
    while( sendATcommand2("AT+CREG?", "+CREG: 0,1", "+CREG: 0,5", 1000)== 0 );

}

void loop() {
 
  if (Serial.available()) {
    switch(Serial.read()) {
      case 'h':
        SubmitHttpRequest();
        break;
        
      case 'i':
        // Closes the socket
        sendATcommand2("AT+CIPCLOSE", "CLOSE OK", "ERROR", 10000);
        sendATcommand2("AT+CIPSHUT", "OK", "ERROR", 10000);
        break;
        
    } 
  }
}

void SubmitHttpRequest() {

char aux_str[50];
char ip_data[]="GET / HTTP/1.1\r\nHost: a.me\r\nConnection: close\r\n\r\n"; //62 chars
  
  Serial.println("-------------------------------------------------------------------");
  
        // Sets the APN, user name and password
        if (sendATcommand2("AT+CSTT=\"epc.tmobile.com\",\"\",\"\"", "OK",  "ERROR", 30000) == 1) {            
            Serial.println("-------------------------------------------------------------------");
        
            // Brings Up Wireless Connection
            if (sendATcommand2("AT+CIICR", "OK", "ERROR", 30000) == 1) {
                Serial.println("-------------------------------------------------------------------");
                
                // Gets Local IP Address
                if (sendATcommand2("AT+CIFSR", ".", "ERROR", 10000) == 1) {
                    Serial.println("-------------------------------------------------------------------");
                
                    // Opens a TCP socket
                    if (sendATcommand2("AT+CIPSTART=\"TCP\",\"a.me\",\"80\"", "CONNECT OK", "CONNECT FAIL", 30000) == 1) {
                        Serial.println("-------------------------------------------------------------------");
                    
                        // Sends data size
                        sprintf(aux_str,"AT+CIPSEND=%d", strlen(ip_data)); //62
                        if (sendATcommand2(aux_str, ">", "ERROR", 10000) == 1) {
                            Serial.println("-------------------------------------------------------------------");
                            // Sends data
                            GetData(ip_data, 10000);
                            Serial.println("-------------------------------------------------------------------");
                        }
                        
                    } else {
                        Serial.println("Error openning the connection");
                    }
                    
                } else {
                    Serial.println("Error getting the IP address");
                }  
                
            } else {
                Serial.println("Error bring up wireless connection");
            }
            
        } else {
            Serial.println("Error setting the APN");
        } 
        
}

void power_on() {

    if (sendATcommand2("AT", "OK", "OK", 2000) == 0) {
        Serial.println("Powering up...");
        
        pinMode(9, OUTPUT); 
        digitalWrite(9,LOW);
        delay(1000);
        digitalWrite(9,HIGH);
        delay(2000);
        digitalWrite(9,LOW);
        delay(3000);
    
        while(sendATcommand2("AT", "OK", "OK", 2000) == 0);
    }
}

int8_t sendATcommand2(char* ATcommand, char* expected_answer1, char* expected_answer2, unsigned int timeout){
  
    uint8_t answer=0;
    char response[100];
    unsigned long previous;

    memset(response, NULL, 100);

    mySerial.println(ATcommand);

    int chrnum = 0;

    previous = millis();

    do {
        if(mySerial.available() != 0){
          
          response[chrnum] = mySerial.read();
          chrnum++;
             
            if (strstr(response, expected_answer1) != NULL)    
            {
                answer = 1;
            }

            else if (strstr(response, expected_answer2) != NULL)    
            {
                answer = 2;
            }
        }
    }
    while((answer == 0) && ((millis() - previous) < timeout));

    Serial.println(response);

    return answer;
}

int8_t GetData(char* ATcommand, unsigned int timeout){
    unsigned long previous;

    memset(response, NULL, 100);

    mySerial.println(ATcommand);

    int chrnum = 0;

    previous = millis();

    do {

        if (mySerial.available() > 0) {
          response[chrnum++] = mySerial.read();
          if (chrnum > 98) {
            Serial.println(response);
            memset(response, NULL, 100);
            chrnum=0;
          }
        } 

    }  while(((millis() - previous) < timeout));

    Serial.println(response);
}

Flush waits until the output buffer is empty, its like putting in a delay! It would help if you stopped knowing that its a buffer overflow! and posted all your code.

Mark

Hi Mark, thanks for your reply. I am not using the flush() function. Thank-you for being willing to respond. Here is my entire script. The entire script is in the above code

Your loop() function won't work!

Flush() acts only on the output side of serial i.e. to the "PC", and it just waits until the output buffer is empty.

Your loop() function won't work! as yo will use up data in the input buffer far faster than it arrives.

Think about that will happen if there is only one char available when you get to

    if (mySerial.available()) {
      Serial.write(mySerial.read());
    }

You'll just go back to the start of loop().

Mark

Hi Mark,
I think you may be assuming that I am using the flush() serial function, I am not. I have changed my verbage to better reflect what I am doing.

My problem is that I have garbled text, not that I have missing text. ("Last-Modified: Mon, 1" c" catMtame.")
Thanks for your response

I see

Serial.begin(115200);

and I see

 delay(1000);

and with a serial buffer of just 64 bytes, I see multiple potential overflows.
Then I stop reading.

thanks for the reply AWOL. I've changed my speed & there are no delays in do loop for reading incoming text though, it should receive all text, the delay(1000); is in a power_on() function that I use while initializing.

So, what could be wrong? Why is there garbled text?

I appreciate your desire to help

If your just looking for the answer, the short of it is: holmes4 didn't read my code, AWOL was semi-correct, at least his last sentence was.

After the tedious work of counting characters, I discovered this is a Serial buffer problem. AWOL's response was correct. 64 byte limit will cause an overflow, the Arduino was not meant to process at even the slowest cellphone internet (GSM) speeds.

How do I overcome this? It's not possible. the Arduino cannot effectively interface with an HTTP server because the size of the returning HTTP header maybe over the size of the Arduino's buffer. To interface remotely via GSM, a custom server has to be written on the remote machine that will send as few bytes as possible to the device, this way it doesn't overwhelm the Arduino's serial buffer.

So much for that idea...

How do I overcome this? It's not possible.

For you, I agree. Now stomp the arduino and GPRS shield into little pieces and you will feel better.

64 byte limit will cause an overflow, the Arduino was not meant to process at even the slowest cellphone internet (GSM) speeds.

Nonsense.
Even at 115200 bits per second, you're only receiving a new character every 86 microseconds, or in other words, just shy of 1400 instruction cycles.

in theory... maybe.
But nah, i have yet to see an example or code that will process a whole webpage using a GSM shield... and through my own testing it just isnt possible. at one instruction cycle the buffer is 0, the next cycle its full at 64. perhaps this is because I was printing debug code to screen and the fact that the Seeed Studio shield cannot reach 115200 bps, (max at 19200) and we have a problem.

It's okay, theres a work-a-round. I'll write my own server instead of using apache :~

at one instruction cycle the buffer is 0, the next cycle its full at 64

An instruction cycle is 62.5 nanoseconds, so 64 characters in that time is a data rate of 1Gbyte per second.

Looks like bradburns wrote the book...

Doc

lots of talk... no "byte" :wink:

bradburns:
... the Arduino was not meant to process at even the slowest cellphone internet (GSM) speeds.
...
So much for that idea...

My Arduino outputs VGA output which requires very tight timings. So your idea that it can't interface with a cellphone is complete nonsense.

Each pixel is 125 nS apart.

As for capturing cellphone data at 115200 baud. A doddle. You might want to revisit your technique.

One idea that springs to mind is that on receiving a single byte you are sending many bytes:

  Serial.println("-------------------------------------------------------------------");

If you send all that when receiving one byte you are certainly likely to overwhelm the output buffer size. You can make it larger, but you only have so much RAM. Maybe you can manage with less hyphens?

bradburns:
lots of talk... no "byte" :wink:

Moderate your condescending tone or be banned. We have too many trolls already.

I'm certainly impressed with your VGA output :slight_smile: and I understand your pain in removing trolls. I admin my own forum, I have built and currently host multiple popular websites. There is no stopping trolls my friend, they simply re-create new username, new email, from a new IP. However, i've done nothing worthy of the "troll" accusation. There's no way to determine tone, "no byte" is friendly jesting (a play on words), and puns are not the mark of a troll. Threatening, name calling, thread-hijacking, and bullying other members are certainly the mark of a troll. Please, let's continue our polite discussion.

The visual ques and other hyphens were certainly removed, they are for debugging purposes. Also, I am unable to transfer at 115200, 19200 baud at best.
If anyone has any constructive ideas on how to rectify this issue, I & the community would very much appreciate it!

Muchas gracias to everyone that contributed to this discussion! :smiley:

bradburns:
If anyone has any constructive ideas on how to rectify this issue, I & the community would very much appreciate it!

You need to know how long it would take the incoming serial stream to fill the serial buffer at maximum speed, and design your sketch so that it checks and empties the serial buffer before that can happen. In your case, the loop was delayed by your calls to delay() and by your serial print statements, which meant it would not be capable of checking the serial buffer soon enough to stop it overflowing. That's just a fault in the design of your sketch - you need to know how long it would take to fill the serial buffer and design your sketch so that it checks the buffer soon enough to prevent an overflow. If you code it correctly, the Arduino is easily capable of keeping up with the full speed of the serial port.

Software serial is problematic in that it requires bit-banging the data, and the higher the baud rate the smaller the tolerances. Also it turns interrupts off while it is doing it.

Can you post your amended sketch? Why do you have "response" declared both globally and locally?

I'm not a big fan of loops like this:

    do {

        if (mySerial.available() > 0) {
          response[chrnum++] = mySerial.read();
          if (chrnum > 98) {
            Serial.println(response);
            memset(response, NULL, 100);
            chrnum=0;
          }
        } 

    }  while(((millis() - previous) < timeout));

In that loop, which looks like it might go for a while, you are not reading from Serial and thus not emptying its buffer. I suggest a less "loopy"* way of processing data.

  • play on words there :wink:

If anyone has any constructive ideas on how to rectify this issue, I & the community would very much appreciate it!

If you want help, you really should give a detailed technical explanation of just what you are trying to do. you appear to being to combine HTTP code and two versions of serial code for reasons that aren't very clear.