Archive for May, 2008

Arduino, Xport, PHP and the Internet

This article explains how to use the Arduino and an Xport Ethernet module to send and retrieve data to an external web server. I discuss the advantages of this method over various other methods of communications between Arduino and the internet. After discussing hardware setup, some simple test code for Arduino and the PHP code that you need to run on the web server is provided. Some real world extensions of this project are a web page that lets you control the lights in your house, or sending sensor data to a web page and graphing it so you have a pretty record of sensor readings.

The first stage in this project was researching how I wanted to connect Arduino to the internet. There are a lot of different options. The easiest required an external computer, but I avoided this because I wanted a highly reliable and very low power solution which a PC could not provide. I wanted a fairly simple solution that would use a minimal amount of flash memory on my Arduino. There is only 16K of flash memory on Arduino to hold your code. Since talking to a web server will always just part of a larger project I wanted to use the least memory possible so the rest of the project had enough space. After this research phase, I decided one the Xport modules from Lantronix would fit my needs best. The three Lantronix Ethernet modules I considered were the Xport, Xport Direct+ and Xport Direct. Xport has a different pin out than the Direct modules, but other than that they are very similar. As far as functionality the main difference is that Xport and Xport Direct+ have a web server, but Xport Direct does not. I went with the Xport because it was slightly smaller and had a web server. Knowing what I know now I would just get Xport Direct because it’s $30 instead of $50 like Xport Direct+ and Xport and I don’t need the web server.

Why don’t I care about a web server? At first I thought having a web server built into Xport was important, but for my use case it is not. The reason is because I would rather upload my data to a real web server. This way I don’t have to worry about a bunch of people connecting to my Arduino and effectively launching a denial of service attack on my Arduino. I would rather push data up to a real web server and then let it dish out the data to the rest of the world. This model also means I don’t need to worry about my firewall or getting my router to forward ports to my Arduino since all requests are initiated with Arduino. Another benefit of not using Xport’s web server is that it is quite limiting, but if I use an external web server then I can have much more flexibility like running PHP, SQL, Java, and any other common features that the Xport web server does not support.

I have a cheap hosted web server through Dreamhost. I mention dreamhost because I use them, but any web server that supports PHP and has a dedicated IP address should work fine for this project. One issue that took a long time to figure out is that cheap hosted account usually don’t have dedicated IP addresses for each domain name. I had to pay dreamhost an extra $4 a month for this option. One way to see if the domain you want to use has a dedicated IP address is to ping the server and then type that IP address into your web browser. If you have a dedicated IP address then you will go to your domain. If you don’t your browser will return an error. Another limitation of using a hosting service like dreamhost is that they have firewalls that get triggered if you try to connect too frequently. You can see in my code below how I added a delay to work around the firewall issues I found. I had to contact dreamhost a few times to get everything working. I must say their tech support was great and I was very pleased with the service they provided.

At this point I needed a way to connect the Xport to Arduino. I could have done this with a breadboard, but I found this cheap ($15) shield for the Xport module at Adafruit and it works great. That page also links to a great tutorial about putting the shield together and some code examples on how to setup a web server on Xport if you choose to go that route instead of what I’m describing here.

Now I could power up the Xport module and plug and Ethernet cable into it. Then I could configure it with telnet. You can get full documentation on your xport module and how to configure it here. Here is a list of the things I changed on my xport module.

  • Set the Channel 1 ConnectMode to “D4” which changed the serial responce to single character mode (my code expects this mode)
  • Changed the Channel 1 port to 81 to work around my webhosting firewall
  • (Optional) Set the Xport to use a static IP address since I prefer that over the default dynamic IP address

The last part of the hardware setup was to hook up 3 wires between the Arduino and the Xport. Before doing this I decided to use the AFSoftSerial library. To install this library you just copy the AFSoftSerial directory into your Arduino-0011/hardware/libraries folder where all the libraries live. You could use the hardware serial port by using pins 0 and 1, but I wanted to allow those to talk to my PC so I used this soft serial port library. You can reconfigure all this in the code if you want, but I choose to use pin 2 as TX, pin 3 as RX and pin 4 as Xport Reset. Remember you need to connect Arduino’s TX pin to Xport’s RX pin, and Arduino’s RX pin to Xport’s TX pin. I made this stupid mistake. Just remember you need the transmit pins talking to the recieving pins or things just won’t work.

