Arduino and ENC28J60 Ethernet module

Item: Sure electronics – Ethernet Communication Module (ENC28J60)

Image: #1 #2 #3

Description: The Ethernet module is a small network interface card implemented with Microchip Technology new Stand Alone ENC28J60 Ethernet Network Controller.
The circuit board includes all required components for the Ethernet controller, plus a RJ-45 jack with integrated magnetics and built-in Link, and Activity LEDs for connection to an Ethernet Local Area Network. This module can be used with any Microprocessor or Microcontroller supporting the industry standard SPI™ interface.

Diagram: schematic

Connections to Arduino:
Ethernet module – Arduino
GND to GND
5v to 5v
DO (Serial data out) to Arduino pin 12
DI (Serial data in) to Arduino pin 11
CLK (Serial data clock) to Arduino pin 13
CS (Chip select) to Arduino pin 10
INT (Interrupt) to Arduino pin 3

Libraries:
There are quite a few options out there, I tried a lot of them and found that the updated version of “EtherShield” by thiseldo, worked best for my needs. The orginal lib created by nuelectronics.com works, but it lacks features like DHCP and a lot of other neat features.
Other libs:

Code (Arduino C):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
// EtherShield webserver that control an LED. 
/*
Sample code originally created by nuelectronics.com, but this has been modified by denhart.dk 
to take advatage of the new EtherShield Library from https://github.com/thiseldo/EtherShield\
*/
#include "EtherShield.h"
 
// please modify the following two lines. mac and ip have to be unique
// in your local area network. You can not have the same numbers in
// two devices:
static uint8_t mymac[6] = {
  0x54,0x55,0x58,0x10,0x00,0x25}; 
 
static uint8_t myip[4] = {
  192,168,1,25};
static char baseurl[]="http://192.168.1.25/";
#define MYWWWPORT 80
#define BUFFER_SIZE 550
#define LED_PIN 4
static uint8_t buf[BUFFER_SIZE+1];
uint16_t print_webpage(uint8_t *buf, byte on_off);
// The ethernet shield
EtherShield es=EtherShield();
 
uint16_t http200ok(void)
{
  return(es.ES_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nPragma: no-cache\r\n\r\n")));
}
 
 
// prepare the webpage by writing the data to the tcp send buffer
uint16_t print_webpage(uint8_t *buf, byte on_off)
{
  uint16_t plen;
  plen=http200ok();
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<center><h1>Welcome to Arduino ENC28J60 Ethernet Shield V1.1</h1>"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<hr><br><form METHOD=get action=\""));
  plen=es.ES_fill_tcp_data(buf,plen,baseurl);
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("\">"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<br> Control digital outputs"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h1><font color=\"#00FF00\"> "));
 
        if(on_off)
        	plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("ON"));
        else 
        	plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("OFF"));
 
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("  </font></h1><br> ") );
 
        if(on_off){
        	plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<input type=hidden name=cmd value=2>"));
        	plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<input type=submit value=\"Switch off\"></form>")); 
        }
        else {
        	plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<input type=hidden name=cmd value=1>"));
        	plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<input type=submit value=\"Switch on\"></form>"));
        }
 
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</center><hr>"));;  
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</body></html>"));
 
  return(plen);
}
 
 
void setup(){
  pinMode(LED_PIN, OUTPUT);
  // Initialise SPI interface
  es.ES_enc28j60SpiInit();
 
  // initialize enc28j60
  es.ES_enc28j60Init(mymac);
 
  // init the ethernet/ip layer:
  es.ES_init_ip_arp_udp_tcp(mymac,myip, MYWWWPORT);
}
 
