Monday, April 7, 2014

Configurar Etherner Shield ENC28J60 con Arduino MEGA 2560



Después de tanto buscar en inet como lograr hacer funcionar mi Ethernet Shield ENC28J60, logré encontrar la solución y la posteo acá porque sé que a alguien le servirá en algún futuro cercano. Para los que tengan dudas si su Shield es el adecuado, trabajé con el HanRun HR911105A 09/48, pero seguramente sirva para otros modelos. Acá una foto para más claridad:
Las conexiones con Arduino Mega 2560 son las siguientes:
GND -> GND
3.3 -> Vcc
SO -> Pin 50
SI -> Pin 51
SCK -> Pin 52
CS -> Pin 53
Los otros cuatro pines (INT, RESET, WOL, CLKOUT) quedan sin conectar.

La librería que se usará es la EtherCard, que la pueden bajar aquí: https://github.com/jcw/ethercard
Esta librería funciona sin problemas para placas Arduino UNO y quizás para algunas más, pero existe un pequeño inconveniente con las placas MEGA. En las placas Arduino MEGA, está mal configurado el pin CS, lo que genera que si se utiliza la librería con los ejemplos que trae, no vaya a funcionar jamás. Para arreglar dicho inconveniente, el método ether.begin que inicializa al Shield debe recibir un parámetro extra indicando la modificación del pin CS. Los encabezados deberían quedar de la siguiente forma:

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

Normalmente, dicho seteo suele estar en la función setup del Arduino. Lo que se hizo fue agregar un parámetro más al final del llamado a la función begin, que indica a que pin debe conectarse CS.

Finalmente, para verificar que el Arduino trabaja correctamente, pueden cargar el siguiente código:

#include <EtherCard.h>

// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31  };
static byte myip[] = { 192,168,2,188 };

byte Ethernet::buffer[500]; 
BufferFiller bfill;                   

void setup () {
  if (ether.begin(sizeof Ethernet::buffer, mymac, 53) == 0)
    Serial.println( "Failed to access Ethernet controller");
  ether.staticSetup(myip);
}

static word homePage() {
  bfill = ether.tcpOffset();        
  bfill.emit_p(PSTR(                  
"<!DOCTYPE html>"
"<html>"
    "<head>"
    "<style>"
    "body {"
    "font-size:100%;"
    "font-family:arial;"
    "}"
    "</style>"
    "</head>"
    "<body>"
        "<div >Hello World!</div>"
    "</body>"
"</html>"
    ));
  return bfill.position();
}

void loop () {
  word len = ether.packetReceive();
  word pos = ether.packetLoop(len);
  
  if (pos)  // check if valid tcp data is received
    ether.httpServerReply(homePage()); // send web page data
}

En mi caso, conecté la salida del Ethernet Shield a mi router y desde mi computadora, ingresando la IP indicada en el código, correspondiente al Arduino, logré entrar y ver la respuesta HTML. Es posible incluso pasar parámetros a la función emit_p y referenciarlos desde el HTML de la siguiente forma:

  bfill.emit_p(PSTR( 
"<!DOCTYPE html>"
"<html>"
    "<head>"
    "<style>"
    "body {"
    "font-size:100%;"
    "font-family:arial;"
    "}"
    "</style>"
    "</head>"
    "<body>"
        "<div >$D $D</div>"
    "</body>"
"</html>"
    ), "Hello ", "World!");  

Al final de la función se puede pasar una lista (no importa la cantidad) de elementos. En el HTML, mediante $D se tomará al elemento correspondiente al número de aparición de $D. En este caso, el primer $D toma el valor "Hello " y el segundo el valor "World!".

Dejo la fuente que me permitió llegar a solucionar este problema, que es básicamente todo lo que dejé aquí: http://en.code-bude.net/2013/06/22/how-to-use-enc28j60-ethernet-shield-with-arduino-mega-2560/
Saludos!

10 comments:

  1. cuando agrego el valor 63 al lado de mymac me da error

    webClientStaticIP.ino: In function 'void setup()':
    webClientStaticIP:32: error: no matching function for call to 'EtherCard::begin(unsigned int, byte [6], int)'
    C:\Users\Usuario\Documents\Arduino\libraries\EtherCard/EtherCard.h:131: note: candidates are: static uint8_t EtherCard::begin(uint16_t, const uint8_t*)

    ReplyDelete
    Replies
    1. Hola! A mi me sucedió lo mismo en su momento. Estas utilizando otra versión de esa library. Tendrías que descargar nuevamente la librería de EtherCard que indico (https://github.com/jcw/ethercard) y reemplazar la carpeta lib de Arduino. Fijate también si no estás usando otra librería de Ethernet, que no corresponda. En tu versión, la librería EtherCard tiene solamente un método constructor con 2 parámetros, en la versión que yo te paso, está el método con 3 parámetros (donde el último parámetro es el pin de CS correspondiente 53). Fijate, cualquier cosa me consultas. Saludos

      Delete
  2. Eres un hacha, muchas gracias me ha funcionado.

    ReplyDelete
    Replies
    1. De nada, me alegra haber ayudado a alguien con esto

      Delete
  3. era una mala configuración de la librería, ya me corrió, mil gracias...

    ReplyDelete
  4. funciona bien, pero al cabo de un tiempo (aprox un minuto) se pierde la comunicación con enc28j60, deja de hacer pin, alguien sabe por que ocurre esto?

    ReplyDelete
    Replies
    1. Me sucede lo mismo, pudiste solucionarlo?
      Temporalmente agregue un reset en el codigo para que inicie todo de nuevo.

      Delete
  5. muy bueno
    y para poner dos botones apagar y encender??
    gracias

    ReplyDelete