I have one note about the php code below. You can test test the php code with your web browser to make sure the php code is setup correctly. All you need to do is type this into your browsers address bar: http://www.yourdomain.com/arduino/xPortTest.php?value0=111&value1=222. Of course you’ll need to make sure the the location of the php file matches where it is located on your web server. This will append the values 111 and 222 to xportTest.txt and create the file if needed. If it doesn’t work the most likely issues are that your web server doesn’t support php or you don’t have the permissions setup to allow the php script to create/modify the text file.

That’s pretty much it. The code I used on Arduino and the PHP code I put on my web server is listed below. If anyone has any questions don’t hesitate to ask them here or on the Arduino Forums.

Arduino Code:

// Maurice Ribble
// 4-3-2008
// http://www.glacialwanderer.com/hobbyrobotics

// The flow of data is Arduino -> Xport -> PHP -> text file
// Once the connection is established by Arduino to the PHP page
// the PHP page can also send data back to Arduino

// This code demonstrates a simple yet flexible way to let Arduino
// talk to a webserver.  While there are versions of xport that
// have a webserver built in they are more expensive and require you
// to setup your internet connection to allow you to run a server.
// With this method you can just use a cheap hosted website.
// I use dreamhost and am very satisfied with their service, but there are
// many other options (any host that support PHP should work fine).
// With Dreamhost I needed to sign up for a dedicated IP address and I
// had port 80 with connections no more frequent than once per minute or
// I had problems with their firewall blocking my connection attempts.
// If you want to send data back and forth frequently just connect once
// and just keep using that connection.  This will avoid issues with
// web hosting firewalls.

// Xport Settings (everything default except)
//  Channel 1 -- CoonnectMode : D4 -- This changes serial responce to single char mode
//  Channel 1 -- Port 80
//   I also changed my IP address to a static IP, but you could leave this alone

#define XPORT_SERIAL_RX_PIN 3
#define XPORT_SERIAL_TX_PIN 2
#define XPORT_RESET_PIN 4

// These are web server specific values
#define PHP_PAGE_LOCATION "/arduino/xPortTest.php"
#define WEB_HOST "HOST: yourdomain.com\n\n"
#define IP_AND_PORT "C111.111.111.111/80\n"

#include 

AFSoftSerial xPortSerial = AFSoftSerial(XPORT_SERIAL_RX_PIN, XPORT_SERIAL_TX_PIN);

void setup()
{
  // start serial port at 9600 bps:
  Serial.begin(9600);
  xPortSerial.begin(9600);
}

void loop()
{
  xportReset();
  xportConnect();
  httpRequest();

  // Delay for 1 minute to aviod triggering my host's firewall
  delay(60000);
}

void xportReset()
{
  pinMode(XPORT_RESET_PIN, OUTPUT);
  digitalWrite(XPORT_RESET_PIN, LOW);
  delay(100);
  digitalWrite(XPORT_RESET_PIN, HIGH);
  delay(3000);
}

void xportConnect()
{
  byte theByte = 0;

  while (theByte != 'C')
  {
    xPortSerial.print(IP_AND_PORT);
    while(!xPortSerial.available()) {} // Just loop until available
    theByte = xPortSerial.read();
    Serial.print(theByte);
    Serial.print(" ");
  }
}

void httpRequest()
{
  byte theByte;

  xPortSerial.print("GET ");
  xPortSerial.print(PHP_PAGE_LOCATION);

  // value0 = 123 and value1 = 456
  // You should change these to be your sensor values or whatever you want to send
  // (see php code if you want to add more values or change the names value0/value1
  xPortSerial.print("?value0=123&value1=456");
  xPortSerial.print(" HTTP/1.1\n");
  xPortSerial.print(WEB_HOST);

  while(!xPortSerial.available()) {} // Just loop until available
  theByte = xPortSerial.read();
  if (theByte != 0)
    Serial.println("Passed.");
  else
    Serial.println("Failed.");
}

PHP Code:

You need to pass in valid _GET parameters. Script Terminated."; exit; } $fp = fopen("./xportTest.txt", 'at'); if (!$fp) { echo '

Failed to open file'; exit; } $outputstring = "$value0 $value1\r\n"; fwrite($fp, $outputstring, strlen($outputstring)); // end with a 0 to close the session to the client: echo "\0"; end; ?>

Comments (25)

Processing

I just found this open source project at processing.org that looks supper useful. A lot of people use it to design cross platform GUIs for interfacing the Arduino with the PC since it has easy to use serial communications. Another part that looks useful to me is that it has imaging/camera libraries that should make some of my ideas that require motion tracking and other video related ideas much easier to implement.

I will likely use this in future projects, but for now I just wanted to write it down so I don’t forget about it.

Comments off