Ethernet Shield - (params, "?led=on") doesn't return 0

I’m starting with arduino and I’ve bought a ENC28J60 Ethernet Shield, and search for some sketch examples online. So i found this:

// A simple web server that turn an LED on or off"

#include "etherShield.h"
#include "ETHER_28J60.h"

int outputPin = 6;

static uint8_t mac[6] = {0x54, 0x55, 0x58, 0x10, 0x00, 0x24};   // this just needs to be unique for your network, 
                                                           
static uint8_t ip[4] = {192, 168, 1, 15}; // IP address for the webserver

static uint16_t port = 80; // Use port 80 - the standard for HTTP


ETHER_28J60 e;

void setup()
{ 
  e.setup(mac, ip, port);
  pinMode(outputPin, OUTPUT);
}

void loop()
{
  char* params;
  if (params = e.serviceRequest())
  {
    e.print("<h1><a href='/?led=off'>Arduino Web Remote</a></h1>");
    if (strcmp(params, "?led=on") == 0)
    {
      digitalWrite(outputPin, HIGH);
      e.print("<a href='?led=off'><button style='border: 1px solid #ff0000; border-left: 10px solid #ff0000' type='button'>LED IS ON</button></a>");
    }
    else if (strcmp(params, "?led=off") == 0)
    {
      digitalWrite(outputPin, LOW);
      e.print("<a href='?led=on'><button style='border: 1px solid #000; border-left: 10px solid #000' type='button'>LED IS OFF</button></a>");
    }
    e.respond();
  }
}

I tried this code and it perfectly worked. Then i tried to do my own, based on this, and it didn’t work, 'cause the (params, “?led=on”) apparently is not equal 0;

Here’s my code:

#include "etherShield.h"
#include "ETHER_28J60.h"

int led = 6;

static uint8_t mac[6] = {0x54, 0x55, 0x58, 0x10, 0x00, 0x24};

static uint8_t ip[4] = {192, 168, 1, 15};

static uint16_t port = 80;

static byte gwip[4] = {192, 168, 25, 1};

ETHER_28J60 e;

