Go Down

Topic: Ethernet Shield Not Being Consistent (Read 708 times) previous topic - next topic

Freumar

I'm using a SainSmart Wiznet W5100 ethernet shield and an Arduino Uno to try to create a webserver that reads POST information sent by a form and interprets the information to control the turning on and off of lights at specific times. The problem I am having is that the WebServer is being inconsistent. Here is my code I am using:
Code: [Select]
#include <SPI.h>
#include "Ethernet.h"

// Ethernet library configuration
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };  //physical mac address
byte ip[] = { 192, 168, 0, 222 };                     // ip in lan
EthernetServer server(82);                            //server port

// HMTL processing variables
String readString = "";             //string to get incoming data

char c;
char buffer[10];
int dataLength =0;

// Buffer containing processed hmtl data
char data[50];
char datamotor[5];
int  index=3;

//Setting the time
int wdstarth = 0;
int wdstartm = 0;
int wdstartp = 0;
int westarth = 0;
int westartm = 0;
int westartp = 0;
int wdstoph = 0;
int wdstopm = 0;
int wdstopp = 0;
int westoph = 0;
int westopm = 0;
int westopp = 0;
int control = 2;
 
// Setup function
void setup()
{
   Ethernet.begin(mac, ip);   //start Ethernet
   Serial.begin(9600);
   Serial.print("The server is at: ");
   Serial.println(Ethernet.localIP());
}


// Loop function
void loop()
{
 EthernetClient client = server.available();
 if (client)
 {
    while (client.connected())
    {
       while (client.available())  // Receive client data
       {
       
         Serial.print(".");
         c = client.read();   //read char by char HTTP request
         readString +=c;
         //Serial.print(c);          //output chars to serial port
       
         // If first request upon connexion, the 3 first characters will be "GET"
         // If "GET" is caught, skip the request info
         if( readString.equals("GET"))
         {
           Serial.println("");
           Serial.println("GET caught, skipping request and printing HTML");
           break;
         }
       
         // Otherwise, if the request contains data,
         // the first characters will be "POST"
         // We then skip the request header and this "if" becomes our main function
         if( readString.equals("POST"))
         {
           Serial.println("");
           Serial.println("POST caught, skipping header and acquiring DATA");
           // 320 is arbitrary. The actual length that has to be skipped depends on
           // several user settings ( browser, language, addons...)
           // the skipped length has not to be too long to skip relevant data
           // and not to short to waste computing time
           for(int i=0; i<320; i++)
           {
             c = client.read();
             Serial.print(c); // UNCOMMENT FOR DEBUG
           }
           //Searches for "Length: "
           while(c  != 'L')
           {            
             c = client.read();
             Serial.print(c); // UNCOMMENT FOR DEBUG
           }
           // Skip "Length: "
           for (int i=0; i<7; i++)
           {
             c = client.read();
             Serial.print(c); // UNCOMMENT FOR DEBUG
           }
         
           // Read the data package length
           readString="";
           c = client.read();
         
           while(c != '\n')
           {
             readString += c;
             Serial.print(c);
             c = client.read();  
           }
         
           // convert data read from String to int
           readString.toCharArray(buffer, readString.length());
           dataLength = atoi(buffer);
           Serial.println("");
           Serial.print("dataLength: ");
           Serial.println(dataLength);
         
           // gets DATA
           client.read(); // skips additional newline
           client.read();
           for (int i=0; i<dataLength; i++)
           {
             data[i] = client.read();
           }
         
           Serial.println("");
           Serial.print("data: ");
           Serial.println(data);
           readString=data;
           checkURL(readString);
         
           readString ="";
         }      
       }
     
     
       // HTML CODE
         client.println("HTTP/1.1 200 OK");
         client.println("Content-Type: text/html");
         client.println("Connnection: close");
         client.println();
         client.println("<!DOCTYPE HTML>");
         client.println("<html>");
                   // add a meta refresh tag, so the browser pulls again every 5 seconds:
//          client.println("<meta http-equiv=\"refresh\" content=\"5\">");
         // print the hour, minute and second:
         client.print("<center><table border='1'><tr><td colspan='4' align='center'><b>Omni Systems Outdoor Lights Controller</b></td></tr><tr><td colspan='4' align='center'>");
         //FORM
         client.println("</td></tr><form method='post'><tr>");
         client.println("<td align='center' colspan='2'><b>Weekdays</b></td><td align='center' colspan='2'><b>Weekends</b></td></tr>");
         client.println("<tr><td align='center'><b>Start:</b></td><td align='center'><input type='text' name='wdstart' size='7'></td><td align='center'><b>Start:</b></td><td align='center'><input type='text' name='westart' size='7'></td>");
         client.println("<tr><td align='center'><b>Stop:</b></td><td align='center'><input type='text' name='wdstop' size='7'></td><td align='center'><b>Stop:</b></td><td align='center'><input type='text' name='westop' size='7'></td>");
         client.println("</tr><tr><td colspan='4' align='center'><b>Light Control: ");
         client.println("</td></tr><tr><td colspan='4' align='center'><input type='submit' value='Submit Changes'></td></tr></table>");
               client.println("</html>");
     
       Serial.println("__________");
       delay(100);
     
       client.stop();
     
    }
 }



 
 // Reinitializing variables
 readString ="";          // Reinitialize String
 for (int i=0; i<10; i++)
   {buffer[i] = '\0';}
 for (int i=0; i<50; i++)
   {data[i] = '\0';}
 for (int i=0; i<5; i++)
   {datamotor[i] = '\0';}
 dataLength =0;
 index = 3;

}

