simple arduino webserver

by hdr on Thu Mar 20, 2008 10:53 am

here is code for a really simple arduino webserver, building a little on ladyada's test code.

no error checking; won't deal with multiple requesting clients; might even fail if you hit "refresh" in your browser too quickly...

but if you access the arduino IP address and port in your brower (i.e. type in something like 'http://192.168.0.15:10001') then you should get a web page that shows you a message, displays its analog-in values and changes background colour with the value of analog-in 0.

and if you are able to enable port forwarding from your router you can let your arduino serve data to the world....

hope it is useful....

usman

Code: Select all
#include <AFSoftSerial.h>
#include <string.h>

#define XPORT_CP2       8
#define XPORT_RXPIN     2
#define XPORT_TXPIN     3
#define HTTP_HEADER "HTTP/1.0 200 OK\nServer: arduino\nContent-Type: text/html\n\n"

#define TOTAL_ANALOG_IN 6

char linebuffer[256];
char c;

int analog[TOTAL_ANALOG_IN];
int requestNumber = 0;

AFSoftSerial mySerial =  AFSoftSerial(XPORT_TXPIN, XPORT_RXPIN);

void setup()  {
  Serial.begin(57600);
  pinMode(XPORT_CP2, OUTPUT);
  Serial.println("serial port ready");
  mySerial.begin(19200);
  Serial.println("ethernet response ready");
  digitalWrite(XPORT_CP2, HIGH);
}

void loop()               
{

  checkAnalogIns(); 

  if (requested()){
    respond();
  }
}


uint8_t serialavail_timeout(int timeout) {  // in ms
  while (timeout) {
    if (mySerial.available()) {
      return 1;
    }
    timeout -= 1;
    delay(1);
  }
  return 0;
}

uint8_t readline_timeout(int timeout) {
  uint8_t idx=0;
  char c;
  while (serialavail_timeout(timeout)) {
    c = mySerial.read();
    //Serial.print(c);
    linebuffer[idx++] = c;
    if ((c == '\n') || (idx == 255)) {
      linebuffer[idx] = 0;
      return idx;
    }
  }
  linebuffer[idx] = 0;
  return idx;
}


int requested(void) {
  uint8_t ret;
  char *found=0, *start=0, *end=0;
  while (1) {
    ret = readline_timeout(200);
    found = strstr(linebuffer, "GET /");
    if (((int)found) != 0) {
      return 1;
    }
    return 0;
  }
}

void XPort_flush(int timeout) {
  while (serialavail_timeout(timeout)) {
    mySerial.read();
  }
}

void checkAnalogIns(){
  for (int i = 0; i < 6; i++){
    analog[i] = analogRead(i);
  }
}

void respond(){
  XPort_flush(50);
  mySerial.print(HTTP_HEADER);
  mySerial.print("<html><body bgcolor=\"0000");
  mySerial.print(analog[0]/4, HEX);
  mySerial.print("\"><h1>hello this is your Arduino speaking...</h1>");
  mySerial.print("<h3>My analog-in values are:</h3><ul>");

  for (int i = 0; i < TOTAL_ANALOG_IN; i++){
    mySerial.print("<li><b>");
    mySerial.print(i);   
    mySerial.print(": </b> &nbsp; ");
    mySerial.print(analog[i]);
    mySerial.print("</li>");   
  }

  mySerial.print("</ul></body></html>");
  XPort_disconnect();

  Serial.print("Requested! No. ");
  Serial.println(requestNumber++);
 
}

void XPort_disconnect(){
  digitalWrite(XPORT_CP2, LOW);
  delay(20);
  digitalWrite(XPORT_CP2, HIGH);
}



your xport should be set up as follows:

Code: Select all
Baudrate (19200) ?
I/F Mode (4C) ?
Flow (00) ?
Port No (10001) ?
ConnectMode (C0) ?
Send '+++' in Modem Mode  (Y) ?
Show IP addr after 'RING'  (Y) ?
Auto increment source port  (N) ?
Remote IP Address : (000) .(000) .(000) .(000)
Remote Port  (0) ?
DisConnMode (80) ?
FlushMode   (00) ?
DisConnTime (00:00) ?:
SendChar 1  (00) ?
SendChar 2  (00) ?


i am using here the 'On Mdm_Ctrl_In Drop:' function to disconnect after serving a page -- i thought this should be connected to the Xport's CP2, but i actually had to wire up to the pin marked "CP3" on one side and "CTS" on the other.

