Relays controlled over ethernet with arduino

I have this project I’m working on that I seem to be running into memory issues. It’s like the majority of the code is going into a “Global Variable” section which is only 2KB in size and if I add too much, it simply runs out and fails to work properly.

At present, the global variables use 1498 bytes of dynamic memory. The sketch uses 15,542 bytes of program space with a max of 32,256 Bytes.

The project is supposed to consist of 8 relays that will be toggleable via the network. I’m using a Ethernet Shield on top of a Arduino Uno. Now currently, I can only get 5 of the 8 outputs to work. I have the others commented out. If I uncomment the 6th one, it will upload but the 6th output will not work. As if there’s not enough memory to run it. If I load all 8, it malfunctions and none of them work. With all 8 loaded, it’s using 90% of my dynamic memory according to the sketch program.

I will attach my code and if someone can tell me how to optimise the code to use less memory and work as I need it to, that’d be awesome. Also, if there is a way I could possibly use a microsd card to load the html and css from while keeping within the memory constraints or simply pull the majority of the code from an external server, I’d like that too.

I do not want to have to buy bigger arduino just because my code is too big or something when it seems to upload just fine. It just doesn’t work when the memory is somehow too full. I do have a teensy++ 2.0 I could use, I’d just have to somehow adapt the SPI header to the teensy.

Thanks

#include <SPI.h>
#include <Ethernet.h>
byte relay0 = 2;
byte relay1 = 3;
byte relay2 = 4;
byte relay3 = 5;
byte relay4 = 6;
//byte relay5 = 7;
//byte relay6 = 8;
//byte relay7 = 9;
byte mac[] = {0xDE,0xAD,0xBE,0xEF,0xFE,0xED};   //physical mac address
byte ip[] = {10,10,1,150};                      // ip in lan (that's what you need to use in your browser. ("192.168.1.178")
byte gateway[] = {10,10,1,1};                   // internet access via router
byte subnet[] = {255,255,254,0};                  //subnet mask
EthernetServer server(80);                             //server port
String readString;

