Pages

Migrating from EtherShield to EtherCard library

Important Note: I have now stopped development work on the EtherShield library
However, this is not the end for Arduino and ENC28J60 libraries. The excellent EtherCard library from Jeelabs. I have decided this is the library I am to use in my examples and future ENC28J60 developments.

As the two librariers are based on the same original code they share a lot of similarities. One being that I wrote the DHCP code that is used in both the EtherShield and EtherCard libraries. There are a number of things that need to be changed in your sketches in order to use the EtherCard library. These are documented below:

Header file

Replace

#include <EtherShield.h>

with

#include <EtherCard .h>

Library use

Replace

#define BUFFER_SIZE 650
static uint8_t buf[BUFFER_SIZE+1];
EtherShield es=EtherShield();

With

#define BUFFER_SIZE 650
byte Ethernet::buffer[BUFFER_SIZE];

ENC28J60 initialisation

Replace

// Initialise SPI interface
es.ES_enc28j60SpiInit();
// initialize enc28j60
es.ES_enc28j60Init(mymac,8); // To specify CS pin
// es.ES_enc28j60Init(mymac); // To use default CS

es.ES_client_set_wwwip(websrvip); // target web server

With

if (ether.begin(sizeof Ethernet::buffer, mymac) == 0) {
Serial.println( "Failed to access Ethernet controller");
while(1);
}

or, if using a Nuelectronics ENC28J60 shield to use correct select pin

if (ether.begin(sizeof Ethernet::buffer, mymac,10) == 0) {
Serial.println( "Failed to access Ethernet controller");
while(1);
}

Allocate IP Address using DHCP

Replace

es.allocateIPAddress(buf, BUFFER_SIZE, mymac, 80, myip, mynetmask, gwip, dnsip, dhcpsvrip );

With

if (!ether.dhcpSetup()) {
Serial.println( "DHCP failed");
while(1);
}

Allocate IP Addresses using static addressing

Define Addresses with

static uint8_t myip[4] = { 192,168,1,101 };
static uint8_t gwip[4] = { 192,168,1,1 };

Setup library with

ether.staticSetup(myip, gwip);

Resolve DNS Hostname

Replace

if(!es.resolveHostname(buf, BUFFER_SIZE,(uint8_t*)HOSTNAME ) > 0 ) {
Serial.println("Hostname not resolved");
}

With

if (!ether.dnsLookup(PSTR( HOSTNAME ) )) {
Serial.println("DNS failed");
while(1);
}

Other Bits

You might want this bet next just to make sure ARP has been done for Router address:


while (ether.clientWaitingGw())
ether.packetLoop(ether.packetReceive());

Main Processing

Replace

dat_p=es.ES_packetloop_icmp_tcp(buf,es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf));

With

dat_p = ether.packetLoop(ether.packetReceive());

Sending HTTP GET Request

Replace

es.ES_client_browse_url(PSTR("/xyz.php"), "?search=Arduino", PSTR(HOSTNAME), &browserresult_callback);

With

ether.browseUrl(PSTR("/xyz.php"), "?search=Arduino", PSTR(HOSTNAME), &browserresult_callback);

General Packet Buffer Access

Replace

buf[55]

With

Ethernet::buffer[55]

DHCP Lease Expiry

Replace:

With

if (ether.dhcpExpired())
ether.dhcpSetup();

Setting alternative port for http server

Use:

ether.hisport = 1234;

There are more changes but these should cover most cases for now.

Still to address

The EtherCard library still needs a few updates such as:

  • Sleep mode
  • dodgy TCP implementation allowing only one packet before closing connection

Bookmark this post: bookmark bookmark bookmark bookmark bookmark bookmark bookmark bookmark bookmark bookmark