(incidentally, if anyone gets confused by the XPort seemingly beginning all data-serving with the bytes "ff fb soh ff fb etx" -- this is because you might have "Telnet Com Port Cntrl" enabled -- it should be disabled).
hdr
 
Posts: 3
Joined: Wed Mar 19, 2008 3:29 pm

by adafruit on Thu Mar 20, 2008 2:37 pm

wow, great start to xport-apache! :)
User avatar
adafruit
 
Posts: 11506
Joined: Thu Apr 06, 2006 3:21 pm
Location: nyc

by Snaxter on Mon Mar 24, 2008 10:31 pm

First, apologies for any stupidity here - just new to Arduino.

hdr:

Thanks for posting your sample code, it does seem like a great step on the path to a full blown web server. I was able to get your code to render a web page, but then it hangs. The rendered page includes the "hello this is is your Arduino speaking ..." and the values of the 7 analog ports show up just fine. However, the browser is hung "waiting" and subsequent requests do not get a response unless the Arduino/Xport are reset.

I suspect that my problem is with your XPort_disconnect() function that is attempting to toggle the Xport CP2 pin. I wired my shield exactly described on ladyada's instructions here: http://ladyada.net/make/eshield/wire.html

If I understand your description, the CP2 pin is actually mapped to the line that labeled "CTS" on one side and "CP3" on the other. On my board (and presumably, ladyada's board) that is actually pin 6 on the Arduino. So, I tried modifying your code so that XPORT_CP2 is 6 (rather than 8 in your original code). That didn't help, and the page hung in exactly the same way.

Any suggestions?
Snaxter
 
Posts: 3
Joined: Mon Mar 24, 2008 9:57 pm

by hdr on Wed Mar 26, 2008 1:49 pm

yes, that's right, you're not disconnecting after serving the page.

frankly i don't know if cp2 is mapped to cts -- just that when it didn't work the first time i tried connecting to each of the other pins in turn (trial and error) until the one labeled 'cts' actually worked.

you need the disconnect function "On Mdm_Ctrl_In Drop" enabled -- and i don't remember offhand whether this was something i had to enable specially or whether it came like that out of the box. if you don't find it by telnetting in, try the web-browser configuration interface which makes configuration a lot quicker/simpler.
hdr
 
Posts: 3
Joined: Wed Mar 19, 2008 3:29 pm

by Snaxter on Sat Mar 29, 2008 1:32 pm

I finally got some time to debug this problem and I thought I'd add a little bit of documentation on this page in case someone has the same problem. There are several label and documentation issues with the ethernet shield, with the Lantronix documenation (which is not self consistent) and with the Lantronix web configuration utility.

As hdr pointed out, my problem was that the Xport was not dropping the connection after the page was served. This had the symptom that my web browser would "hang" (the specific page, not the entire browser) waiting for the Xport to drop the connection. The solution is to allow the Arduino to drop the connection via the modem control when the page has been updated. The tricky part is getting everything enabled through the myriad of documation issues.

First, I'm using a Lantronix Xport Direct+ module that is connected to an Ethernet Shield v1.0. I've seens some posts that suggest that the shield is being revised, so it will be important to check the board version. Also, I wired the shield exactly as described on Ladyada's web page, this will be important later.

Starting with the Lantronix documentation: The Direct+ has a really funky pin numbering system. Pin 1 is the upper left of the module (looking from the top, with the pins away) and pin 2 is on the upper right. On the Direct+, pins 1-23 are active signals and 2-24 are not connected (reserved in the documenation). Obviously pin 2 is an exception, but not relevant here.

The pins relevant for this particular problem are the "Configurable Pins" that are labeled CP1-CP3 on page 7 of the Lantronix Integration Guide (came on the little CD with the Direct+). Specifically, CP3=pin19, CP2=pin21, CP1=pin23. For the rest of this post, I assume that this documenation is correct (golden) and everything else is in error (there are going to be 3 other points that disgree with these labels). The Lantronix Integration Guide has a schematic on page 12 that mislables pin21 and relables pin19 (1st documentation issue). I decided to use CP1 (pin 23) for the the modem control. CP1 is the bottom left pin (looking from the top of the Direct+) and correspondingly gets connected to the bottom left side of the shield connector.

On the shield, CP1 is routed to a via that is labled "CP2" (2nd documenation issue). I believe that this is just a typo on Ladyada's board. I wound up wiring that via (labeled "CP2" but actually connected to CP1) to pin 9 of the Arduino digital I/O. This wiring required that hdr's code be tweaked slightly to map to the correct pin, but more on that later. Neither of the CP1/CP2 vias were wired in ladyada's original documentation.

Now the modem control needs to be enabled on the Direct+. On my particular module, this needed to be configured in two places. First, enable the modem control using the web configuration utility. This is on the "Channel 1 / Connection" page near the bottom of the page. In the section labeled "Disconnect Mode" there is a switch labeled "On Mdm_Ctrl_In Drop:". Make sure that the "Yes" button is clicked.

Then, go to the "Configurable Pins" page. The 3rd documenation issue pops up on this page where the CP pins are now numbered CP0-CP2. Assuming you're using CP1 (pin 23) as I have described so far, click on the "Function" field just to the right of "CP0" (really - this is CP1). Change the "General Purpose I/O" to "Modem Ctrl Channel 1 In" and then make sure that the "Active Level" section is set to "Low". Click the "OK" button and then make sure you click the "Apply Settings" link on the left side of the page.

Now make sure that you're using the right Arduino pin in hdr's code (the original post in this thread). In the version he posted, change the "#define XPORT_CP2 8" to map to the Arduino pin that was connected to CP1. In my case, I just made this consistent by changing this line to "#define XPORT_CP1 9" and doing a global replace on all of the CP2 instances in the code.

That fixed my problems.
Snaxter
 
Posts: 3
Joined: Mon Mar 24, 2008 9:57 pm

by adafruit on Sat Mar 29, 2008 4:44 pm

thanks for the note, i seem to have a bunch of small errors in this PCB but will update the online d0x and next rev
User avatar
adafruit
 
Posts: 11506
Joined: Thu Apr 06, 2006 3:21 pm
Location: nyc

by adafruit on Wed Apr 02, 2008 9:02 pm

i built on this example and mae a javascript LED color picker for a tricolor led (on my desk)
check it out
http://www.ladyada.net/rant/2008/04/cha ... a-the-web/
User avatar
adafruit
 
Posts: 11506
Joined: Thu Apr 06, 2006 3:21 pm
Location: nyc

by Snaxter on Wed Apr 02, 2008 10:59 pm

Ladyada:

Thanks for posting this example. I'm dying to get javascript working on the Xport. It looks like the line to your Sketch code is broken - I get your funny 404 error:

http://ladyada.net/make/eshield/LEDcolorpicker.pde

This looks like
z0mg!
What you want ain't available. Maybe try the search box in the upper right hand corner?
Snaxter
 
Posts: 3
Joined: Mon Mar 24, 2008 9:57 pm

by adafruit on Wed Apr 02, 2008 11:26 pm

ugh sorry, try again! dreamweaver sux sometimes
User avatar
adafruit
 
Posts: 11506
Joined: Thu Apr 06, 2006 3:21 pm
Location: nyc

by hdr on Thu Apr 03, 2008 2:35 am

nice one. (couldn't actually get through to the IP address but i'm guessing it was just offline).

disconnect after 3secs is a good solution -- much simpler!
hdr
 
Posts: 3
Joined: Wed Mar 19, 2008 3:29 pm

by adafruit on Thu Apr 03, 2008 11:37 am

turns out the real problem was that verizon was blocking port 80. i had no problem connecting from my machine (of course) but now ive changed it to port 8888
so you can try again, i know it works cause the led keeps changing every few seconds
User avatar
adafruit
 
Posts: 11506
Joined: Thu Apr 06, 2006 3:21 pm
Location: nyc

by Superworms on Thu Apr 03, 2008 10:46 pm

have you thought about sticking a webcam in front of it so the world can see it?
Superworms
 
Posts: 68
Joined: Thu May 10, 2007 3:58 pm

by adafruit on Thu Apr 03, 2008 10:51 pm

i dont have a good enough connection for a webcam, its very slooow and if lots of people tried to stream video i wouldnt be able to get any work done!
User avatar
adafruit
 
Posts: 11506
Joined: Thu Apr 06, 2006 3:21 pm
Location: nyc

Simple webserver example clarification

by OldScot on Fri Apr 04, 2008 11:14 am

Am I right in thinking the "LED Colour picker" example is using an XPort Direct (no web server) and is using the Arduino to handle/serve the web requests?

Thanks
OldScot
 
Posts: 1
Joined: Fri Apr 04, 2008 10:53 am

by adafruit on Fri Apr 04, 2008 11:30 am

yes
User avatar
adafruit
 
Posts: 11506
Joined: Thu Apr 06, 2006 3:21 pm
Location: nyc