With an Ethernet shield you can transform your Arduino into a tiny little web server. Not only that but a web server with Inputs and Outputs. So you can use it to measure things on an analog input and then access those readings from anywhere on the Internet. Or, if you like, you can use it as a remote control to turn things on and off.
The Nuelectronics library is very thorough, but not the easiest library in the world to use, so I decided to write a library that wrapped up this library with a simpler interface.
You can download the library from here but you will also need to download the Nuelectronics library from here.
Install both libraries into your Arduino environment by unzipping them into a folder called 'libraries' in your sketches directory.
You can now create a simple sketch like this hello world web server example:
#include "etherShield.h"
#include "ETHER_28J60.h"
static uint8_t mac[6] = {0x54, 0x55, 0x58, 0x10, 0x00, 0x24};
static uint8_t ip[4] = {192, 168, 1, 15};
static uint16_t port = 80;
ETHER_28J60 ethernet;
void setup()
{
ethernet.setup(mac, ip, port);
}
void loop()
{
if (ethernet.serviceRequest())
{
ethernet.print("<H1>Hello World</H1>");
ethernet.respond();
}
}
This example just displays Hello World when you connect to it in a browser.
I have included some other examples that display the values at the analog ports, set a digital output and also echo the request parameters.
This is all heavily influenced by a posting I saw and now cannot find by some who had done a very similar thing to this. If you are reading this, please let me know so that I can give you the credit you deserve. I just kind of did things a slightly different way, and put it in a library rather than a set of functions.
The API is documented below:
Setup.
void setup(uint8_t macAddress[], uint8_t ipAddress[], uint16_t port);
Example:
You will need to find an ipAddress that is both in a valid range and unused on your local network.
The mac address just has to be unique on your network, so unless you have two of these boards on the network, the value above will be fine.
Servicing Web Requests
char* serviceRequest();
This also shows how to write the response and make the final response to the browser's request.
Writing the Response
void print(char* text)
- adds a string of HTML to the response to be returned.
void print(int value);
- adds an integer displayed in decimal form to the response.
void respond();
- commits the response back to the requesting browser.
Some things to watch.
The board consumes about 250mA which seems a lot to me. When driven from a power adaptor rather than USB, that makes the Arduino board get pretty hot around the voltage regulator. So just be careful, particularly if you plan to put your project in a box.
If you start to get strange things happening with the code, and you are using a 168 Arduino, you may well be running out of memory. The examples in the library will work with a 168, but to do anything more substantial use a 328.
About the Author
These are my books. Click on the image below to find out more about them.
This is all heavily influenced by a posting I saw and now cannot find by some who had done a very similar thing to this. If you are reading this, please let me know so that I can give you the credit you deserve. I just kind of did things a slightly different way, and put it in a library rather than a set of functions.
The API is documented below:
Setup.
void setup(uint8_t macAddress[], uint8_t ipAddress[], uint16_t port);
Example:
static uint8_t mac[6] = {0x54, 0x55, 0x58, 0x10, 0x00, 0x24};
static uint8_t ip[4] = {192, 168, 1, 15};
static uint16_t port = 80;
ETHER_28J60 ethernet;
void setup()
{
ethernet.setup(mac, ip, port);
}
The mac address just has to be unique on your network, so unless you have two of these boards on the network, the value above will be fine.
Servicing Web Requests
char* serviceRequest();
Example:
void loop()
{
char* params;
if (params = e.serviceRequest())
{
e.print("<H1>Web Remote</H1>");
if (strcmp(params, "?cmd=on") == 0)
{
digitalWrite(outputPin, HIGH);
e.print("<A HREF='?cmd=off'>Turn off</A>");
}
else
{
digitalWrite(outputPin, LOW);
e.print("<A HREF='?cmd=on'>Turn on</A>");
}
e.respond();
}
}
{
char* params;
if (params = e.serviceRequest())
{
e.print("<H1>Web Remote</H1>");
if (strcmp(params, "?cmd=on") == 0)
{
digitalWrite(outputPin, HIGH);
e.print("<A HREF='?cmd=off'>Turn off</A>");
}
else
{
digitalWrite(outputPin, LOW);
e.print("<A HREF='?cmd=on'>Turn on</A>");
}
e.respond();
}
}
serviceRequest either returns null if there has not been an incoming web request to service, or it returns a string containing the request parameter string for the incoming request. The request string includes the '?' character.
This also shows how to write the response and make the final response to the browser's request.
Writing the Response
void print(char* text)
- adds a string of HTML to the response to be returned.
void print(int value);
- adds an integer displayed in decimal form to the response.
void respond();
- commits the response back to the requesting browser.
Some things to watch.
The board consumes about 250mA which seems a lot to me. When driven from a power adaptor rather than USB, that makes the Arduino board get pretty hot around the voltage regulator. So just be careful, particularly if you plan to put your project in a box.
If you start to get strange things happening with the code, and you are using a 168 Arduino, you may well be running out of memory. The examples in the library will work with a 168, but to do anything more substantial use a 328.
About the Author
These are my books. Click on the image below to find out more about them.
52 comments:
AMAZING, so much easier to understand than the nuelectronics one, i've set it up with your code fine, but i've got a php file on my webserver than takes a GET value in a variable "Value" and put thats variables value into a mysql db.
What i cant work out is how, using your code, i can send the url with "GET http://localhost/index.php?value=(analog value)"
If you could put a bit of sample code that would be great!
Thanks
Thanks Ben, glad you liked it.
Unfortunately the code that I wrote only lets the Arduino and Ethershield act as a web server. So it can serve HTML but not itself send web requests. That was going to be phase 2, but I wouldn't hold your breath, it will be a while before I get to it.
However, all is not lost. What you could do is use a javascript timer on your PHP to poll the Arduino periodically to get the reading and then put that reading into the database.
Hope this helps.
Simon.
There's another library here if you're interested - http://news.jeelabs.org/2010/05/31/jeenode-as-web-server/
Hello Simon, Thanks for putting this together, it is much easier to understand! did you have a go at making a client library? you inspired me to have a go at making one and I think its worked out quite well. I have documented it here: http://openenergymonitor.org/emon/node/80
It would be cool to see if we could combine both libraries in to one. I will try to have a go when I next get a moment and let you know.
Thanks, Trystan
Trystan, I really haven't had the time. Your library looks great, so please feel free to combine the two. I'd just appreciate a credit in the header file :-)
PS Your open energy stuff looks really interesting.
Cool will do!
Simon, you should help me out and serve up the Nuelectronics library as well as the website is dead.
Hi, Nueclectronics site is back up.
I can't make it work,
I've plug my Arduino Duemilanove with an eBay Ethernet board with the ENC28J60 on it (made by ekitszone or something).
Well when I plug the Arduino on it recognize it and I can program it well.
Then, I unplug the USB and plug the ethernet board and then plug back the USB.
At this point the USB does not recognize the arduino and when trying to access the IP that I've set (10.0.0.15) I get a request time out.
Any clues ?
Is it normal that the arduino is not being recognized by the USB when the ethernet is pluged on it ?
Thanks a lot
Yaniv
Yaniv,
With that hardware, you cannot use USB at the same time as Ethernet, as they both use pins 0 and 1 for serial communication.
Hello Simon,
your library is the most useful enhancement to my little development environment since Emacs. :)
I'm pretty new to the Arduino (and electronics at all) but I'm a very big fried of understandability and simplicity (especially in technics related stuff).
For my personal use, I made a little code-cleanup (nothing to speak of) and merged the etherShield library with your one into a single folder.
In this sense: great work!
Michael
PS: As you might already noted: english isn't my native language. :)
And I forgot: is it critical to increase the BUFFER_SIZE? 500 was too little for my needs, so I set it to 1000.
Michael
Thanks Anonymous, glad it has been useful.
Are you going to post your enhancements somewhere?
My Changes aren't enhancements. I just changes the Indent style, renamed your class and library to Ethernet28J60 etc. As I already said it is nothing to speak of. The functionality is still the same. :)
Hi Simon!
I use Your library and examples to create Web-server with analog temperature sensor and controlled LED.
I use MK-duino http://mk-duino.narod.ru/ and MMX-ENC28J60 http://int.com.ua/index.php?option=com_content&task=view&id=31&Itemid=46
Server sends Temperature value and recives command to switch LED On/Off.
Arduino sends HTML page with instructioncon to auto-refresh it's content:
"<meta http-equiv=refresh content=1>"
But some time Arduino hung-up.
I guess this is result of Stack overflow.
Do You have any solution to this problem?
Vladimir
Yes you are probably out of memory.
Are you using a 328 chip? That gives you a massive 2K to use. Instead of the 1K in a 168.
use ATmega8 with 1K RAM.
In past I had program AVR Butterfly with ATmega169. It has special methods for string constants located in Flash instead of RAM.
May be You will improve Your Library to use Flash ?
My e-m: kvi(at)mksat(point)net
Vladimir
Hi, Simon.
Is it possible to reduce buffer size here?
...\libraries\ETHER_28J60\ETHER_28J60.cpp
...
#define BUFFER_SIZE 500
...
I need web-server examle will works with 1K RAM without hung-up.
Vladimir
You probably could - give it a go, you have the source code.
Hi, Simon.
I have tested examle "ethershield_webserver.pde"with ATmega8 with refresh option in HTML body
"< meta http-equiv=refresh content=1>".
It's work without hung-up.
But Your's example "ServeReadings.pde" with refresh option goes to hung-up after 2 minutes.
I am sorry that Your library "ETHER_28J60" has bugs.
I like Your library. I hope You will fixe bugs.
Vladimir
Hi, Simon.
What is start value for "plen" in first call "print()" in "ETHER_28J60.cpp"?
Vladimir
Hi Vladimir,
Sadly I just don't have time to look into this at the moment. Please feel free to adapt / mend the library in any way you want.
Simon.
Gr8 job. I hope you will come back to this project in the future. I will try to implement the library for Arduino Mega. I let you know..
great job! thank you very much that you gave that nice piece of cod to the community.
greetings from Germany
Hello Simon, good job!
I did not see all your code, but it appears that you wrote a whole HTTP-server library (not only TCP/IP stack).
Well, I started a project with the goal of turn the Ethernet examples found on Arduino's IDE compatbile with ENC28J60, so I'm rewriting all the socket layer, based on nuelectronics etherShield Library.
For now, TCP server connections work (with some limitations) and the web server example is working fine.
If do you want to know more, please see:
- Topic on Arduino Forum: http://arduino.cc/forum/index.php/topic,56057.0.html
- Project on GitHub: http://github.com/turicas/Ethernet_ENC28J60
Hi, first of all thank you for creating this wonderful library.
You seem to be the only one on the planet to be able to make sense of the Nuelectronics library!
Is it possible to send json strings using your library?If yes then how.
Also if say for example I type in this into my browser "http://192.168.1.15/{"name":"John","age":25}"
how can I retrieve the exact string which follows the / which in this case would be : {"name":"John","age":25}
Thank a lot in advance.
Thanks very much.
You probably could use JSON. But then you would have to parse them on the Arduino.
I would just stick to a simple request parameter as in the examples with the library.
Hi Simon,
do you think it is possible to send multiple packets before closing the connection?
What i intend to do is to have an sdcard board attached to the arduino and enc28j60, read individual characters from a file on the sd card, fill the buffer with these and send the contents of the buffer as a packet over the ethernet. Then continue reading the file, begin filling the buffer again and send the packet again when the buffer is full.
Thanks.
It should be ok yes. Give it a try :)
Hi Simon,
I tried sending the contents of a file from the sd card over ethernet using the enc28j60 and an arduuino uno but the problem is that the size of file that can be sent is limited by the buffer size defined and in the present library there is no way to send more than one packet.
How do you suggest i send multiple packets before closing the connection? Can you help me with this?
Thanks!
Dear, It´s a great Lib. But when I use a html temperatura with two decimals. It´s don´t works.
e.print(tempC);
The result is 28 not 28.34 !
How I public with decimals numbers.
Best for you.
JORGE ORENGO
when I try compiling, say this error:
C:\DOCUME~1\AREATE~1\CONFIG~1\Temp\build2823184158983767047.tmp/HelloWorld.cpp:24: undefined reference to `ETHER_28J60::setup(unsigned char*, unsigned char*, unsigned int)'
Whats happend?? thanks.
Sinu
Hi, it probably means your library is not installed in the right place. Or, you have not restarted Arduino after adding the library.
How to set gateway (Want make public webserver for led controlling).
Hi Simon,
Thank you for the library you shared. I am getting following copliler errors and I don't know how to fix it.
C:\Program Files\arduino-0022\libraries\ETHER_28J60\ETHER_28J60.cpp: In member function 'char* ETHER_28J60::serviceRequest()':
C:\Program Files\arduino-0022\libraries\ETHER_28J60\ETHER_28J60.cpp:102: error: 'class EtherShield' has no member named 'ES_init_len_info'
C:\Program Files\arduino-0022\libraries\ETHER_28J60\ETHER_28J60.cpp:103: error: 'class EtherShield' has no member named 'ES_get_tcp_data_pointer'
C:\Program Files\arduino-0022\libraries\ETHER_28J60\ETHER_28J60.cpp:108: error: 'class EtherShield' has no member named 'ES_make_tcp_ack_from_any'
C:\Program Files\arduino-0022\libraries\ETHER_28J60\ETHER_28J60.cpp: In member function 'void ETHER_28J60::respond()':
C:\Program Files\arduino-0022\libraries\ETHER_28J60\ETHER_28J60.cpp:158: error: 'class EtherShield' has no member named 'ES_make_tcp_ack_from_any'
C:\Program Files\arduino-0022\libraries\ETHER_28J60\ETHER_28J60.cpp:159: error: 'class EtherShield' has no member named 'ES_make_tcp_ack_with_data'
Thanks in advance.
Ozden
Hi, your lib work with this hardware?
http://www.ebay.co.uk/itm/ENC28J60-Ethernet-LEN-Network-Module-51-AVR-STM32-/180702040803?pt=LH_DefaultDomain_3&hash=item2a12ae52e3
Many thanks,
Vitor
Hi. Sorry for bothering.
I'd like to know if is there any way to increse the buffer that it's used on the ethernet.print function.
Thanks in advance.
To increase the buffer size, find the file arduino/libraries/ETHER_28J60.cpp and modify BUFFER_SIZE
SI.
Hi... I'm using your lib in a sketch (http://arduino.cc/forum/index.php/topic,74761.0.html) after a few interactions the arduino stops responding. Can you give me any idea/hint to solve this?
Thanks in advance,
Pedro
Hi Pedro. A common reason for unexpected halting is that you have run out of memory in your sketch.
How i extension code for second,third led on/off?I try but no load...I make pulse on / off a/c and i want to change mode heat,cool,dry,fan,auto...buffer size?Thanks.
Hello, Simon.
Thank you for the wrapper.
Does it support HTTP POST?
Thanks, 4ntoine.
Sorry, no HTTP Post.
hi Simon, Im using an ATmega to detect some values,this part i finished,now i would like to send the measured values via ENC28j60 to internet and open it as a HTML... do you have an C-code demonstrating the HTML in C?? or an example showing that... thanx
hi Simon, Im using an ATmega to detect some values,this part i finished,now i would like to send the measured values via ENC28j60 to internet and open it as a HTML... do you have an C-code demonstrating the HTML in C?? or an example showing that... thanx
hi Simon, Im using an ATmega to detect some values,this part i finished,now i would like to send the measured values via ENC28j60 to internet and open it as a HTML... do you have an C-code demonstrating the HTML in C?? or an example showing that... thanx
hi, great job.
a wed client example ?
"#include "etherShield.h"
#include "ETHER_28J60.h""
Hi Simon, thanks for your work. I have a question: does your library use the ENC28J60's internal RAM for packet buffering?
Hi Simon, thanks for your work. I have a question: does your library use the ENC28J60's internal RAM for packet buffering?
Hi Simon, thanks for your work. I have a question: does your library use the ENC28J60's internal RAM for packet buffering?
Post a Comment