0

My Ethernet server keeps crashing after pulling the RGB values from the string. It remains connected if I'm just toggling a pin, but whenever the string has the rgb values in it, the RGB values are pulled, the LED changes but then the server crashes and won't take any more requests. Do I need to restart the server after it plucks the RGB values for another read? If so, how would I go about doing this?

Thanks, James :)

Example HTTP request that causes the crash: /?LED=B233+G011+R133&t=T HTTP/1.1

    #include <SPI.h>
    #include <Ethernet.h>
    #include <string.h>

    byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 
    byte ip[] = {192, 168, 0, 102 }; 
    byte gateway[] = {192, 168, 0, 1 }; 
    byte subnet[] = {255, 255, 255, 0 }; 
    EthernetServer server(84);
    ; 

    char* redstring={0};
    String blue1;
    String green1;
    String red1;
    String testString = "0123456789";


    int blue;
    int green;
    int red;
    int been=0;
    int b=0;
    int g=0;
    int r=0;
    //////////////////////

    void setup(){

    pinMode(11, OUTPUT);
    pinMode(9, OUTPUT);
    pinMode(7, OUTPUT);
    pinMode(6, OUTPUT);

    //start Ethernet
    Ethernet.begin(mac, ip, gateway, subnet);
    server.begin();

    //enable serial data print 
    Serial.begin(9600); 
    Serial.println("SERVER RUNNING HTTP / GET"); 
    }

    void loop(){
     ////////////////////////////////////////
     EthernetClient client = server.available();
if (client) {
while (client.connected()) {
  if (client.available()) {
    char c = client.read();

    //read char by char HTTP request
    if (sizeof(redstring) < 100) {

      //store characters to string 
      redstring += c; 
      //Serial.print(c);
    } 

    //if HTTP request has ended
    if (c == '\n') {

      ///////////////////////////////////////////

      Serial.println(redstring);



      client.println("HTTP/1.1 200 OK");
      client.println("Content-Type: text/html");
      client.println();
      client.println("<HTML>");
      client.println("<link rel=\"shortcut icon\" href=\"data:image/x-icon;,\" type=\"image/x-icon\">"); 
      client.println("<HEAD>");
      client.println("<TITLE>Arduino GET</TITLE>");
      client.println("</HEAD>");
      client.println("<BODY>");

      client.println("<H1>HTML GET</H1>");
      //change ip back if not local
      client.println("<FORM ACTION=\"http://192.168.0.102:84\" method=get >");

      client.println("JQUERY: <INPUT TYPE=TEXT NAME=\"LED\" VALUE=\"\" SIZE=\"25\" MAXLENGTH=\"50\"><BR>");

      client.println("<INPUT TYPE=SUBMIT NAME=\"t\" VALUE=\"T\">");

      client.println("</FORM>");

      client.println("<BR>");

      client.println("</BODY>");
      client.println("</HTML>");

      delay(1);
      //stopping client
      client.stop();
      /////////////////////
      //readString = Character.toUpperCase(readString); 
      for (int i = 1; i < sizeof(redstring); i++) {
        if (strchr(redstring, 'B') && && redstring[i+1] > -1) {
          blue=redstring[i+1, i+4];
          analogWrite(11, blue); 
          delay(1000);
                      }

        if (strchr(redstring, 'G') && redstring[i+1] > -1) {
          green=redstring[i+1, i+4];
          analogWrite(9, green); 
          delay(1000);
                      }


        if (strchr(redstring, 'R')&& redstring[i+1] > -1) {
          red=redstring[i+1, i+4];
          analogWrite(7, red); 
          delay(1000);
                      }



      }






      //clearing string for next read
           redstring="";
          (redstring, "0", sizeof(redstring));
        }
      }
    }
  }
} 
11
  • 1
    When you compile this program with Arduino IDE, what does it tell you about the amount of memeory used? It looks your program uses a lot of SRAM and it may quickly happen that memory gets exhausted during runtime. Commented Sep 28, 2014 at 7:39
  • It complies fine and just says the typical: Binary sketch size: 16,688 bytes (of a 258,048 byte maximum). It only appears to crash when I use RED, blue and green are fine and I can execute it as many times as I want, as soon as it finds red it crashes. Commented Sep 28, 2014 at 10:11
  • It seems you have an Arduino Mega, right? When I was talking about memory, I was referring to SRAM (data), not Flash (code). This is where you can have an issue (8KB limit on Mega). But more improtant: avoid using String as it is a source of this kind of crashes, due to memory heap fragmentation. Commented Sep 28, 2014 at 10:22
  • Yeah, I'm using the Mega. How would I check the SRAM usage? Hmm, what would you suggest using except string? Or would you suggest doing this another way? Commented Sep 28, 2014 at 11:10
  • Arduino IDE shows the amount od SRAM used for data after compilation. I got it on 1.5.7; I'm not sure this also works on 1.0.5 though. Commented Sep 28, 2014 at 12:41

