Here's the idea. I know how to code HTML. I have an Uno with the Ethernet Shield. I have a micro SD card. I want to put the html code on the sd card. The arduino will act as the web server to host the website. When I use a browser on the local network to access the web server (by typing in the http://192.168.0.100 for example) the website I created will appear. It will have little buttons I can click which can turn pins on and off. How do you get the html code to work with the arduino code to turn the pins on and off?
njdurkin:
How do you get the html code to work with the arduino code to turn the pins on and off?
You will need to learn how to run a web server, read files from an SD card, and turn pins on and off. You will find plenty of examples showing how to do those things separately, even if you can't find an existing solution that matches exactly what you're trying to achieve.
//zoomkat 4-1-12
//simple button GET for servo and pin 5
//for use with IDE 1.0
//open serial monitor to see what the arduino receives
//use the \ slash to escape the " in the html, or use ' instead of "
//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>
#include <Servo.h>
Servo myservo; // create servo object to control a servo
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 1, 102 }; // 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(5, OUTPUT); //pin selected to control
//start Ethernet
Ethernet.begin(mac, ip, gateway, gateway, subnet);
server.begin();
myservo.write(90); //set initial servo position if desired
myservo.attach(7); //the pin for the servo control
//enable serial data print
Serial.begin(9600);
Serial.println("server servo/pin 5 test 1.0"); // 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
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='/?on'>ON</a>");
client.println("<a href='/?off'>OFF</a>");
client.println("</BODY>");
client.println("</HTML>");
delay(1);
//stopping client
client.stop();
///////////////////// control arduino pin
if(readString.indexOf("on") >0)//checks for on
{
myservo.write(40);
digitalWrite(5, HIGH); // set pin 4 high
Serial.println("Led On");
}
if(readString.indexOf("off") >0)//checks for off
{
myservo.write(140);
digitalWrite(5, LOW); // set pin 4 low
Serial.println("Led Off");
}
//clearing string for next read
readString="";
}
}
}
}
}
Okay I made some really good progress. What I'm stuck on now is trying to use images with arduino. I have an html file on the sd card which can be accessed from a browser on the network. All the image files are on the sd card but they do not display on the html file when called. When I open the html file from the sd card on the computer the page loads fine with all the images. I'm guessing arduino doesn't have the algorithms to display or communicate those images with a browser by default. Is there some library or some way to get those images to show?
Thanks.
/*
* USERS OF ARDUINO 0023 AND EARLIER: use the 'SDWebBrowse.pde' sketch...
* 'SDWebBrowse.ino' can be ignored.
* USERS OF ARDUINO 1.0 AND LATER: **DELETE** the 'SDWebBrowse.pde' sketch
* and use ONLY the 'SDWebBrowse.ino' file. By default, BOTH files will
* load when using the Sketchbook menu, and the .pde version will cause
* compiler errors in 1.0. Delete the .pde, then load the sketch.
*
* I can't explain WHY this is necessary, but something among the various
* libraries here appears to be wreaking inexplicable havoc with the
* 'ARDUINO' definition, making the usual version test unusable (BOTH
* cases evaluate as true). FML.
*/
/*
* This sketch uses the microSD card slot on the Arduino Ethernet shield
* to serve up files over a very minimal browsing interface
*
* Some code is from Bill Greiman's SdFatLib examples, some is from the
* Arduino Ethernet WebServer example and the rest is from Limor Fried
* (Adafruit) so its probably under GPL
*
* Tutorial is at http://www.ladyada.net/learn/arduino/ethfiles.html
* Pull requests should go to http://github.com/adafruit/SDWebBrowse
*/
#include <SdFat.h>
#include <SdFatUtil.h>
#include <Ethernet.h>
#include <SPI.h>
/************ ETHERNET STUFF ************/
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 0, 80 };
EthernetServer server(80);
/************ SDCARD STUFF ************/
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;
// store error strings in flash to save RAM
#define error(s) error_P(PSTR(s))
void error_P(const char* str) {
PgmPrint("error: ");
SerialPrintln_P(str);
if (card.errorCode()) {
PgmPrint("SD error: ");
Serial.print(card.errorCode(), HEX);
Serial.print(',');
Serial.println(card.errorData(), HEX);
}
while(1);
}
void setup() {
Serial.begin(9600);
PgmPrint("Free RAM: ");
Serial.println(FreeRam());
// initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
// breadboards. use SPI_FULL_SPEED for better performance.
pinMode(10, OUTPUT); // set the SS pin as an output (necessary!)
digitalWrite(10, HIGH); // but turn off the W5100 chip!
if (!card.init(SPI_HALF_SPEED, 4)) error("card.init failed!");
// initialize a FAT volume
if (!volume.init(&card)) error("vol.init failed!");
PgmPrint("Volume is FAT");
Serial.println(volume.fatType(),DEC);
Serial.println();
if (!root.openRoot(&volume)) error("openRoot failed");
// list file in root with date and size
PgmPrintln("Files found in root:");
root.ls(LS_DATE | LS_SIZE);
Serial.println();
// Recursive list of all directories
PgmPrintln("Files found in all dirs:");
root.ls(LS_R);
Serial.println();
PgmPrintln("Done");
// Debugging complete, we start the server!
Ethernet.begin(mac, ip);
server.begin();
}
void ListFiles(EthernetClient client, uint8_t flags) {
// This code is just copied from SdFile.cpp in the SDFat library
// and tweaked to print to the client output in html!
dir_t p;
root.rewind();
client.println("<ul>");
while (root.readDir(&p) > 0) {
// done if past last used entry
if (p.name[0] == DIR_NAME_FREE) break;
// skip deleted entry and entries for . and ..
if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.') continue;
// only list subdirectories and files
if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;
// print any indent spaces
client.print("<li><a href=\"");
for (uint8_t i = 0; i < 11; i++) {
if (p.name[i] == ' ') continue;
if (i == 8) {
client.print('.');
}
client.print((char)p.name[i]);
}
client.print("\">");
// print file name with possible blank fill
for (uint8_t i = 0; i < 11; i++) {
if (p.name[i] == ' ') continue;
if (i == 8) {
client.print('.');
}
client.print((char)p.name[i]);
}
client.print("</a>");
if (DIR_IS_SUBDIR(&p)) {
client.print('/');
}
// print modify date/time if requested
if (flags & LS_DATE) {
root.printFatDate(p.lastWriteDate);
client.print(' ');
root.printFatTime(p.lastWriteTime);
}
// print size if requested
if (!DIR_IS_SUBDIR(&p) && (flags & LS_SIZE)) {
client.print(' ');
client.print(p.fileSize);
}
client.println("</li>");
}
client.println("</ul>");
}
// How big our line buffer should be. 100 is plenty!
#define BUFSIZ 100
void loop()
{
char clientline[BUFSIZ];
int index = 0;
EthernetClient client = server.available();
if (client) {
// an http request ends with a blank line
boolean current_line_is_blank = true;
// reset the input buffer
index = 0;
while (client.connected()) {
if (client.available()) {
char c = client.read();
// If it isn't a new line, add the character to the buffer
if (c != '\n' && c != '\r') {
clientline[index] = c;
index++;
// are we too big for the buffer? start tossing out data
if (index >= BUFSIZ)
index = BUFSIZ -1;
// continue to read more data!
continue;
}
// got a \n or \r new line, which means the string is done
clientline[index] = 0;
// Print it out for debugging
Serial.println(clientline);
// Look for substring such as a request to get the root file
if (strstr(clientline, "GET / ") != 0) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
// print all the files, use a helper to keep it clean
client.println("<h2>Files:</h2>");
ListFiles(client, LS_SIZE);
} else if (strstr(clientline, "GET /") != 0) {
// this time no space after the /, so a sub-file!
char *filename;
filename = clientline + 5; // look after the "GET /" (5 chars)
// a little trick, look for the " HTTP/1.1" string and
// turn the first character of the substring into a 0 to clear it out.
(strstr(clientline, " HTTP"))[0] = 0;
// print the file we want
Serial.println(filename);
if (! file.open(&root, filename, O_READ)) {
client.println("HTTP/1.1 404 Not Found");
client.println("Content-Type: text/html");
client.println();
client.println("<h2>File Not Found!</h2>");
break;
}
Serial.println("Opened!");
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/plain");
client.println();
int16_t c;
while ((c = file.read()) > 0) {
// uncomment the serial to debug (slow!)
//Serial.print((char)c);
client.print((char)c);
}
file.close();
} else {
// everything else is a 404
client.println("HTTP/1.1 404 Not Found");
client.println("Content-Type: text/html");
client.println();
client.println("<h2>File Not Found!</h2>");
}
break;
}
}
// give the web browser time to receive the data
delay(1);
client.stop();
}
}
Are these static images? If so, why force the the Arduino to work even harder when you can just have the images hosted on one of the many free image hosting sites and have the Arduino Web Server just send the URL and let the client web browser do all the heavy lifting?
The problem is that this local network is not connected to the internet in anyway (not even the client browser because it is connected to the arduino network only). So while I would love to do that, there is no way. Sorry that I did not specify before.
The only other solution I can think of is to have the image files on the client device and have the webserver point the client to look in its own directory for the images. Is that even possible?
durkinnj:
Okay I made some really good progress. What I'm stuck on now is trying to use images with arduino. I have an html file on the sd card which can be accessed from a browser on the network. All the image files are on the sd card but they do not display on the html file when called. When I open the html file from the sd card on the computer the page loads fine with all the images. I'm guessing arduino doesn't have the algorithms to display or communicate those images with a browser by default. Is there some library or some way to get those images to show?
If the web server is serving out binary resources then the web client and server need to agree what encoding scheme to use, and the server then needs to implement that encoding scheme. (The 'agreeing' part could consist of you simply choosing an encoding scheme that you know your browser supports.)
You also have a PC. A PC can run almost any program you want!
You can run a full on server on you PC. The code is free. Look at Apache the webs most widely used server. You could also look at "wildcat" a Java server and many others.
Thanks for the input but unfortunately my project cannot include my computer. The arduino must host the webserver.
Okay so I think my problem will be solved if I can just get the browser to open an an html file as an html file instead of a text document because right now when I open a .htm file it opens it as a text file in the browser.
All I'm doing is hosting a very simple pin control web server not websites.
I tried a lot of different browsers. It seems like there are two types. One type: firefox, opera, that can open files from your browser by using file://localhost/sdcard/file.ext or some similar command but will not open the html file as a webpage but instead as a text document with all the html code. Another type: dolphin that will open the html file as a webpage but cannot navigate and open files on the local disk. I need the browser to do both so that I can 1; view the html file as a webpage and 2; use images on the local disk as part of that webpage.
Otherwise I'm going to need arduino to host and display the images somehow.
UPDATE: I found out that dolphin has a command to view files that is very different but it can be done and it does open the html file as a webpage but it won't use the files on the sdcard of the mobile device.
How do I get a browser on my phone like firefox to view the .htm file as a webpage and not a text document?
How the web browser interprets the page is determined by the page encoding indicated in the HTTP response. If your HTML page is being rendered as plain text then you are sending the wrong content-type.
Why are the files on the sdcard seen with different names? When I have a name like indexabc.html arduino loads it as indexh~1.htm and that's how I access it. Why is this happening?
Your SD card is probably formatted with a FAT file system, which cannot handle .html as a normal extension, since normal extensions back when FAT was invented were limited to 3 characters. Files with more than 8 characters in the filename or three characters in the extension get this special treatment.
I'm guessing the tilde thing isn't happening to files that fit the 8.3 limit.
You could name your file .htm and see if it helps.
Here is my problem. If I open this file on the sdcard of my phone it opens the webpage fine and displays the images perfectly fine. If I have the same exact file on the sdcard of my ethernet shield on the arduino it does not load the images. Why is this happening? Sorry to throw these html problems at you guys.
Here is what the serial monitor is displaying:
Free RAM: 831
Volume is FAT16
Files found in root:
INDEX.HTM 2012-12-19 18:06:36 1363
Files found in all dirs:
INDEX.HTM
Done
GET /INDEX.HTM HTTP/1.1
INDEX.HTM
Opened!
GET /favicon.ico HTTP/1.1
favicon.ico
The problem is the file:// url. There is a great difference between http:// and file:// urls. The main issue here is that a file:// url is only valid on the device where the resource named by the url lives.
To fetch a resource like an image across the network, it needs to be on an http:// server and the referring HTML code needs to use the appropriate http:// url to fetch it.
Well I don't know if you've read any previous posts but the problem is that this local network is not connected to the internet in anyway (not even the client browser because it is connected to the arduino network only). So while I would love to have the images hosted elsewhere, I can't.
The only other solution I can think of is to have the image files on the client device and have the webserver point the client to look in its own directory for the files. I'm kind of stuck here
The only other way to go with this is to actually connect the arduino to the internet. I honestly do not know how to do this as a mobile application. I'll have to use a broadband device either usb or mobile hotspot and somehow connect the arduino to it but how?