Arduino Mega + Ethernet (WIZ812MJ) example help

Hi, I am new to this forum but have been programing for years. I do most of my programing in PHP or on the iPhone. I am trying to interface the Arduino Mega with a web site and eventually an iPhone app to both send commands and data and receive data.

The first step toward this is being able to communicate between the arduino and a web site. I have a web sever on my local network to play with. I can use the example sketches to download content from the server or to setup the arduino as a server and send out html responses to request made to the arduino.

The problem I am having is this, I would like a button on a web page, either served by the arduino or served by my server which then relays the request to the arduino, to which the arduino receives and executes specific code based on the request. I click LED ON button on a web site and the arduino turns on an led, and also tells me the current status of the LED on the web page. I need a to be able to request data and have a response sent back as well as just issue a command with parameters to the arduino to execute.

Here is the code I have so far... I cant find an example of how to listen for the response and do something based on it... Any help or examples would be great!

#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 24 };
byte gateway[] = { 192, 168, 1, 1 };
byte subnet[]  = { 255, 255, 255, 0 };

Server server(80);

void setup()
{
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();
}

void loop()
{
  Client client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean current_line_is_blank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        // if we've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so we can send a reply
        if (c == '\n' && current_line_is_blank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
         
          client.print("<html>");
          client.print("<head><meta name=\"viewport\" content=\"width=device-width\"><title>Arduino LED Test</title></head>"); // mobile optimized
          client.print("<body>");
          client.print("<form method=GET><input type=submit name=LED value=HIGH></form>");
          client.print("</body>");
          client.print("</html>");
          
          break;
        }
        if (c == '\n') {
          // we're starting a new line
          current_line_is_blank = true;
        } else if (c != '\r') {
          // we've gotten a character on the current line
          current_line_is_blank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    client.stop();
  }
}

The ethernet shield isn't compatible with the MEGA without rewiring some pins (the MEGA's SPI isn't on pins 11/12/13) and hacking a bit of the ethernet code. There has been a post in the past 24 hours or so with information on that.

-j

I am using this http://www.nkcelectronics.com/nkc-ethernet-shield-for-arduino-mega--duemilanove--diecimila-diy-kit.html which is designed to work with the Mega with just a change of one library file and it works fine. It is based on the WIZ812MJ chip and standard arduino library.

"This Ethernet shield is 100% compatible with the official Arduino Ethernet Library.

It works with:

Arduino Duemilanove and all its variations (Freeduino, Seeeduino, etc)
Arduino MEGA (with a small modification to spi.h)"

I am just looking for the code to make the arduino do something based on the form shown in the code....

Cool, was not aware of the NKC shield.

You'll still need to make the software mod in the library.

As far as HTML communications go, I don't have an answer for that as the code is a bit more complex. I'd make sure you can do simple things like ping the arduino, grab simple text from the web using the arduino, etc before leaping into POST processing.

-j

Yep it is a pretty cool shield. I can do all of those things. In the example above, which is currently running on my mega, it acts as a server serving the html shown at the ip address listed. When I visit the site via a web browser I see the button but there is no code in the arduino that says Run this function when the user submits this form. Thats the part I need to know.

I'm now looking at this...

Will the "current_line_is_blank = false" clause be the place to place to trap strings to interpret and then call functions to do the stuff ??

I do not know about web servers so I just guessing.

I'll Google it.

Chewie B

No I was wrong.
The browser submits a load of data before the blank line that indicates an http request has ended.

I added a Serial.print(c) after the "char c = client.read();" line to investigate this.

I get ...

GET /html_form_submit.asp?user=h HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/x-shockwave-flash, */*
Referer: http://192.168.1.177/html_form_submit.asp?user=fred
Accept-Language: en-gb
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Accept-Encoding: gzip, deflate
Host: 192.168.1.177
Connection: Keep-Alive

Were my form asks for the "user" name and I typed in "fred". The interesting bit is....

Referer: http://192.168.1.177/html_form_submit.asp?user=fred

Hope this helps you as I now stuck trying to strip out the strings in the client message.

Chewie B :-[

I figured this out. Here is complete code on how to turn on and off leds based on post response from a seperate web server...

#define WEBDUINO_FAIL_MESSAGE "<h1>Request Failed</h1>"
#include "Ethernet.h"
#include "WebServer.h"

#define VERSION_STRING "0.1"

/* CHANGE THIS TO YOUR OWN UNIQUE VALUE.  The MAC number should be
 * different from any other devices on your network or you'll have
 * problems receiving packets. */
static uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };


/* CHANGE THIS TO MATCH YOUR HOST NETWORK.  Most home networks are in
 * the 192.168.0.XXX or 192.168.1.XXX subrange.  Pick an address
 * that's not in use and isn't going to be automatically allocated by
 * DHCP from your router. */
static uint8_t ip[] = { 192, 168, 1, 64 };

int led[14] = {22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35};

// ROM-based messages used by the application
// These are needed to avoid having the strings use up our limited
//    amount of RAM.

P(Page_start) = "<html><head><title>Web_Parms_1 Version " VERSION_STRING "</title></head><body>\n";
P(Page_end) = "</body></html>";
P(Get_head) = "<h1>GET from >";
P(Post_head) = "<h1>POST to ";
P(Unknown_head) = "<h1>UNKNOWN request for ";
P(Default_head) = "unidentified URL requested.</h1>
\n";
P(Raw_head) = "raw.html requested.</h1>
\n";
P(Parsed_head) = "parsed.html requested.</h1>
\n";
P(Good_tail_begin) = "URL tail = '";
P(Bad_tail_begin) = "INCOMPLETE URL tail = '";
P(Tail_end) = "'
\n";
P(Parsed_tail_begin) = "URL parameters:
\n";
P(Parsed_item_separator) = " = '";
P(Params_end) = "End of parameters
\n";
P(Post_params_begin) = "Parameters sent by POST:
\n";
P(Line_break) = "
\n";
P(test) = "test";



/* This creates an instance of the webserver.  By specifying a prefix
 * of "", all pages will be at the root of the server. */
#define PREFIX ""
WebServer webserver(PREFIX, 80);



/* commands are functions that get called by the webserver framework
 * they can read any posted data from client, and they output to the
 * server to send data back to the web browser. */
void helloCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  /* this line sends the standard "we're all OK" headers back to the
     browser */
  server.httpSuccess();

  /* if we're handling a GET or POST, we can output our data here.
     For a HEAD request, we just stop after outputting headers. */
  if (type == WebServer::HEAD)
    return;

  server.printP(Page_start);
  switch (type)
    {
    case WebServer::GET:
        server.printP(Get_head);
        break;
    case WebServer::POST:
        server.printP(Post_head);
        break;
    default:
        server.printP(Unknown_head);
    }

    server.printP(Default_head);
    server.printP(tail_complete ? Good_tail_begin : Bad_tail_begin);
    server.print(url_tail);
    server.printP(Tail_end);
    server.print("hello");
    server.printP(Page_end);
    

}


void rawCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  /* this line sends the standard "we're all OK" headers back to the
     browser */
  server.httpSuccess();

  /* if we're handling a GET or POST, we can output our data here.
     For a HEAD request, we just stop after outputting headers. */
  if (type == WebServer::HEAD)
    return;

  server.printP(Page_start);
  switch (type)
    {
    case WebServer::GET:
        server.printP(Get_head);
        break;
    case WebServer::POST:
        server.printP(Post_head);
        break;
    default:
        server.printP(Unknown_head);
    }

    server.printP(Raw_head);
    server.printP(tail_complete ? Good_tail_begin : Bad_tail_begin);
    server.print(url_tail);
    server.printP(Tail_end);
    server.print("raw");
    server.printP(Page_end);
     

}

#define NAMELEN 32
#define VALUELEN 32

void parsedCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  URLPARAM_RESULT rc;
  char name[NAMELEN];
  int  name_len;
  char value[VALUELEN];
  int value_len;

  /* this line sends the standard "we're all OK" headers back to the
     browser */
  server.httpSuccess();

  /* if we're handling a GET or POST, we can output our data here.
     For a HEAD request, we just stop after outputting headers. */
  if (type == WebServer::HEAD)
    return;

  server.printP(Page_start);
  switch (type)
    {
    case WebServer::GET:
        server.printP(Get_head);
        break;
    case WebServer::POST:
        server.printP(Post_head);
        break;
    default:
        server.printP(Unknown_head);
    }

    server.printP(Parsed_head);
    server.printP(tail_complete ? Good_tail_begin : Bad_tail_begin);
    server.print(url_tail);
    server.printP(Tail_end);
    server.print("ttt");

  if (strlen(url_tail))
    {
    server.printP(Parsed_tail_begin);
    while (strlen(url_tail))
      {
      rc = server.nextURLparam(&url_tail, name, NAMELEN, value, VALUELEN);
      if (rc == URLPARAM_EOS)
        server.printP(Params_end);
       else
        {
        server.print(name);
        server.printP(Parsed_item_separator);
        server.print(value);
        server.printP(Tail_end);
        // This is the spot to put the code!!!!!!!!!
       
       int L = 0;
         if ( name[0] == 'a' )
           L = 0;
         else if ( name[0] == 'b' )
           L = 5;
         else if ( name[0] == 'c' )
           L = 10;
         
         int a = atoi(value);
         
        if ( a == 1 )
          digitalWrite(led[L], HIGH);
        else if ( a == 0 )          
          digitalWrite(led[L], LOW); 
         
        
        }
      }
    }
  if (type == WebServer::POST)
  {
    server.printP(Post_params_begin);
    while (server.nextURLparam(&url_tail, name, NAMELEN, value, VALUELEN))
    {
      server.print(name);
      server.printP(Parsed_item_separator);
      server.print(value);
      server.printP(Tail_end);
      server.print("parse");
    }
  }
  server.printP(Page_end);
 
}

void my_failCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  /* this line sends the standard "we're all OK" headers back to the
     browser */
  server.httpFail();

  /* if we're handling a GET or POST, we can output our data here.
     For a HEAD request, we just stop after outputting headers. */
  if (type == WebServer::HEAD)
    return;

  server.printP(Page_start);
  switch (type)
    {
    case WebServer::GET:
        server.printP(Get_head);
        break;
    case WebServer::POST:
        server.printP(Post_head);
        break;
    default:
        server.printP(Unknown_head);
    }

    server.printP(Default_head);
    server.printP(tail_complete ? Good_tail_begin : Bad_tail_begin);
    server.print(url_tail);
    server.printP(Tail_end);
    server.print("fail");
    server.printP(Page_end);
     

}




void setup()
{
  /* initialize the Ethernet adapter */
  Ethernet.begin(mac, ip);

  /* setup our default command that will be run when the user accesses
   * the root page on the server */
  webserver.setDefaultCommand(&helloCmd);

  /* setup our default command that will be run when the user accesses
   * a page NOT on the server */
  webserver.setFailureCommand(&my_failCmd);

  /* run the same command if you try to load /index.html, a common
   * default page name */
  webserver.addCommand("index.html", &helloCmd);

  /*This command  is called if you try to load /raw.html */
  webserver.addCommand("raw.html", &rawCmd);
  webserver.addCommand("parsed.html", &parsedCmd);

  /* start the webserver */
  webserver.begin();
  for ( int i = 0; i < 14; i++ )
    pinMode(led[i], OUTPUT);
  
}

void loop()
{
  char buff[64];
  int len = 64;

  /* process incoming connections one at a time forever */
  webserver.processConnection(buff, &len);
}

Code for web site.....

<form id="addUser" name="addUser" method="GET" action="http://192.168.1.64/parsed.html" >
V1 ON<input type="checkbox" name="a" value="1" />
      OFF<input type="checkbox" name="a" value="0" />

      V2 ON<input type="checkbox" name="b" value="1" />
      OFF<input type="checkbox" name="b" value="0" />

      V3 ON<input type="checkbox" name="c" value="1" />
      OFF<input type="checkbox" name="c" value="0" />

      <input type="submit" value="update" />
</form>

I hope this helps someone else out....