Pages: [1] 2   Go Down
Author Topic: State of Arduino Ethernet Library  (Read 6693 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm new to the Ethernet Library so please excuse if I make some wrong assumptions here. I'm just looking for a more generic way to do things.

  • Is there someone maintaining the Library? I could not find a name anywhere.
  • Looks like the whole library is only useful for W5100 chips, every file links to it.
  • Why not extract a generic interface which could support multiple implementations?
  • DHCP works nicely but what's about DNS? The existing code does not work for me.

I'm asking because I ported this library to the W5200 on a Teensy3. Almost all code is identical to the Ethernet library but I had to replace this <<#include "w5100.h">> in every single file.

For me it looks like more or less every Ethernet chipset should be usable through one generic interface… Is there someone interested in this? What about the original author(s) of the Ethernet Library?

cheers,
Thomas
« Last Edit: January 04, 2013, 05:12:07 am by tht » Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 147
Posts: 6038
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The libraries and the related docs are maintained basically by us with the Arduino code crew editing the code, and the webmaster of the Arduino site doing the documentation editing. That webmaster person has been getting a bit behind lately it seems. It is a thankless job, so I'm not complaining, just saying...

I have submitted changes and bug fixes to the ethernet library, as have others here. It seems to be doing much better since IDE v1.0.1.  smiley

Quote
For me it looks like more or less every Ethernet chipset should be usable through one generic interface… Is there someone interested in this?
That is a GREAT idea! Contact Microchip and tell them to "get on the stick" and get their ENC28J60 hardware compatible with the w5100.  smiley-wink

Quote
What about the original author(s) of the Ethernet Library?
The original author(s) based the ethernet library around the w5100.h and w5100.cpp files provided by Wiznet. I have already submitted changes to the Arduino code crew that allows the ethernet library to use the w5200, the newer of the Wiznet products.
« Last Edit: January 02, 2013, 07:26:47 am by SurferTim » Logged

Forum Administrator
Cambridge, MA
Offline Offline
Faraday Member
*****
Karma: 12
Posts: 3538
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

BTW, there are generic Client, Server, IPAddress classes in the core, that various implementations can inherit from to provide a common interface. It probably doesn't share as much as it could but it's something.
Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 147
Posts: 6038
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

BTW, there are generic Client, Server, IPAddress classes in the core, that various implementations can inherit from to provide a common interface. It probably doesn't share as much as it could but it's something.
I can see how the libraries could be designed to use the same function calls, but different low level libraries. It would be great if you could compile for an ENC28J60 just by changing the include file. Is there enough reason to add that? Does the ENC28J60 offer advantages the W5200 does not?

This is just a transport, not a protocol. Setting up the transport should be rather universal. I mean, how much is there to it? mac, ip, subnet, gateway, dns, dhcp.

Thanks for all your help, David. Your efforts do not go unnoticed by at least some here.  smiley
Karma +1 for you.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for your fast reply. Looks like we're thinking in the same direction.

This is just a transport, not a protocol. Setting up the transport should be rather universal. I mean, how much is there to it? mac, ip, subnet, gateway, dns, dhcp.

For me the transport-layer should provide stuff like: mac, ip, subnet, gateway, sockets (open, close, send, getFreeTxSpace, getBytesAvailable). I'm quite sure it's possible to abstract this for (at least) the most common Ethernet chips out there.

Currently all implemented protocols (EthernetUDP, EthernetClient, DNS and DHCP) do include the w5100.h which binds it to this specific chipset. Some people just replace the content of the w5100.h,.cpp files with a driver for the W5200 chip. I don't like this workaround at all...

I only had to replace two functions (and some minor adjustments) in W5100.cpp and it worked for a W5200 on a 32bit ARM Cortex-M4 CPU. This is just great! The different layers (transport, IP/UDP, highlevel-protocol using TCP/UDP) are already layered how it should be but the binding is too tight.

Actually I don't know much about inheritance, interfaces, linking and stuff like this in C++ as I do have a Java background. Shouldn't this be possible?
« Last Edit: January 03, 2013, 02:49:14 pm by tht » Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 147
Posts: 6038
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

We are together here. I see where you are going, but it may require more than meets the eye. How would you tell the devices apart before compile? You must select the correct Arduino board in the IDE before compile. It does not even do that automatically.

I thought maybe using a different ethernet library include file for each. I wouldn't want to include all the code for every ethernet device, just the one I am using.
Code:
#include <Ethernet.h>
// or
#include <Ethernet5200.h>
// or
#include <Ethernet28J60.h>

All could include the same functions with the same parameters and return values as the current ethernet library.
Ethernet.begin()
server.available()
client.read()
client.println()
client.stop()
...and the like, don't you think?
Logged

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4085
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@SurferTim, is there an online repository (github, Google Code, etc.) where an adventurous person could download the library with the mods and enhancement that have not yet made their way into the IDE?
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 147
Posts: 6038
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@Jack Christensen: Here is the request I submitted on the code.google.com site. It has been imported into the github site now.
http://code.google.com/p/arduino/issues/detail?id=898
https://github.com/arduino/Arduino/issues/898
It does the w5200 conversion part, but not the ENC28J60.

edit: Careful on the Ethernet.h and Ethernet.cpp files. Back up your current files first. They may have changed since I posted that code.
« Last Edit: January 05, 2013, 03:20:15 pm by SurferTim » Logged

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4085
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@Jack Christensen: Here is the request I submitted on the code.google.com site. It has been imported into the github site now.

Great, thanks!  I've just recently started playing with the W5200 (on a WIZ810io module).
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 147
Posts: 6038
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@Jack: Let me know how it does for you. If good, then we only have one more to go. The ENC28J60.
Logged

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4085
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@Jack: Let me know how it does for you. If good, then we only have one more to go. The ENC28J60.

Sure will. Not sure if there's an ENC28J60 in my future though. Don't know much about it, but what little I've read makes me think it's a less capable chip, by which I just mean it does less in hardware, so the software has to pick up some functionality.
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

We are together here. I see where you are going, but it may require more than meets the eye. How would you tell the devices apart before compile? You must select the correct Arduino board in the IDE before compile. It does not even do that automatically.

I thought maybe using a different ethernet library include file for each. I wouldn't want to include all the code for every ethernet device, just the one I am using.
Code:
#include <Ethernet.h>
// or
#include <Ethernet5200.h>
// or
#include <Ethernet28J60.h>

All could include the same functions with the same parameters and return values as the current ethernet library.
Ethernet.begin()
server.available()
client.read()
client.println()
client.stop()
...and the like, don't you think?


That's what I'm looking at too. Actually I found a nice solution where there is one common, device-independent Ethernet class which is never used directly but only as interface. The actual implementation is EthernetW5200 which could easily be replaced with other implementations. What I like about my solution is that there is absolutely no change needed in the library files. The 'include' in the Sketch decides about the implementation. What I don't like about this solution is the amount of work which has to be done before this'll work. TCP and UDP implementation are tightly coupled to the W5x00 module.

W5100 and W5200 are almost identical, so it's possible to do them in the same sourcecode files but I doubt it's the same with ENC28J60 and others. IMHO this is only a short-term solution.

I've already uploaded some stuff to github too. It's not much more than a proof-of-concept but it already shows that it's possible to include different header files to select an implementation. Here's what I did:
* Made EthernetClass an abstract class which'll be the only interface used by all protocol implementations.
* Changed EthernetW5200 class so it inherits methods from the EthernetClass
* The Sketch now has to include one implementation and assign it to the global variable 'Ethernet'
* All protocol implementations are unchanged but won't work until they are freed from the direct calls to W5x00.*

And finally the link: https://github.com/tht/ArduinoEthernetGeneric

I won't be able to spend much time on it for a few weeks but it's a start and shows a possible way to go.
Logged

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4085
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@Tim, I downloaded the four files from Issue 898 on Google, Comment 6 by alexis.z...@gmail.com, Jun 14, 2012. Is that correct?
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 147
Posts: 6038
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Those should be good.
Logged

Hamme, Belgium
Offline Offline
Sr. Member
****
Karma: 4
Posts: 387
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I needed the Arduino Ethernet Library to give me back the DHCP-server's IP address, So I changed the Ethernet.h and Ethernet.cpp files (Arduino IDE 1.0.3)

Now one can use this in his sketch to get the DHCP-server's IP-address:

Code:
byte dhcpip[4];
for (byte i = 0; i < 4; i++)
{
  dhcpip[i] = Ethernet.dhcpServerIP()[i];
}

could someone submit these changes?

The topic I used to help me on the dhcp subject:
http://arduino.cc/forum/index.php/topic,133670.0

This is what I added in Ethernet.h (between the *********************************):

Code:
#ifndef ethernet_h
#define ethernet_h

#include <inttypes.h>
//#include "w5100.h"
#include "IPAddress.h"
#include "EthernetClient.h"
#include "EthernetServer.h"
#include "Dhcp.h"

#define MAX_SOCK_NUM 4

class EthernetClass {
private:
  IPAddress _dnsServerAddress;
//**************************************
  IPAddress _dhcpServerAddress;
//**************************************
  DhcpClass* _dhcp;
public:
  static uint8_t _state[MAX_SOCK_NUM];
  static uint16_t _server_port[MAX_SOCK_NUM];
  // Initialise the Ethernet shield to use the provided MAC address and gain the rest of the
  // configuration through DHCP.
  // Returns 0 if the DHCP configuration failed, and 1 if it succeeded
  int begin(uint8_t *mac_address);
  void begin(uint8_t *mac_address, IPAddress local_ip);
  void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server);
  void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway);
  void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet);
  int maintain();

  IPAddress localIP();
  IPAddress subnetMask();
  IPAddress gatewayIP();
  IPAddress dnsServerIP();