void setup() {
  pinMode(relay0, OUTPUT);
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
  pinMode(relay4, OUTPUT);
  //pinMode(relay5, OUTPUT);
  //pinMode(relay6, OUTPUT);
  //pinMode(relay7, OUTPUT);
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip, gateway, subnet);
}


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

        //read char by char HTTP request
        if (readString.length() < 100) {
          //store characters to string
          readString += c;
          //Serial.print(c);
        }

        //if HTTP request has ended
        if (c == '\n') {
          Serial.println(readString); //print to serial monitor for debuging

          client.println("HTTP/1.1 200 OK"); //send new page
          client.println("Content-Type: text/html");
          client.println();
          client.println("<HTML>");
          client.println("<HEAD>");
          client.println("<meta name='apple-mobile-web-app-capable' content='yes' />");
          client.println("<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />");
          client.println("<link rel='stylesheet' type='text/css' href='http://www.thelonegeek.net/projects/hardware/arduino-ethernet/ethernetcss.css' />");
          client.println("<TITLE>Arduino Relays</TITLE>");
          client.println("</HEAD>");
          client.println("<BODY>");
          client.println("<H1>Arduino Relays - Using leds for some tests.</H1>");
          client.println("<hr />");
          client.println("<H2>Arduino with Ethernet Shield</H2>");
          client.println("
");
          client.println("<a href=\"/?button1on\"\">Turn On Relay 1</a>");
          client.println("<a href=\"/?button1off\"\">Turn Off Relay 1</a>
");
          client.println("
");
          client.println("
");
          client.println("<a href=\"/?button2on\"\">Turn On Relay 2</a>");
          client.println("<a href=\"/?button2off\"\">Turn Off Relay 2</a>
");
          client.println("
");
          client.println("
");
          client.println("<a href=\"/?button3on\"\">Turn On Relay 3</a>");
          client.println("<a href=\"/?button3off\"\">Turn Off Relay 3</a>
");
          client.println("
");
          client.println("
");
          client.println("<a href=\"/?button4on\"\">Turn On Relay 4</a>");
          client.println("<a href=\"/?button4off\"\">Turn Off Relay 4</a>
");
          client.println("
");
          client.println("
");
          client.println("<a href=\"/?button5on\"\">Turn On Relay 5</a>");
          client.println("<a href=\"/?button5off\"\">Turn Off Relay 5</a>
");
          /*          
          client.println("
");
          client.println("
");
          client.println("<a href=\"/?button6on\"\">Turn On Relay 6</a>");
          client.println("<a href=\"/?button6off\"\">Turn Off Relay 6</a>
");
          client.println("
");
          client.println("
");
          client.println("<a href=\"/?button7on\"\">Turn On Relay 7</a>");
          client.println("<a href=\"/?button7off\"\">Turn Off Relay 7</a>
");
          client.println("
");
          client.println("
");
          client.println("<a href=\"/?button8on\"\">Turn On Relay 8</a>");
          client.println("<a href=\"/?button8off\"\">Turn Off Relay 8</a>
");
          */
          client.println("
");
          client.println("</BODY>");
          client.println("</HTML>");

          delay(1);
          //stopping client
          client.stop();
          //controls the Arduino if you press the buttons
          if (readString.indexOf("?button1on") > 0) {
            digitalWrite(relay0, HIGH);
          }
          if (readString.indexOf("?button1off") > 0) {
            digitalWrite(relay0, LOW);
          }
          if (readString.indexOf("?button2on") > 0) {
            digitalWrite(relay1, HIGH);
          }
          if (readString.indexOf("?button2off") > 0) {
            digitalWrite(relay1, LOW);
          }
          if (readString.indexOf("?button3on") > 0) {
            digitalWrite(relay2, HIGH);
          }
          if (readString.indexOf("?button3off") > 0) {
            digitalWrite(relay2, LOW);
          }
          if (readString.indexOf("?button4on") > 0) {
            digitalWrite(relay3, HIGH);
          }
          if (readString.indexOf("?button4off") > 0) {
            digitalWrite(relay3, LOW);
          }
          if (readString.indexOf("?button5on") > 0) {
            digitalWrite(relay4, HIGH);
          }
          if (readString.indexOf("?button5off") > 0) {
            digitalWrite(relay4, LOW);
          }/*
          if (readString.indexOf("?button6on") > 0) {
            digitalWrite(relay5, HIGH);
          }
          if (readString.indexOf("?button6off") > 0) {
            digitalWrite(relay5, LOW);
          }
          if (readString.indexOf("?button7on") > 0) {
            digitalWrite(relay6, HIGH);
          }
          if (readString.indexOf("?button7off") > 0) {
            digitalWrite(relay6, LOW);
          }
          if (readString.indexOf("?button8on") > 0) {
            digitalWrite(relay7, HIGH);
          }
          if (readString.indexOf("?button8off") > 0) {
            digitalWrite(relay7, LOW);
          }*/
          //clearing string for next read
          readString = "";

        }
      }
    }
  }
}

All those literal strings are gobbling up your RAM, try the “(F)” function to store them in flash, I started, you finish and try it.

client.println(F("HTTP/1.1 200 OK")); //send new page
          client.println(F("Content-Type: text/html"));
          client.println();
          client.println(F("<HTML>"));
          client.println(F("<HEAD>"));
          client.println(F("<meta name='apple-mobile-web-app-capable' content='yes' />"));
          client.println(F("<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />"));
          client.println(F("<link rel='stylesheet' type='text/css' href='http://www.thelonegeek.net/projects/hardware/arduino-ethernet/ethernetcss.css' />"));

First things first
Use C char arrays instead of Strings
Minimize calls to print… use write() it’s faster and smaller.
These changes not compiled or tested - but intended to point you in the right direction.
oops! - The red highlights not displayed in the code blocks - you can see where they were meant to be!
Sorry

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

####>>  //Later, you might like to look at an array[] of pins, which will simplify your code, and make it much more readable.

####>>  #define relay0 2;   // define uses no storage at runtime
#define relay1 = 3;
#define relay2 = 4;
#define relay3 = 5;
#define relay4 = 6;
//#define relay5 = 7;
//#define relay6 = 8;
//#define relay7 = 9;[/color]

byte mac[] = {0xDE,0xAD,0xBE,0xEF,0xFE,0xED};   //physical mac address
byte ip[] = {10,10,1,150};                      // ip in lan (that's what you need to use in your browser. ("192.168.1.178")
byte gateway[] = {10,10,1,1};                   // internet access via router
byte subnet[] = {255,255,254,0};                  //subnet mask
EthernetServer server(80);                             //server port

####>>  char readString[110];
####>>  char *ptr = readString;             // a char pointer is easier to use!

void setup() {
  pinMode(relay0, OUTPUT);
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
  pinMode(relay4, OUTPUT);
  //pinMode(relay5, OUTPUT);
  //pinMode(relay6, OUTPUT);
  //pinMode(relay7, OUTPUT);
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip, gateway, subnet);
}


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

        //read char by char HTTP request
####>>          if (strlen(readString) < 100) {
          //store characters to string
####>>  // use a pointer into readString, and use that to append chars
          *ptr++ = c;
          //Serial.print(c);
        }

        //if HTTP request has ended
        if (c == '\n') {
####>>            *ptr++ = 0; // append NUL
          Serial.println(readString); //print to serial monitor for debuging

####>>  // you may find it smaler and faster using client.write("xxx\r\n");
          client.println("HTTP/1.1 200 OK"); //send new page
          client.println("Content-Type: text/html");
          client.println();
          client.println("<HTML>");
          client.println("<HEAD>");
          client.println("<meta name='apple-mobile-web-app-capable' content='yes' />");
          client.println("<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />");
          client.println("<link rel='stylesheet' type='text/css' href='http://www.thelonegeek.net/projects/hardware/arduino-ethernet/ethernetcss.css' />");
          client.println("<TITLE>Arduino Relays</TITLE>");
          client.println("</HEAD>");
          client.println("<BODY>");
          client.println("<H1>Arduino Relays - Using leds for some tests.</H1>");
          client.println("<hr />");
          client.println("<H2>Arduino with Ethernet Shield</H2>");
          client.println("
");
          client.println("<a href=\"/?button1on\"\">Turn On Relay 1</a>");
          client.println("<a href=\"/?button1off\"\">Turn Off Relay 1</a>
");
          client.println("
");
####>>  // combine these into one line (fewer calls)   [b]"

"
          client.println("
");
          client.println("<a href=\"/?button2on\"\">Turn On Relay 2</a>");
          client.println("<a href=\"/?button2off\"\">Turn Off Relay 2</a>
");
          client.println("
");
          client.println("
");
          client.println("<a href=\"/?button3on\"\">Turn On Relay 3</a>");
          client.println("<a href=\"/?button3off\"\">Turn Off Relay 3</a>
");
          client.println("
");
          client.println("
");
          client.println("<a href=\"/?button4on\"\">Turn On Relay 4</a>");
          client.println("<a href=\"/?button4off\"\">Turn Off Relay 4</a>
");
          client.println("
");
          client.println("
");
          client.println("<a href=\"/?button5on\"\">Turn On Relay 5</a>");
          client.println("<a href=\"/?button5off\"\">Turn Off Relay 5</a>
");
          /*          
          client.println("
");
          client.println("
");
          client.println("<a href=\"/?button6on\"\">Turn On Relay 6</a>");
          client.println("<a href=\"/?button6off\"\">Turn Off Relay 6</a>
");
          client.println("
");
          client.println("
");
          client.println("<a href=\"/?button7on\"\">Turn On Relay 7</a>");
          client.println("<a href=\"/?button7off\"\">Turn Off Relay 7</a>
");
          client.println("
");
          client.println("
");
          client.println("<a href=\"/?button8on\"\">Turn On Relay 8</a>");
          client.println("<a href=\"/?button8off\"\">Turn Off Relay 8</a>
");
          */
          client.println("
");
          client.println("</BODY>");
          client.println("</HTML>");

          delay(1);
          //stopping client
          client.stop();

####>>  // these lines could be squashed down by using smartere strings and arraays - later!

          //controls the Arduino if you press the buttons
####>>  if [b](strstr(readString, "?button1on"))[/b] { // do same for others
            digitalWrite(relay0, HIGH);
          }
          if (readString.indexOf("?button1off") > 0) {
            digitalWrite(relay0, LOW);
          }
          if (readString.indexOf("?button2on") > 0) {
            digitalWrite(relay1, HIGH);
          }
          if (readString.indexOf("?button2off") > 0) {
            digitalWrite(relay1, LOW);
          }
          if (readString.indexOf("?button3on") > 0) {
            digitalWrite(relay2, HIGH);
          }
          if (readString.indexOf("?button3off") > 0) {
            digitalWrite(relay2, LOW);
          }
          if (readString.indexOf("?button4on") > 0) {
            digitalWrite(relay3, HIGH);
          }
          if (readString.indexOf("?button4off") > 0) {
            digitalWrite(relay3, LOW);
          }
          if (readString.indexOf("?button5on") > 0) {
            digitalWrite(relay4, HIGH);
          }
          if (readString.indexOf("?button5off") > 0) {
            digitalWrite(relay4, LOW);
          }/*
          if (readString.indexOf("?button6on") > 0) {
            digitalWrite(relay5, HIGH);
          }
          if (readString.indexOf("?button6off") > 0) {
            digitalWrite(relay5, LOW);
          }
          if (readString.indexOf("?button7on") > 0) {
            digitalWrite(relay6, HIGH);
          }
          if (readString.indexOf("?button7off") > 0) {
            digitalWrite(relay6, LOW);
          }
          if (readString.indexOf("?button8on") > 0) {
            digitalWrite(relay7, HIGH);
          }
          if (readString.indexOf("?button8off") > 0) {
            digitalWrite(relay7, LOW);
          }*/
          //clearing string for next read
          readString = "";

        }
      }
    }
  }
}

#####> DONT FORGET TO RESTORE cPtr to the beginning of the buffer when you’re finished with it!

I could rewrite the whole thing for you, but you’ll learn a lot more by trying and stumbling.
There are several examples of all the above suggestions sprinkled around the forum.[/b][/b][/b][/b][/b][/b]

outsider:
All those literal strings are gobbling up your RAM, try the “(F)” function to store them in flash, I started, you finish and try it.

client.println(F("HTTP/1.1 200 OK")); //send new page

client.println(F(“Content-Type: text/html”));
          client.println();
          client.println(F(""));
          client.println(F(""));
          client.println(F(""));
          client.println(F(""));
          client.println(F(""));

Thank You man! I didn’t know how to do that. It reduced my code down to 30% for global variables with all 8 channels enabled. The Sketch is about 50% used and the entire code works now. I also truncated the html and reduced the number of print lines.

I have no idea what @lastchancename is talking about.

...and that's why we're here, to help you learn!