Ethernet Shield WebServer timing out/can't connect

Hi all,

Working on a project to control an ROV through an ethernet tether running directly from my laptop through a cat5 cable to an Uno with an Ethernet Shield.

At this point, I’m simply trying to make a server that turns an LED on and off and reads sensor data from an accelerometer (For the sake of solving this problem I have commented out the additional code related to the accelerometer and am strictly trying to get the server to communicate with the laptop for the purposes of turning on the LED. I’ve included it for completeness).

I have written the following sketch which initializes a server, and attempts to gather input from the laptop/client. However, when I attempt to connect to the server it times out (Chrome error ERR_CONNECTION_TIMED_OUT; ping response “Request timed out”). As you can see, I’ve got most of my HTML printing from code memory rather than SRAM, and it is a simple program so I don’t think I’m having memory issues. I’m concerned with my sockets, however, because the debug data returned is “0x0 D:0.0.0.0” on every socket. Maybe a client sided issue?

I’m very new to back-end programming so feel free to treat me like a kindergartner, haha.

Thanks so much!

#include <SPI.h>
#include <Wire.h>
#include <Ethernet.h>
//#include <SparkFunLSM9DS1.h> //Special Library for using LSM9DS1 sensor
#include <utility/w5100.h>

// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte gateway[] = {192, 168, 1, 1};
byte subnet[] = {255, 255, 255,0};
byte socketStat[MAX_SOCK_NUM];
IPAddress ip(192, 168, 1, 2); // IP address, may need to change depending on network
EthernetServer server(80);  // create a server at port 80

String HTTP_req;          // stores the HTTP request
boolean LED_status = 0;   // state of LED, off by default

//LSM9DS1 imu; //Accelerometer object, SparkFun LSM9DS1

void setup()
{
    //imu.settings.device.commInterface = IMU_MODE_I2C; // Set mode to I2C
    //imu.settings.device.mAddress = 9; // Mag CS pin connected to D9
    //imu.settings.device.agAddress = 10; // AG CS pin connected to D10
    Ethernet.begin(mac, ip, gateway, gateway, subnet);  // initialize Ethernet device
    server.begin();           // start to listen for clients
    Serial.begin(9600);       // for diagnostics
    pinMode(13, OUTPUT);       // LED on pin 13
}
// outputs socket status to serial console for debugging purposes
void ShowSockStatus(){
  for (int i=0; i < MAX_SOCK_NUM; i++){
    Serial.print(F("Socket#"));
    Serial.print(i);
    uint8_t s = W5100.readSnSR(i);
    socketStat[i] = s;
    Serial.print(F(":0x"));
    Serial.print(s,16);
    Serial.print(F(" "));
    Serial.print(W5100.readSnPORT(i));
    Serial.print(F(" D:"));
    uint8_t dip[4];
    W5100.readSnDIPR(i, dip);
    for (int j=0; j<4; j++) {
      Serial.print(dip[j],10);
      if(j<3) {Serial.print(".");}
    }
  Serial.print(F("("));
  Serial.print(W5100.readSnDPORT(i));
  Serial.println(F(")"));
  }
}

void ProcessLEDButton(EthernetClient cl) { // switch LED and send back HTML
    if (HTTP_req.indexOf("on1") > -1) {  // see if button is clicked
        // the button is clicked, turn on LED
            LED_status = 1;
        }
    if (HTTP_req.indexOf("off1") > -1) { //if button is not clicked, turn off LED
            LED_status = 0;
        }
    if (LED_status) {    // switch LED on
        digitalWrite(13, HIGH);
    }
    else {              // switch LED off
        digitalWrite(13, LOW);
    }
}
/*
void readSensor(EthernetClient cl) {
  if (!imu.begin()) {//initialize sensor
    Serial.println("Failed to communicate with LSM9DS1.");
  }
  else {
    //update data from Accelerometer
    imu.readAccel(); 
    imu.readGyro();
    imu.readMag();
    // display data
    cl.println(F("Accelerometer Readings:"));
    cl.print(imu.calcAccel(imu.ax));
    cl.print(", ");
    cl.print(imu.calcAccel(imu.ay));
    cl.print(", ");
    cl.println(imu.calcAccel(imu.az));
    cl.println(F("Gyro Readings:"));
    cl.print(imu.calcGyro(imu.gx));
    cl.print(", ");
    cl.print(imu.calcGyro(imu.gy));
    cl.print(", ");
    cl.println(imu.calcGyro(imu.gz));
    cl.println(F("Magnetometer Readings:"));
    cl.print(imu.calcMag(imu.mx));
    cl.print(", ");
    cl.print(imu.calcMag(imu.my));
    cl.print(", ");
    cl.println(imu.calcMag(imu.mz));
  }
}
*/  
void loop() {
    EthernetClient client = server.available();  // try to get client
    ShowSockStatus();
    if (client) {  // got client?
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {   // client data available to read
                char c = client.read(); // read 1 byte (character) from client
                HTTP_req += c;  // save the HTTP request 1 char at a time
                // last line of client request is blank and ends with \n
                // respond to client only after last line received
                if (c == '\n' && currentLineIsBlank) {
                    // send a standard http response header
                    client.println("HTTP/1.1 200 OK");
                    client.println("Content-Type: text/html");
                    client.println("Connection: close");
                    client.println();
                    // send HTML to client
                    client.println(F("<html>"));
                    client.println(F("<head>"));
                    client.println(F("<title>Arduino ROV Controls</title>"));
                    client.println(F("<body>"));
                    client.println(F("<h1>LED Switch</h1>"));
                    client.println(F("<form method = 'get'>"));
                    client.println(F("<input type='button' name='LED' value=ON onmousedown=location.href='?on1' onmouseup=location.href='?off1'></>"));
                    client.println(F("</form>"));
                    client.println(F("
"));
                    ProcessLEDButton(client);
                    //readSensor(client);
                    client.println(F("</body>"));
                    client.println(F("</html>"));
                    break;
                }
                // every line of text received from the client ends with \r\n
                if (c == '\n') {
                    // last character on line of received text
                    // starting new line with next character read
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    // a text character was received from client
                    currentLineIsBlank = false;
                }
            } // end if (client.available())
        } // end while (client.connected())
        delay(1);      // give the web browser time to receive the data
        client.stop(); // close the connection
    } // end if (client)
}

A much easier way to communicate would be a telnet connection. Look at the example in the Ethernet library. Then it is much more like a serial connection where you type a command and the uno receives it.

You should also avoid the String class, especially on an Uno as it will eat up a lot of memory and eventually crash, especially how you are using it to append 1 char at a time.

Thanks! I'll try both. Instead of string I'm guessing I should use a char array, or is there another option?

daonstott:
Thanks! I’ll try both. Instead of string I’m guessing I should use a char array, or is there another option?

it is not ‘string’ but ‘String’ that is the problem. The ‘String’ class allocates, and re-allocates, memory in the background which can lead to problem. A ‘string’ is a char array that you allocate and then you have to manage such that you don’t overrun the limits, etc. A bit more work but a good idea on these small memory MCUs