//*****************************************
  IPAddress dhcpServerIP();
//*****************************************
  friend class EthernetClient;
  friend class EthernetServer;
};

extern EthernetClass Ethernet;

#endif

This is what I added in Ethernet.cpp (between the *********************************):

Code:
#include "w5100.h"
#include "Ethernet.h"
#include "Dhcp.h"

// XXX: don't make assumptions about the value of MAX_SOCK_NUM.
uint8_t EthernetClass::_state[MAX_SOCK_NUM] = {
  0, 0, 0, 0 };
uint16_t EthernetClass::_server_port[MAX_SOCK_NUM] = {
  0, 0, 0, 0 };

int EthernetClass::begin(uint8_t *mac_address)
{
  _dhcp = new DhcpClass();


  // Initialise the basic info
  W5100.init();
  W5100.setMACAddress(mac_address);
  W5100.setIPAddress(IPAddress(0,0,0,0).raw_address());

  // Now try to get our config info from a DHCP server
  int ret = _dhcp->beginWithDHCP(mac_address);
  if(ret == 1)
  {
    // We've successfully found a DHCP server and got our configuration info, so set things
    // accordingly
    W5100.setIPAddress(_dhcp->getLocalIp().raw_address());
    W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address());
    W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address());
    _dnsServerAddress = _dhcp->getDnsServerIp();

   //**************************************
    _dhcpServerAddress = _dhcp->getDhcpServerIp();
   //**************************************
   
  }

  return ret;
}