void checkURL(String readString) {
 int wdstartindex = readString.indexOf("wdstart=");
 int westartindex = readString.indexOf("westart=");
 int wdstopindex = readString.indexOf("wdstop=");
 int westopindex = readString.indexOf("westop=");
 wdstarth = readString.substring(wdstartindex+8, readString.indexOf("%3A")).toInt();
 wdstartm = readString.substring(readString.indexOf("%3A")+3, westartindex-1).toInt();
 westarth = readString.substring(westartindex+8, readString.indexOf("%3A", westartindex)).toInt();
 int colon = readString.indexOf("%3A", westartindex)+3;
 int stop = wdstopindex - 1;
 westartm = readString.substring(colon, stop).toInt();
 wdstoph = readString.substring(wdstopindex+7, readString.indexOf("%3A", wdstopindex)).toInt();
 colon = readString.indexOf("%3A", wdstopindex)+3;
 stop = westopindex - 1;
 wdstopm = readString.substring(colon, stop).toInt();
//  westoph = readString.substring(westopindex+7, readString.indexOf("%3A", westopindex)).toInt();
//  colon = readString.indexOf("%3A", westopindex)+3;
//  stop = readString.length()-1;
//  westopm = readString.substring(colon, stop).toInt();
 Serial.print("Weekday Start Time: ");
 Serial.print(wdstarth);
 Serial.print(":");
 Serial.println(wdstartm);
 Serial.print("Weekend Start Time: ");
 Serial.print(westarth);
 Serial.print(":");
 Serial.println(westartm);
 Serial.print("Weekday Stop Time: ");
 Serial.print(wdstoph);
 Serial.print(":");
 Serial.println(wdstopm);
//  Serial.print("Weekend Stop Time: ");
//  Serial.print(westoph);
//  Serial.print(":");
//  Serial.println(westopm);
}

The problem I am having is the last method, checkURL(). What it does is interpret the readString, which is the POST data, and set variables equal to the values found in the string. The problem is, I can check any 3 variables in any order, but as soon as I try to check all 4, the WebServer hangs and does one of two things:

  • The serial feed stops and the webserver hangs until I reset it

  • The serial feed keeps repeating the POST information infinitely until I have to reset it



