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.
    – jfpoilpret
    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.
    – JamesH
    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.
    – jfpoilpret
    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?
    – JamesH
    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.
    – jfpoilpret
    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.
    – JamesH
    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.
    – jfpoilpret
    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?)
    – JamesH
    Sep 29, 2014 at 6:58
  • Oops, my mistake, see my edit: atoi(&bb[1]) instead of atoi(bb).
    – jfpoilpret
    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?
    – JamesH
    Sep 29, 2014 at 9:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.