26 comments to Migrating from EtherShield to EtherCard library

  • PaulViscovich

    Well the lib looks nice and if a far cry better than what im using but….. I am using the arduino and ENC28J60 shield i do not see where i would have to make changes to get the code to compile and work with the shield You mention •User definable CS pin. Default of 8 works for Nanode and EtherCard on Jeenodes but not regular ENC28J60 shields but that leave me with my head hurting tring to figure out if it is a simple change to the code to make it work of if it simply wont work at all… although the lib is documented as having arduino support….

    Can you toss me a bone as to where to look to tweek it to work with the EtherShield and arduino..

    Thanks
    Paul

  • PaulViscovich

    #define ENC28J60_CONTROL_CS 10
    #define SPI_MOSI 11
    #define SPI_MISO 12
    #define SPI_SCK 13

    is what i find in the code of the current lib im using… will there be some thing simular in the ethercard lib??

  • PaulViscovich

    void ENC28J60::initSPI () {
    const byte SPI_SS = 10;
    const byte SPI_MOSI = 11;
    const byte SPI_MISO = 12;
    const byte SPI_SCK = 13;

    Humm and what i found while looking…..

    still cant seem to get the ethercadr lib to do anything it seems like the card will not init and i never get a link light

  • nat

    Hi Andy,

    Been updating my code to use EtherCard library, I uploaded the ‘pings’ example to a Nanode5 at its working fine. I’ve a few projects that are using the older Nueletronics ENC28J60 shield though, none of the examples work.

    Is this related to the CS pin? Thanks,

    Nat,

  • MarcoDP

    Great Job. Thanks!!

    Just a tip … found after several attempts: to use a ENC28J60 shield with arduino there is a parameter that MUST BE set: file enc28j60.cpp, line 243
    #define SELECT_BIT 2 ( default is 0, see comment )

    After this, all examples work fine on my arduino

    Marco

  • Hi Marco,

    with the latest version of EtherCard there is no need to hack the library to change the /CS pin. See Readme on github for EtherCard. Its an additional parameter to the begin function. Only values supported are 8, 9 and 10 with 8 being default if parameter is not present.

    Andy

  • jpdw

    I’ve been updating to EtherCard & spent 4 hrs debugging something only to find it was the DHCP server I was using on my dev bench – so thought I’d post as much in case this helps anyone else with Nanode Ethercard DHCP problems .

    Whatever I did in the Nanode code and/or added debug in the Ethercard dhcp code, it just wouldn’t seem to get an IP Addr. Wireshark showed DHCPDiscover, DHCPOffer then nothing (till the Nanode tried again). Turns out the DHCP server (an old netgear dsl router) was *always* (incorrectly) responding to DHCP requests with broadcasts which the nanode wasn’t processing. Replaced the DHCP server & hey presto!

  • Hi,

    The DHCP broadcast was identified some time ago and fixed in EtherShield library and has now been fixed in EtherCard too. If you get the lastest code you should see a difference.

    thanks

    Andy

  • Jim

    Hi,

    I have been having some trouble with the dhcp client in the Ethercard library, the dhcpd recieved the request and answered, but the client didn’t take the IP.

    I found that the OpenBSD dhcpd I was using sends packets with an extra option, so the hardcoded “int optionIndex = UDP_DATA_P + sizeof( DHCPdata ) + 4” in the function “check_for_dhcp_answer(word len)” was hitting option 52 in the packet instead of 53.

    I changed the code to check a small span of the packet instead:

    static void check_for_dhcp_answer (word len) {
    // Map struct onto payload
    DHCPdata *dhcpPtr = (DHCPdata*) (gPB + UDP_DATA_P);
    if (len >= 70 && gPB[UDP_SRC_PORT_L_P] == DHCP_SRC_PORT &&
    dhcpPtr->op == DHCP_BOOTRESPONSE && dhcpPtr->xid == currentXid ) {
    //int optionIndex = UDP_DATA_P + sizeof( DHCPdata ) + 4;
    int optionIndexBase=UDP_DATA_P + sizeof( DHCPdata );
    for (int optionIndex = optionIndexBase;
    optionIndex < optionIndexBase+10; optionIndex++) {
    if (gPB[optionIndex] == 53){
    switch( gPB[optionIndex+2] ) {
    case DHCP_STATE_OFFER: have_dhcpoffer(len); break;
    case DHCP_STATE_OK: have_dhcpack(len); break;
    }
    }
    }
    }
    }

    I'm not really sure what span I should be looking through, I just guessed a small span, and it works on both OpenBSDs dhcpd as well as Ubuntus udhcpd. It should also work with all of the previously working dhcpds as the code passes through the previously hardcoded +4.

    On another topic, does anyone reading this have a working example for a NTP client using the Ethercard lib functions?

    Regards,
    Jim

  • Jim

    Ah, sorry about that, my editor had replaced the spaces with tabs..

    Second attempt:

    static void check_for_dhcp_answer (word len) {
    // Map struct onto payload
    DHCPdata *dhcpPtr = (DHCPdata*) (gPB + UDP_DATA_P);
    if (len >= 70 && gPB[UDP_SRC_PORT_L_P] == DHCP_SRC_PORT &&
    dhcpPtr->op == DHCP_BOOTRESPONSE && dhcpPtr->xid == currentXid ) {
    //int optionIndex = UDP_DATA_P + sizeof( DHCPdata ) + 4;
    int optionIndexBase=UDP_DATA_P + sizeof( DHCPdata );
    for (int optionIndex = optionIndexBase;
    optionIndex < optionIndexBase+10; optionIndex++) {
    if (gPB[optionIndex] == 53){
    switch( gPB[optionIndex+2] ) {
    case DHCP_STATE_OFFER: have_dhcpoffer(len); break;
    case DHCP_STATE_OK: have_dhcpack(len); break;
    }
    }
    }
    }
    }

  • anupa89

    I’m little new to this, but I have a requirement to monitor a particular sensor via Internet. So now I have an Arduino UNO and a ENC28J60 Ethernet module(http://www.geeetech.com/Documents/ENC28J60%20Manual%20Source%20Code.pdf) and connected as described.
    But I couldn’t get it to work with this EtherCard lib. Is there any deference between EtherCard module and my ethernet module?
    If this lib won’t work with my module, can you recommend a lib suitable for my setting..(Better If there is a proper documentation also, so I can understand the sketch and make modifications easily)

    Please help.

  • soccou

    Hello Andy,

    I used your EtherShield library and found it quite helpful. Thank you. I am hoping you could give me a quick opinion.

    I am now trying to use the EtherCard library with a atmega1284p setup as a arduino clone. I started a thread over at http://forum.jeelabs.net/node/793 but no-one has any info.

    The summary is that your EtherShield library continues to work great with my setup, but not the EtherCard library. Do you have any ideas on the differences? the h/w is the same. I noticed one thing your library seems to use digitalWrite as opposed to direct register manipulation in EtherCard.

    Thanks

  • I am a Chinese, forgive my English is not very good, I use google translate. I use UNO with ENC28j60 when there is a problem, all the examples are not running, that many people use ehtercard lib, they also experienced the same problem. Here is my solution.

    Modify enc28j60.cpp line 360

    selectBit = 2; That’s all.

    Finally, thanks Andy.

  • The ethercard doesnt currently have pin definitions for the mega.

  • This is not needed, to use different CS pins no need to hack the library – you just ned to specify the pin, 8 9 or 10 as described in the ENC28J60 initialisation section above.

    Andy

  • yizhak

    Hi Andy,
    I’d be very glad if you could help me.
    I’m trying to compile a project that sends data packets (originating at a meteorological station) to the web.
    All I need is that the Arduino will send a GET request to a web server, or will open a URL, in this form:
    http://partcl.com/publish?publish_key=73111c2bd8309b00498330e0fa373acf&id=temp_test&value=100
    I don’t have much experience with HTTP, though. Also, I have the nuelectronics etherShield on arduino uno
    I tried to use your code, mainly the twitter example, but didn’t have any success.
    The EtherCard has a webClient example, but I can’t get it to run after the
    if (ether.begin(sizeof Ethernet::buffer, mymac) == 0
    line. It is just stuck on this line and doesn’t advance (maybe there are other libraries besides the etherCard that I need to have? the code compiled correctly)

    Could you please try to help me with that (supposedly 🙂 ) simple code?
    Thanks!!

  • yizhak

    Resolved!
    I found out here: http://winkleink.blogspot.com/2012/01/arduino-enc28j60-ethernet-module-part-2.html that the chip select may be connected to another pin than the etherCard’s defualt (8), and that you can state the pin number at the .begin(…) procedure.
    I found here: http://www.nuelectronics.com/download/projects/Ethernet_v1_0.pdf that the nuelectronics device indeed uses pin 10 for cs.
    A few minor changes to the webClient example and VOILA!! it works perfectly.

  • rossoreed

    Hi Andy, I’m using the ethercard library to post data to Pachube, and wanting to create a ‘watchdog’ to reset a Nanode if I fail to get a connection to Pachube similar to .
    But as you will see from those posts, I have been unable to transfer Glyn’s excellent work from openenergymonitor to a Pachube system, Have you any advice please how this can be achieved?
    Many thanks
    Paul

  • rossoreed

    Re my last post – the website link appears to have been blocked, it is openenergymonitor.org/emon/node/363

    Thank you

  • Scargill

    Is it just me? I have tried every variation of library and indeed it looks like the Ethercard library is the easiest to us – but for anything but the most trivial job, I cannot get it to work reliably. I’m using the 328 chip and basically switching relays, reading temperature and I’ve a number of web pages. The smaller web pages are fine including a login page – but the larger ones crash. If I increase RAM they work but then other problems crop up – it would APPEAR there is no checking to see if the pages are longer than the available RAM – I’ve tried looking at the Ethercard.CPP program – in particular BufferFiller:emit_p to see if I could simply truncate long pages – nope – I get blank pages instead…. has anyone implemented this library and added traps to stop Ram overflow???

  • fabianpie

    Hi Andy,
    Is it possible with EtherShield or EtherCard to allow a web server to reply to a get request with data longer than the ethernet buffer ? the ES_www_server_reply close the request …
    Regards,
    Fabian

  • francoml

    for ARDUINO UNO R3 : chance CS pin 8 to 10 everywhere com the .h files. ALSO initializing the ethercard, include like the ping example, the “,10) ” on the end of the initialization.

    Thankyou so much for this libray and Ethercard creation, is AMAZING and very stable! THANKS

  • superid888

    Hi Andy?
    I’am from China ?I‘am sorry for my poor english.
    I have a problem about UDP send with ethercard.

    My problem is about:
    I use Arduino uno3+ ENC28J60 + DHT11 + two 7segment LED to display temperature and humidity and send data to host PC by UDP , all the hardware and sub-module test normal, the ENC28J60 CS connect to D10, the measured power supply voltage for ENC28J60 is 3.3V, The IDE with the 1.03 version, EtherCard with the latest version. all functions in normal when I running wireshake to capture data on host PC,I got correctly display of temperature and humidity and the received UDP data is OK, but when I stop capture data with wireshake,the host computer can not receive any data.

    I’ve try several different program on host PC and got the same result.
    When I do the capturing with winshake, the program I use to receive UDP data can got correct result, when I stop capturing with winshake, the program I use to receive UDP data can’t received any data.

    I do a test by replace ENC28J60 with W5100 ,I got a correct result without runing winshask.
    Compare with the w5100 code I think the code for UDP in ethercard maybe short of something for bind sport to dport,but I don’t know how to modify the ethercard library. I also I don’t know how to use ether.udpTransmit() for Transmit udp data,would tell me what possible with the problem or give me a example?

    Thanks,
    Chen JW

    the code as below?

    //CS?D10?SI?D11?SO?D12?SCK?D13

    #include
    static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
    static byte myip[] = {192,168,2,23};
    static byte gwip[] = {192,168,23,254};
    byte Ethernet::buffer[100];
    static byte destip[]= {192,168,2,10};
    static int myport=1000,destport=1001;

    // bits representing segments A through G (and decimal point) for numerals 0-9
    const int numeral[10] = {
    //ABCDEFG /dp
    B11111100, // 0
    B01100000, // 1
    B11011010, // 2
    B11110010, // 3
    B01100110, // 4
    B10110110, // 5
    B10111110, // 6
    B11100000, // 7
    B11111110, // 8
    B11110110, // 9
    };
    // pins for decimal point and each segment
    // dp,G,F,E,D,C,B,A
    const int segmentPins[] = { 9,8,7,6,5,4,3,2};
    const int nbrDigits= 2; // the number of digits in the LED display
    //dig 1 2
    const int digitPins[nbrDigits] = { A4,A5};
    int dppin=A3; //set the decimal point link to PIN A3

    #include
    dht11 DHT11;
    #define DHT11PIN A0 //DHT11 PIN 3 ?UNO A0

    char string1[2];//humidity
    char string2[2];//temperature

    void setup()
    {
    Serial.begin(19200);

    if (ether.begin(sizeof Ethernet::buffer, mymac, 10) == 0)
    Serial.println( “Failed to access Ethernet controller”);
    if (!ether.staticSetup(myip))
    Serial.println(“Failed to set IP address”);

    // ether.setGwIp(gwip);

    for(int i=0; i < 8; i++)
    pinMode(segmentPins, OUTPUT); // set segment and DP pins to output
    for(int i=0; i = 0; digit–)
    {
    if(number > 0)
    {
    showDigit( number % 10, digit) ;
    number = number / 10;
    }
    }
    }
    }
    // Displays given number on a 7-segment display at the given digit position
    void showDigit( int segnumber, int digit)
    {
    digitalWrite( digitPins[digit], HIGH );
    for(int segment = 1; segment <8; segment++)
    {
    boolean isBitSet = bitRead(numeral[segnumber], segment);
    // isBitSet will be true if given bit is 1

    //isBitSet = ! isBitSet; // remove this line if common cathode display

    digitalWrite( segmentPins[segment], isBitSet);
    }
    delay(5);
    digitalWrite( digitPins[digit], LOW );
    }

  • […] próprio autor da biblioteca ethershield anunciou que não atualizará mais a biblioteca e recomenda o uso da biblioteca Ethercard. Essa biblioteca é compatível com o módulo sem problemas, mas o pino CS […]