void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip)
{
  // Assume the DNS server will be the machine on the same network as the local IP
  // but with last octet being '1'
  IPAddress dns_server = local_ip;
  dns_server[3] = 1;
  begin(mac_address, local_ip, dns_server);
}

void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server)
{
  // Assume the gateway will be the machine on the same network as the local IP
  // but with last octet being '1'
  IPAddress gateway = local_ip;
  gateway[3] = 1;
  begin(mac_address, local_ip, dns_server, gateway);
}

void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway)
{
  IPAddress subnet(255, 255, 255, 0);
  begin(mac_address, local_ip, dns_server, gateway, subnet);
}

void EthernetClass::begin(uint8_t *mac, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet)
{
  W5100.init();
  W5100.setMACAddress(mac);
  W5100.setIPAddress(local_ip._address);
  W5100.setGatewayIp(gateway._address);
  W5100.setSubnetMask(subnet._address);
  _dnsServerAddress = dns_server;
}

int EthernetClass::maintain(){
  int rc = DHCP_CHECK_NONE;
  if(_dhcp != NULL){
    //we have a pointer to dhcp, use it
    rc = _dhcp->checkLease();
    switch ( rc ){
      case DHCP_CHECK_NONE:
        //nothing done
        break;
      case DHCP_CHECK_RENEW_OK:
      case DHCP_CHECK_REBIND_OK:
        //we might have got a new IP.
        W5100.setIPAddress(_dhcp->getLocalIp().raw_address());
        W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address());
        W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address());
        _dnsServerAddress = _dhcp->getDnsServerIp();
        break;
      default:
        //this is actually a error, it will retry though
        break;
    }
  }
  return rc;
}

IPAddress EthernetClass::localIP()
{
  IPAddress ret;
  W5100.getIPAddress(ret.raw_address());
  return ret;
}

IPAddress EthernetClass::subnetMask()
{
  IPAddress ret;
  W5100.getSubnetMask(ret.raw_address());
  return ret;
}

IPAddress EthernetClass::gatewayIP()
{
  IPAddress ret;
  W5100.getGatewayIp(ret.raw_address());
  return ret;
}

IPAddress EthernetClass::dnsServerIP()
{
  return _dnsServerAddress;
}

//**************************************
IPAddress EthernetClass::dhcpServerIP()
{
  return _dhcpServerAddress;
}
//**************************************

EthernetClass Ethernet;

* Ethernet.h (1.26 KB - downloaded 26 times.)
* Ethernet.cpp (3.43 KB - downloaded 22 times.)
« Last Edit: January 10, 2013, 07:30:13 am by JO3RI » Logged


Pages: [1] 2   Go Up
Jump to: