Sunday, June 9, 2013

How to: Connect your Arduino to the Internet as a Web Server

The following is a post by the Irreverent Engineer.  We are not responsible for what he says.  There is some good information below, but you gotta take it with the off color comments he produces.  Put on your filters folks here goes...


The INTERNET OF THINGS...
< queue lightning and thunder >

It's what all the cool kids are doing these days.  Why should they have all the fun?  Let's setup an Arduino as a Web Server that anyone, anywhere can view.  Why would we do such a thing?  Possible projects include collecting data from a sensor and posting it to the Web or controlling an actuator remotely.  Think internet connected fart sensor that logs realtime how awesome your roommate's flatulence is, or perhaps, a robot that hides in the bushes and pokes pedestrians sauntering by.

Here is a quick video detailing the setup that I will take you through.  We have a servo and an LED that are controlled via a Web page.  The control page is accessible from both the private and public networks (aka: internet accessible for anyone).  The video shows me turning both the servo and LED on and off from my computer and iPhone (with the wireless network turned off so as to force it to access the Arduino from the public network).  I also have a live video feed coming from a wireless IP camera so that you can view what is happening remotely in the case you were to use this functionality for a remote control application that required monitoring of the system.



Awesome, so let's starting tinkering on Al Gore's interweb.  Here's how to do it and what you'll need:

Materials:
1)  Internet connection
2)  Internet router and associated information (LAN IP address, WAN IP Address... don't panic more on this soon)
3)  Arduino
4)  Arduino compatible Ethernet shield (I am using the shield by Seeed Studio)
5)  Ethernet cable
6)  Computer with Arduino programming ability

Lingo:
1)  LAN = Local Area Network
2)  WAN = Wide Area Network
3)  IP Address = Internet Prototocol Address
4)  ISP = Internet Service Provider

Lets get going!


STEP 1:  COLLECT INFORMATION ABOUT YOUR HOME NETWORK

First things first, you need to find the following information about your home network:

a)  The login name and password for your router.  My login credentials were listed on the back of my router on a sticker.  They were super complex credentials... Login = "admin", Password = "password".

b)  Your LAN IP address (aka: Private IP address) and/or your router manager login site.  I have a NetGear router and it listed the router manager login site on the back sticker as http://www.routerlogin.net.  If you do not have something similar on your router try entering these standard LAN IP addresses into your web browser 192.168.2.1,  192.168.0.1, 192.168.1.1 .  You will know it works if you land on a page that requests a login and password (which should be provided on the back of your router or in documentation from your internet service provider).  If you connected via a router login site, you can then find your LAN IP by browsing around and finding a page that details your LAN.  The IP address will generally be of the form xxx.xxx.x.x.

c)  Your WAN IP address (aka: Public IP address).  This one is easy.  Just google "what's my ip address".  Google returns your WAN/Public IP address.  This information will also be listed once you login to your router.


STEP 2:  PLUG N' CHUG

a)  Plug the Ethernet shield into your Arduino.
b)  Plug your Arduino into your computer via the USB cable.
c)  Plug your Ethernet cable into the Ethernet shield and the other end into an open Ethernet plug on your router.


STEP 3:  SETUP PORT FORWARDING

If we want anyone, anywhere to have access to the Arduino Web Server we need to setup something called port forwarding.  This is an option you can set within your Internet router manager.  To make a long story short, port forwarding will allow interactions between the WAN and the LAN, aka:  It exposes your Arduino to the Public network as opposed to keeping it isolated in the Private network.  Thus, anyone, anywhere with Internet access can interact with your Arduino.

a)  Find the IP address of your Arduino.  To do this login to your router manager (see Step 1 parts a & b).  Once logged into your router, find a page titled something similar to "Attached Devices".  Once here, you will be able to see the LAN IP address unique to your Arduino, commonly 192.168.1.177.

b)  Once you have the Arduino LAN IP, find a page within your router called "Port Forwarding".  From here you will have to find the option to "add custom service" or something similar.  To setup a new custom service, enter the LAN IP address of your Arduino, choose TCP/UDP for protocol, choose an open port, how about 8081 - use this number for both the starting port and ending port, and a name for the new service.  Once created, your new custom service (port forwarding for your Arduino) it will show up in the port forwarding list.


STEP 4: CODE AND TEST

Now that all the network bogusness is taken care of we can focus on making widgets whirl.  This code creates a Web Server that can be accessed by entering "http://xx.xxx.xx.xx:8081/"  where, xx.xxx.xx.xx is your WAN IP address.  If you used a different port than 8081 just change the last digits following the ":" to the port you used.  The web page has 5 buttons that control an LED on pin 9 and a servo on pin 6.

a)  Save the code down to your Arduino  (see code included at the end of this post)
b)  Go to "http://xx.xxx.xx.xx:8081/" or whatever is appropriate relative to how you set things up.

Hopefully at this point you see a pretty basic Web page that has buttons for turning on and off the LED and making the servo go forward, backward, or stop.  The code I supplied also imports a live video feed from an IP camera but this functionality is commented out.  Perhaps in the future I will detail how to set that up in another post.



STEP 5: BUILD THE CIRCUIT

The circuit I built is shown below.  This circuit depiction was drawn using a great tool called Fritzing.  This is pretty self explanatory.  The resistor is a 220ohm resistor.
























Here is the code to save down to your Arduino.
Note, this is modified code relying heavily on code from the following source:
Arduino Cookbook, Second Edition, by Michael Margolis with Nick Weldin (O'Reilly). Copyright 2012 Michael Margolis, Nicholas Weldin, 978-1-4493-1387-6.


<<<<<<  BEGINNING OF ARDUINO CODE  >>>>>>


/*
 * WebServerPost sketch
 * Turns pin 9 on and off using HTML form
 */

 //The web form will be located at your public IP address followed by
//the port you are using, eg: "ip address:8081"
 //You can find your IP by
 //googling "what's my ip".

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

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

const int MAX_PAGENAME_LEN = 8; // max characters in page name
char buffer[MAX_PAGENAME_LEN+1]; // additional character for terminating null

EthernetServer server(8081);

// Servo Library and setup
#include <Servo.h>
Servo myservo;  // create servo object to control a servo
int servo = 6;    //Define what pin the servo is on


void setup()
{
  Serial.begin(9600); //Start serial port for debugging
  myservo.attach(servo);  // attaches the servo on pin 6 to the servo object
  Ethernet.begin(mac, ip);
  server.begin();
  delay(2000);
}

void loop()
{

  EthernetClient client = server.available();
  if (client) {
    int type = 0;
    while (client.connected()) {
        if (client.available()) {
        // GET, POST, or HEAD
        memset(buffer,0, sizeof(buffer)); // clear the buffer
        if(client.readBytesUntil('/', buffer,sizeof(buffer))){
          if(strcmp(buffer,"POST ") == 0){
            client.find("\n\r"); // skip to the body
            // find string starting with "pin", stop on first blank line
            // the POST parameters expected in the form pinDx=Y
            // where x is the pin number and Y is 0 for LOW and 1 for HIGH
            while(client.findUntil("pinD", "\n\r")){
              int pin = client.parseInt();       // the pin number
              int val = client.parseInt();       // 0 or 1
              pinMode(pin, OUTPUT);
              if(pin == 9){
                digitalWrite(pin, val);
              }
              Serial.println(val);
              if(pin == 6){
                myservo.write(val);
              }
            }

     
          }
          sendHeader(client,"Post example");
          //Control of Light
          //create HTML button to control pin 9
          client.println("<h2><font color=#f6a343>IoT - Servo and LED</h2>");
          client.print(
          "<form action='/' method='POST'><p><input type='hidden' name='pinD9'");
          client.println(" value='0'><input type='submit' value='Light Off'/></form>");
          //create HTML button to turn on pin 9
          client.print(
          "<form action='/' method='POST'><p><input type='hidden' name='pinD9'");
          client.print(" value='1'><input type='submit' value='Light On'/></form>");

          //Control of Servo
          //Turn Right
          client.print(
          "<form action='/' method='POST'><p><input type='hidden' name='pinD6'");
          client.println(" value='0'><input type='submit' value='Servo Right'/></form>");
          //Turn Left
          client.print(
          "<form action='/' method='POST'><p><input type='hidden' name='pinD6'");
          client.print(" value='180'><input type='submit' value='Servo Left'/></form>");
          //Stop
          client.print(
          "<form action='/' method='POST'><p><input type='hidden' name='pinD6'");
          client.print(" value='90'><input type='submit' value='Servo Stop'/></form>");
       
          //Create webcam feed
          //client.print("<img name=""FoscamCamera"" src=""http://67.168.78.50:1026/videostream.cgi?user=peon&pwd=noob"" width=""480"" height=""360"" alt=""Live Feed"" style=""background-color: #009999"" />");
       
       
          client.println("</body></html>");
       

       
          client.stop();
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    client.stop();
  }
}

void sendHeader(EthernetClient client, char *title)
{
  // send a standard http response header
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println();
  client.print("<html><head><title>");
  client.print(title);
  client.println("</title><body>");
}




<<<<<<  END OF ARDUINO CODE >>>>>>






Sunday, May 12, 2013

Good Ol' TR

Inspirational quote from a legacy.

"It is not the critic who counts; not the man who points out how the strong man stumbles, or where the doer of deeds could have done them better. The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood; who strives valiantly; who errs, who comes short again and again, because there is no effort without error and shortcoming; but who does actually strive to do the deeds; who knows great enthusiasms, the great devotions; who spends himself in a worthy cause; who at the best knows in the end the triumph of high achievement, and who at the worst, if he fails, at least fails while daring greatly, so that his place shall never be with those cold and timid souls who neither know victory nor defeat."

~Teddy Roosevelt