void loop(){
  byte on_off=0;
  int8_t cmd;
  uint16_t plen, dat_p;
 
  while(1) {
    // read packet, handle ping and wait for a tcp packet:
    dat_p=es.ES_packetloop_icmp_tcp(buf,es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf));
 
    /* dat_p will be unequal to zero if there is a valid 
     * http get */
    if(dat_p==0){
      // no http request
      continue;
    }
    // tcp port 80 begin
    if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0){
      // head, post and other methods:
      dat_p=http200ok();
      dat_p=es.ES_fill_tcp_data_p(buf,dat_p,PSTR("<h1>200 OK</h1>"));
      goto SENDTCP;
    }
    // just one web page in the "root directory" of the web server
    if (strncmp("/ ",(char *)&(buf[dat_p+4]),2)==0){
      dat_p=print_webpage(buf, on_off);
      goto SENDTCP;
    }
  //This will be our switches, which control the LED   
    cmd=analyse_cmd((char *)&(buf[dat_p+5]));
 switch (cmd) {
    case 1:
      //do something when var equals 1
      digitalWrite(LED_PIN, HIGH);
      on_off=1;
      dat_p=print_webpage(buf, on_off);
      break;
    case 2:
      //do something when var equals 2
      digitalWrite(LED_PIN, LOW);
      on_off=0;
      dat_p=print_webpage(buf, on_off);
      break;
  }
 
 
SENDTCP:
    es.ES_www_server_reply(buf,dat_p); // send web page data
    // tcp port 80 end
 
  }
 
}
//Taken from the orginal sample code provided by http://nuelectronics.com/
uint8_t find_key_val(char *str,char *key)
{
        uint8_t found=0;
        uint8_t i=0;
        char *kp;
        kp=key;
        while(*str &&  *str!=' ' && found==0){
                if (*str == *kp){
                        kp++;
                        if (*kp == '\0'){
                                str++;
                                kp=key;
                                if (*str == '='){
                                        found=1;
                                }
                        }
                }else{
                        kp=key;
                }
                str++;
        }
        if (found==1){
                // copy the value to a buffer and terminate it with '\0'
                while(*str &&  *str!=' ' && *str!='&' && i<BUFFER_SIZE){
                        buf[i]=*str;
                        i++;
                        str++;
                }
                buf[i]='\0';
        }
        return(found);
}
 
//Taken from the orginal sample code provided by http://nuelectronics.com/
int8_t analyse_cmd(char *str)
{
        int8_t r=-1;
 
        if (find_key_val(str,"cmd")){
                if (*buf < 0x3a && *buf > 0x2f){
                        // is a ASCII number, return it
                        r=(*buf-0x30);
                }
        }
        return r;
}

Thoughts: Android app to control the lights?

8 Responses to “Arduino and ENC28J60 Ethernet module”


  • Hi, thanks for the post, I’m finding it hard to get any real information about these surprisingly cheap Ethernet devices. I have a question though. Does this work on a ATMega 1280 or just the 328 or 168?? what Arduino have you used this with? Thanks heaps!!

  • Hi Tim, this should work on the Arduino Mega with the ATMega 1280, but SPI pins are diffrent from the Uno or Duemilanovo. The pins on an Arduino mega is: 50 (MISO), 51 (MOSI), 52 (SCK), 53 (SS), more information can be found at the arduino website.
    Oh and I’m using the Arduino Duemilanove (ATmega328).

    //Denhart

  • Thanks! It worked right out of the box! It’s friggin’ magic!

  • Colossal kudos to you! Your code worked right out of the box (just had to change the IP and MAC in the code). It is just so fricken amazing.

    Next, i’m going to try to do this again with a Teensy!

  • I’m pleased to hear that it worked! Please do keep me updated on the whole teensy test :)

  • Can we connect it with a router to create it’s own wifi hotspot?

  • Hi,

    can i response MORE than BUFFER_SIZE??

    So i think on a Project with SD Card…
    that on

    GET /Index.htm i load the Index.htm from SD Card

    on

    GRT /Index2.htm i load the Index2.htm from SD Card

    and so on…

    but what happen if the File is bigger than the BUFFER_SIZE??

    Do the lib fill the buffer and if it is full the lib send the first and repeat it after complete file read??

    thanks for help

  • Would like to know how to output sensor data readings using this code?

Leave a Reply