I need to be able to read these 4 variables and one or two more...I can't have only 3 working. I don't get why only 3 of the 4 checks will work in any order or combination but all 4 cause the webserver/arduino to bug out. Also various (readString.indexOf("whatever") >= 0) cause the webserver to bug out similarly, but that's a different issue. I'm more interested in this right now.

If anyone can give me some insight on this, I would appreciate it so much. I've spent 10+ hours getting nowhere because code I am almost 100% positive should work doesn't.

SurferTim

You may be running out of SRAM. Try using the F() function to keep most of your static strings in program memory. For examples:
Code: [Select]
    Serial.print(F("The server is at: "));
    // and
    Serial.println(F("GET caught, skipping request and printing HTML"));

This should free up some memory. Staying away from the String data types can also help.

Nick Gammon

I agree with SurferTim. Use the F macro. Also rewrite to not use String.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

teddyz

I have similar problems with my Ethernet shield.

My problem is that it works for a while, and then stops. (OK, I admit that can be because I also fell in love with String...)

But the worst thing is that I can't reset the Ethernet shield with the reset button after it has been put into error state.

If I upload the code below when it is in "error state", it reports IP 255.255.255.255, and cannot be reached.

If I first disconnect power for a short while, it reports the IP I have set.

I am longing for a hard reset-function for my Ethernet Shield.


Code: [Select]
#include <SPI.h>
// Ethernet shield attached to pins 10, 11, 12, 13
#include <Ethernet.h>

byte mac[] = {
  0xDE, 0xAD, 0xBE, 0x21, 0x11, 0xDF };

byte ip[] = {
  192,168,1,178};

byte gateway[] = { 192, 168, 1, 1 };
byte subnet[] = { 255, 255, 255, 0 };

// IPAddress ip(192,168,1, 177);

// Initialize the Ethernet server library
EthernetServer server = EthernetServer(80);

EthernetClient client;

void setup() {
  Serial.begin(115200);
  tone ( A0, 660 );

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  //Ethernet.begin(mac, ip, gateway, subnet);
 
  Serial.print("Web server address is ");
  Serial.println(Ethernet.localIP());


  server.begin();

  noTone(A0);
}


void loop() {
  while(true)
    ;
}

SurferTim

Quote
My problem is that it works for a while, and then stops. (OK, I admit that can be because I also fell in love with String...)

But the worst thing is that I can't reset the Ethernet shield with the reset button after it has been put into error state.

My goal is to prevent the error state. What code are you using to get it into an error state?

teddyz

I am using a program involving the Ethernet, 433MHz remote control transmitting and decoding, 433MHz temperature receiving, and a web server to connect to the world.
I wish I could find a way to produce the error state, but I do not know what is causing it.

An idea: I am using the Mega, and to make the SD-library work I need to set pin 53 as an output, otherwise it is not working. Is it the same for Ethernet? Should I address the SS to another address than pin 10?
Quote from CardInfo example:
Code: [Select]
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output
  // or the SD library functions will not work.
  pinMode(10, OUTPUT);     // change this to 53 on a mega

SurferTim

I use a setup like this and it doesn't fail. I use a Mega also.
Code: [Select]
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

// change to your network settings
IPAddress ip( 192,168,2,2 );
IPAddress gateway( 192,168,2,1 );
IPAddress subnet( 255,255,255,0 );

EthernetServer server(80);

void setup()
{
  Serial.begin(9600);

  // disable w5100 while setting up SD
  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);

  Serial.print("Starting SD..");
  if(!SD.begin(4)) Serial.println("failed");
  else Serial.println("ok");
 
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  digitalWrite(10,HIGH);

  delay(2000);
  server.begin();
  Serial.println("Ready");
}

void loop() {
}

Here is my full server code. It has been consistent for me.
http://playground.arduino.cc/Code/WebServerST

Go Up