void setup() {
  e.setup(mac, ip, port);
  pinMode(led, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  char* params;
  if (params = e.serviceRequest()) {
    e.print("<head><style>h1 {text-align:center; font-family:courier} body {background-color:lightgrey} button {background-color:red; border: 2px solid black; font-color:black;} button#off {background-color:white} p {text-align:center}</style></head><body><h1>Arduino Controle Web Teste</h1><p>
<a href=/?led=on><button>Led On</button></a>



<a href=/?led=off><button id=off>Led Off</button></a>
</p></body>");
    if (strcmp(params, "?led=on") == 0) {
      digitalWrite(led, 1);
      e.print("
Les is on
");
    }  else if (strcmp(params, "?led=off") == 0) {
      digitalWrite(led, 0);
      e.print("
Led is off
");
    }
    Serial.println(strcmp(params, "?led=on"));
    e.respond();
  }
}

How does this work

static byte gwip[4] = {192, 168, 25, 1};
static uint8_t ip[4] = {192, 168, 1, 15};

Gateway should be something like 192.168.1.0 if the ip is 192.168.1.15 192.168.1.15 can't see 192.168.25.1 there not on the same network.

But 192.168.25.1 only can see 192.168.25.1 - 192.168.25.254 It can't see any of these 192.168.1.1 - 192.168.1.254

  char* params;
  if (params = e.serviceRequest())
  {

Boy, that is ugly, and needs to read more than once to understand. A little rearrangement, and suddenly, its crystal clear.

  char *params = e.serviceRequest();
  if (params)
  {

For now, get rid of all the style crap.

    e.print("<head></head><body><h1>Arduino Controle Web Teste</h1><p>
<a href=/?led=on><button>Led On</button></a>



<a href=/?led=off><button id=off>Led Off</button></a>
</p></body>");

Why does one button have an ID and one not?

Forms make a lot more sense.

    Serial.println(strcmp(params, "?led=on"));

Since I know what strcmp() does, I konw that printing -1, 0, or 1 anonymously makes no sense.

Serial.print("params: [");
Serial.print(params);
Serial.println("]");

would give you orders of magnitude more information. Maybe even enough to look a little like a clue.

Thanks for the tips, i’v made the alterations you suggested.

void loop() {
  char *params = e.serviceRequest();
  if (params) {

It does get far more easy to understand.

But when I did this, as you suggested:

Serial.print("params: [");
    Serial.print(params);
    Serial.println("]");

All that i had in my Serial Monitor was this: “params:
params: [favicon.ico]
params: [?led=on]
params: [favicon.ico]
params: [?led=off]
params: [favicon.ico]
params: [?led=on]
params: [favicon.ico]”

But here’s the interesting: it started do work, my led is turning on and off. But because i didn’t understand yet why it worked, i add this line to the code:

 Serial.print("params: [");
    Serial.print(strcmp(params, "?led=on"));
    Serial.println("]");
    
    Serial.print("params: [");
    Serial.print(strcmp(params, "?led=off"));
    Serial.println("]");

And then my Serial Monitor returns to me (when i click “Led On” on the page) this: “params: [?led=on]
params: [0]
params: [8]
params: [favicon.ico]
params: [39]
params: [39]”

And this when i click on the “Led Off”: “params: [?led=off]
params: [-8]
params: [0]
params: [favicon.ico]
params: [39]
params: [39]”

I suppose those are the 0 and 0 that should happened, so that is why my led now is blinking, but why it didn’t return this values before?? In my old code the line Serial.println(strcmp(params, “?led=on”)); was printing:

“51
51”

What makes those values change??

So just after i post this i put back my “style crap” XD.
Everything stop working again! And look what came back in my serial monitor, when i press “Led On”:

“params: [r>

]
params: [51]
params: [51]”

When i press “Led Off”:

“params: [r>

]
params: [51]
params: [51]”

No 0, just 51.

I can’t put any styles??

All that i had in my Serial Monitor was this: “params:
params: [favicon.ico]
params: [?led=on]
params: [favicon.ico]
params: [?led=off]
params: [favicon.ico]
params: [?led=on]
params: [favicon.ico]”

That’s good.

But because i didn’t understand yet why it worked, i add this line to the code:

So, now you are printing the value returned by strcmp(). The value will be less than 0 if the first string comes before the second string in the dictionary, 0 if the strings are the same, and greater than 0 if the first string comes after the second string in the dictionary. (I may have the meaning of >0 and <0 reversed, but it doesn’t matter; 0 means they are the same, while any other value means that they are not.)

In my old code the line Serial.println(strcmp(params, “?led=on”)); was printing:

“51
51”

When the first string, the value in params, is “favicon.ico” and the second string is “?led=on”, what would you expect strcmp() to return? Why are you surprised/disappointed/upset that it returns 51? Printing the value is meaningless.

All that i had in my Serial Monitor was this: "params: []
params: [favicon.ico]
params: [?led=on]
params: [favicon.ico]
params: [?led=off]
params: [favicon.ico]
params: [?led=on]
params: [favicon.ico]"

Browsers (some more than others) send request for the favorite icon. In the below code I simply use and look for “on1” instead of just “on” to solve the problem.

//zoomkat 10-6-13
//simple button GET with iframe code
//open serial monitor to see what the arduino receives
//use the ' instead of " in html ilnes 
//address will look like http://192.168.1.102:84/ when submited
//for use with W5100 based ethernet shields

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

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //ethernet shield mac address
byte ip[] = { 192, 168, 1, 102 }; // arduino IP in lan
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port

String readString; 

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

void setup(){

  pinMode(4, OUTPUT); //pin selected to control
  //start Ethernet
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  server.begin();

  //enable serial data print 
  Serial.begin(9600); 
  Serial.println("servertest1"); // so I can keep track of what is loaded
}

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 

          //now output HTML data header
             if(readString.indexOf('?') >=0) { //don't send new page
               client.println("HTTP/1.1 204 Zoomkat\r\n\r\n");
             }
             else {
          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("<TITLE>Arduino GET test page</TITLE>");
          client.println("</HEAD>");
          client.println("<BODY>");

          client.println("<H1>Zoomkat's simple Arduino button</H1>");
          
          client.println("<a href='/?on1' target='inlineframe'>ON</a>"); 
          client.println("<a href='/?off' target='inlineframe'>OFF</a>"); 

          client.println("<IFRAME name=inlineframe style='display:none'>");          
          client.println("</IFRAME>");

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

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

          ///////////////////// control arduino pin
          if(readString.indexOf("on1") >0)//checks for on
          {
            digitalWrite(4, HIGH);    // set pin 4 high
            Serial.println("Led On");
          }
          if(readString.indexOf("off") >0)//checks for off
          {
            digitalWrite(4, LOW);    // set pin 4 low
            Serial.println("Led Off");
          }
          //clearing string for next read
          readString="";

        }
      }
    }
  }
}

PaulS:

But if i compared “?led=on” with the href of the button i clicked on (also “?led=on”), shouldn’t it return 0??

if (strcmp(params, "?led=on") == 0)

Anyway, as the only thing i changed the last time that make a difference was the style (now i think that is the size of the string where is the html), i continue to change it. If i keep it this way:

e.print("<head></head><body style='background-color:lightgrey'><h1 style='text-align:center; font-family:courier'>Arduino Controle Web Teste</h1>");
    e.print("<p style='text-align:center'>
<a href=/?led=on><button style='background-color:red; border: 2px solid black; padding: 15px'>Led On</button></a>


");
    e.print("
<a href=/?led=off><button style='background-color:white; border: 2px solid black; padding: 15px'>Led Off</button></a>
</p></body>");

It doesn’t work, but if i reduce the html, taking the padding of both buttons, for example, it works normally again!

With the padding, look what it returns:

params: [f</button></a>
</p></body>]
params: [39]
params: [39]
params: [f</button></a>
</p></body>]
params: [39]
params: [39]

ZoomKat:

Browsers (some more than others) send request for the favorite icon. In the below code I simply use and look for “on1” instead of just “on” to solve the problem.

Ok, but the code you posted doesn’t work on my shield (ENC28J60), and i also didn’t get what i suppose to do in my code. Where do i change “on” to “on1”??

It doesn't work, but if i reduce the html, taking the padding of both buttons, for example, it works normally again!

Running out of memory will cause all kinds of bizarre behavior. That's obviously what you were doing.

dannielcordeiro: ZoomKat:

Ok, but the code you posted doesn't work on my shield (ENC28J60), and i also didn't get what i suppose to do in my code. Where do i change "on" to "on1"??

Using a 'dumb' ENC28J60 network controller with the TCP/IP network stack emulated all in software will cost you huge amounts of RAM which will then not be available to your application.

Using a 'smart' W5100 network controller with all TCP/IP network stack built into its firmware will leave much more memory free in your Atmega controller, which then can be used by your application code.

So you better not expect that you can use much RAM after including your TCP stack software emulation libraries, which are required for ENC28J60.

There had been a reason that the creators of Arduino decided to use a smart W5100 chip for networking, but you seem to ignore those reasons.

If you decide for ENC28J60, you instantly decide for very little functions to create in your sketch, or you run out of RAM quickly.

BTW: The code posted by zoomcat is for W5100 network controllers only, you can see that from the included libraries in the sketch.