1 Answer 1

3

Using String, which uses dynamic allocation/deallocation on the heap is not advised in embedded platforms, as this can quickly lead to heap fragmentation, eventually leading to memory exhaustion, heap/stack collision...

First off, you should try to replace all String usage, everywhere in your program, with C-tyle strings, i.e. char* or char xxx[...] along with dedicated C functions to deal with them: strchr, strstr, strcpy, strcat, strtok, atoi...

Second, you can avoid using global variables and use the stack for many of them.

void loop() {
    ...
    if (client) {
        char readString[101];
        const int READ_STRING_SIZE = sizeof(readString) - 1;
        int readIndex = 0;
        while (client.connected()) {
            if (client.available()) {
                char c = client.read();
                if (readIndex < READ_STRING_SIZE) {
                    readString[readIndex++] = c;
                }

                if (c == '\n') {
                    // Terminate the read string
                    readString[readIndex] = 0;
                    Serial.println(readString);

                    // Prepare for next reeading
                    readIndex = 0;

                    client.println("HTTP/1.1 200 OK");
                    ...
                    client.stop();

                    // convert readString to all uppercase
                    for (i = 0; i < strlen(readString); i++)
                        readString[i] = toupper(readString[i]);

                    bool b = false;
                    bool r = false;
                    bool g = false;
                    int blue, red, green;

                    // Look for 'B' value
                    char* bb = strchr(readString, 'B');
                    if (bb != 0 && isdigit(bb[1]) {
                        blue = atoi(&bb[1]);
                        analogWrite(11, blue);
                        delay(500);
                        b = true;
                    }
                    // Same for 'G' and 'R' value
                    ...
                    if (b && r && g) {
                        Serial.print("CHANGING RED TO: ");
                        Serial.println(red);
                        Serial.print("CHANGING GREEN TO: ");
                        Serial.println(green);
                        Serial.print("CHANGING BLUE TO: ");
                        Serial.println(blue);
                    }
                }

                if (strstr(readString, "PIN6") != 0) {
                    digitalWrite(6, !digitalRead(6));
                    ...
                }
            }
        }
    }
}

In this sample code, we have completely removed dynamic memory allocation.

9
  • Thank you so much for all your help! How would I clear the C-String? It keeps looping and doesn't toggle the pin, rather just makes it flash. Commented Sep 29, 2014 at 0:52
  • See my edit: I had forgotten to reset readIndex once a whole string has been read. Now it should work properly. Commented Sep 29, 2014 at 4:52
  • ah okay, thanks! Another issue I found is that the code breaks the string when it hit's a 'B' but doesn't get the next 3 numbers, but instead copys the http request from the string and tries to make it an int and set the LED, but it just returns a 0. How would I replicate the blue = redstring[i + 1, i + 4]; (to get the 3 numbers after the 'B' like mine?) Commented Sep 29, 2014 at 6:58
  • Oops, my mistake, see my edit: atoi(&bb[1]) instead of atoi(bb). Commented Sep 29, 2014 at 8:30
  • Ah okay, thank you! The same issue is occuring, as soon as I pass three colours, the server disconnects and won't take any more requests. Could this be a problem with the way I have set my server up? Commented Sep 29, 2014 at 9:18

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.