d-a-v / W5500lwIP

W5100, W5500 and ENC28J60 for esp8266 and lwIP (or any other uC using lwIP)
43 stars 11 forks source link

Add example to the repo #5

Open Pimmetje opened 5 years ago

Pimmetje commented 5 years ago

It would be nice to add the example given here https://github.com/d-a-v/W5500lwIP/issues/3#issuecomment-431273815 as a example to the repository.

It could save some people some searching for the correct pin connection.

Thanks for making this. Ill test it later today.

d-a-v commented 5 years ago

Thanks for your interest. Current master will not work, use commit 81fd79b10955a436d111b984078a97d64801eb8f instead. Explanations:

This driver is about to be integrated in the esp8266 arduino core. esp8266/arduino core-2.5.1 is about to be released and right after that, per https://github.com/d-a-v/W5500lwIP/commit/b468cc893e655752cb5876dabb310950fb11751c and this awaiting PR https://github.com/esp8266/Arduino/pull/6039 which will hopefully be integrated, utilization of this driver will be much simpler and will fix use-cases like the one exposed by @borisneubert in https://github.com/d-a-v/W5500lwIP/issues/3#issuecomment-435566310

I am also currently working on a driver compatible with W5100 (#4)

// D0 CS SDCARD
// D8 CS ethernet
// D3 MOS
// D2 INPUT WATER
// D4 1-WIRE temp

#include <ESP8266WiFi.h>

#include <w5500-lwIP.h>

Wiznet5500lwIP eth(D0);

void setup ()
{
  // setup code
  // ...

  eth.setDefault(); // use ethernet for default route
  eth.begin(); // default mtu & mac address
}

void loop ()
{
  // do whatever needed, including
  while (true)
  {
    // do stuff
    yield();
  }
}
Pimmetje commented 5 years ago

Thanks for the fast response

I tried several versions of ESP the error i get is the same. It seems to me a issue with a include or something.

C:\Users\Pim\Documents\Arduino\libraries\W5500lwIP\w5500-lwIP.cpp: In member function 'boolean Wiznet5500lwIP::begin(const uint8_t*, uint16_t)':

C:\Users\Pim\Documents\Arduino\libraries\W5500lwIP\w5500-lwIP.cpp:52:86: error: 'schedule_function_us' was not declared in this scope

     else if (!schedule_function_us([&]() { this->handlePackets(); return true; }, 100))

                                                                                      ^

In file included from C:\Users\Pim\Documents\Arduino\libraries\W5500lwIP\w5500-lwIP.cpp:12:0:

C:\Users\Pim\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.2\cores\esp8266/FunctionalInterrupt.h: At global scope:

C:\Users\Pim\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.2\cores\esp8266/FunctionalInterrupt.h:32:28: warning: 'scheduledInterrupts' defined but not used [-Wunused-variable]

 static ScheduledFunctions* scheduledInterrupts;
d-a-v commented 5 years ago

I tried several versions of ESP the error i get is the same.

As I told,

Current master will not work, use commit 81fd79b instead.

Or, try with the PR https://github.com/esp8266/Arduino/pull/6039

(Well it maybe is not nice of me to to push beta code on master)

borisneubert commented 5 years ago

Thank you d-a-v, still watching. Will try soon.

d-a-v commented 5 years ago

Current state of this driver will now work with latest git version esp8266 arduino core. (I sufferred to get this PR in)

borisneubert commented 5 years ago

Tried this example:

#include <Arduino.h>
#include "ESP8266WiFi.h"
#include <W5500lwIP.h>

// Arduino Pin 4 = Wemos Pin D2
#define CSPIN 4

Wiznet5500lwIP ether;

byte mac[] = {0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02};

void setup() {

  Serial.begin(115200);
  Serial.println("");
  Serial.println("start");

  ether.setDefault();
  //int present = ether.begin(mac);
  int present = ether.begin();
  Serial.println("present= " + String(present, HEX));

  while (!ether.connected()) {
    Serial.print(".");
    delay(1000);
  }
}

void loop() {  }

with latest Arduino core.

Still get this error:

In file included from .pio/libdeps/d1_mini/W5500lwIP/src/W5500lwIP.h:5:0,
                 from src/main.cpp:3:
.pio/libdeps/d1_mini/W5500lwIP/src/utility/lwIPeth.h: In instantiation of 'boolean LwipEthernet<RawEthernet>::begin(const uint8_t*, uint16_t) [with RawEthernet = Wiznet5500; boolean = bool; uint8_t = unsigned char; uint16_t = short unsigned int]':
src/main.cpp:20:29:   required from here
.pio/libdeps/d1_mini/W5500lwIP/src/utility/lwIPeth.h:127:86: error: 'schedule_function_us' was not declared in this scope
     else if (!schedule_function_us([&]() { this->handlePackets(); return true; }, 100))
                                                                                      ^
d-a-v commented 5 years ago

Sorry you need to use git version. The api for Ethernet is still not stable and under heavy discussion. It should work anyway and I'll update when needed until I can integrate everything into the arduino core.

borisneubert commented 5 years ago

Thank you for your quick reply!

I actually use the version of W5500lwIP from this git repository.

We just wait until things have stabilized and continue to watch this repo.

emelianov commented 5 years ago

For some reason at least with latest Arduino core (commit 9f03bbb8c38adf2f6dc9fb95e304b51f20a72f92 from Jun 14 14:58:29 2019) handlePackets() never called with delay() or yield() in setup section. Have to add run_scheduled_functions() as workaround.

#include <SPI.h>
#include <ESP8266WiFi.h>

#include <W5500lwIP.h>
#include <Schedule.h>

Wiznet5500lwIP eth(SPI, D4);
byte mac[] = {0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02};

void setup ()
{
  Serial.begin(115200);
  WiFi.mode(WIFI_OFF);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);
  SPI.setFrequency(40000000); // Works up to 80M

  eth.setDefault(); // use ethernet for default route
  int present = eth.begin(mac);
  Serial.println("present= " + String(present, HEX));

  while (!eth.connected()) {
    Serial.print(".");
    delay(1000);
    run_scheduled_functions();
  }
  Serial.println(eth.localIP());
}

void loop ()
{
    yield();
}
d-a-v commented 5 years ago

@borisneubert I have so far been using one of the examples you pointed me to to test this driver. (with mqtt)


#include <Arduino.h>

//....................................................
// WiFi
#include "ESP8266WiFi.h"
const char *ssid = STASSID;
const char *password = STAPSK;

//....................................................
#define CSPIN 16 // GPIO16

//#include <W5500lwIP.h>
//Wiznet5500lwIP eth(SPI, CSPIN);

#include <W5100lwIP.h>
Wiznet5100lwIP eth(SPI, CSPIN);

int present = 0;

#include <osapi.h>
LOCAL os_timer_t eth_timer;
int led = 0;

//....................................................
// asynchronous web server
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
AsyncWebServer server(80);

//....................................................
// ntp client
#include <NTPClient.h>
#include <WiFiUdp.h>

#define NTPSERVER "91.202.42.83"
//#define NTPSERVER "0.ubuntu.pool.ntp.org"
//#define NTPSERVER "192.53.103.108"
WiFiUDP ntpUDP;
NTPClient ntpClient(ntpUDP, NTPSERVER, 3600, 20000);
unsigned long long t = 0, t0 = 0;

//....................................................
// mqtt client
#include <PubSubClient.h>
WiFiClient espClient;
PubSubClient client(espClient);
const char* mqtt_server = "10.0.1.254";
long lastMsg = 0;
char msg[50];
int value = 0;
String mqttMsg;

// mqtt callback
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.println("MQTT incomming subcribe: ");
  mqttMsg = topic;
  mqttMsg += " - ";
  for (int i = 0; i < length; i++) {
    mqttMsg += (char)payload[i];
  }
  Serial.println(mqttMsg);
}
// mqtt reconnect
void reconnect() {
  Serial.print("Attempting MQTT connection...");
  String clientId = "ESP8266Client-";
  if (client.connect(clientId.c_str())) {
    Serial.println("connected");
    client.publish("outTopic/start", "Hello from W5500!");
    client.subscribe("inTopic/#");
  } else {
    Serial.print("failed, rc=");
    Serial.print(client.state());
    Serial.println(" try again in 5 seconds");
  }
  /*
    -4 : MQTT_CONNECTION_TIMEOUT - the server didn't respond within the keepalive time
    -3 : MQTT_CONNECTION_LOST - the network connection was broken
    -2 : MQTT_CONNECT_FAILED - the network connection failed
    -1 : MQTT_DISCONNECTED - the client is disconnected cleanly
    0 : MQTT_CONNECTED - the client is connected
    1 : MQTT_CONNECT_BAD_PROTOCOL - the server doesn't support the requested version of MQTT
    2 : MQTT_CONNECT_BAD_CLIENT_ID - the server rejected the client identifier
    3 : MQTT_CONNECT_UNAVAILABLE - the server was unable to accept the connection
    4 : MQTT_CONNECT_BAD_CREDENTIALS - the username/password were rejected
    5 : MQTT_CONNECT_UNAUTHORIZED - the client was not authorized to connect
  */
}

//....................................................
void ICACHE_RAM_ATTR eth_loop(void) {
  digitalWrite(LED_BUILTIN, led);
  led = 1 - led;
  //if(present) eth.loop();
}

bool schedule_function_us(const std::function<bool(void)>& fn, uint32_t repeat_ms = 0);

//####################################################
// setup
//####################################################
void setup() {

  // starting example
  Serial.begin(115200);
  Serial.println("");
  delay(1000);
  Serial.println("starting example...");

  // starting wifi
  Serial.println("starting wifi...");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  int i = 0;
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    i++;
    if (i > 20) break;
  }
  Serial.println("");
  if (i > 20) {
    Serial.println("wifi connection failed");
  } else {
    Serial.print("wifi ip address: ");
    Serial.println(WiFi.localIP());
    Serial.print("wifi hostname: ");
    Serial.println(WiFi.hostname());
  }

  // starting ethernet
  // enable Ethernet here-------------------
  pinMode(LED_BUILTIN, OUTPUT);

  //Serial.println("starting ethernet...");
  //os_timer_disarm(&eth_timer);
  //os_timer_setfn(&eth_timer, (os_timer_func_t *)eth_loop, NULL);
  //os_timer_arm(&eth_timer, 1, 1);

  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV4); // 4 MHz?
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);

  eth.setDefault(); // use ethernet for default route
  present = eth.begin();
  if (!present) {
    Serial.println("no ethernet hardware present");
    //return;
  } else {
    Serial.print("connecting ethernet");
    while (!eth.connected()) {
      Serial.print(".");
      delay(1000);
    }
    Serial.println();
    Serial.print("ethernet ip address: ");
    Serial.println(eth.localIP());
  }

  // starting web server
  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    String htmlStr = "";
    htmlStr += "<HTML>";
    htmlStr += "<HEAD>";
    htmlStr += "<meta http-equiv=\"refresh\" content=\"1\">";
    htmlStr += "<TITLE />WiFi/ETH</title>";
    htmlStr += "</head>";
    htmlStr += "<BODY>";
    htmlStr += "WiFi/ETH";
    htmlStr += "<br />";
    htmlStr += "WiFi IP: ";
    htmlStr += WiFi.localIP().toString();
    htmlStr += "<br />";
    htmlStr += "ETH IP: ";
    htmlStr += eth.localIP().toString();
    htmlStr += "<br />";
    htmlStr += "Time: ";
    htmlStr += ntpClient.getFormattedTime();
    htmlStr += "<br />";
    htmlStr += "MQTT: ";
    htmlStr += mqttMsg;
    htmlStr += "<br />";
    htmlStr += "</BODY>";
    htmlStr += "</HTML>";
    request->send(200, "text/html", htmlStr);
  });
  server.begin();

  // starting ntp client
  Serial.println("starting ntp client...");
  ntpClient.begin();

  // starting mqtt client
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  client.subscribe("inTopic");

  // ready
  Serial.println("setup complete");
}

//####################################################
// loop
//####################################################
void loop() {
  while (true)
  {
    client.loop();
    ntpClient.update();

    t = ntpClient.getEpochTime();
    if (t != t0) {
      if (!client.connected()) reconnect();

      Serial.println(ntpClient.getFormattedTime());
      Serial.print("wifi ip address: ");
      Serial.println(WiFi.localIP());
      Serial.print("ethernet ip address: ");
      Serial.println(eth.localIP());

      client.publish("outTopic", ntpClient.getFormattedTime().c_str());
      t0 = t;

      uint32_t mfree;
      uint16_t mmax;
      uint8_t frag;
      ESP.getHeapStats(&mfree, &mmax, &frag);
      Serial.printf("%d %d %d\n", mfree, mmax, frag);

    }
    yield();
  }
}
Pfannex commented 4 years ago

Moin d-a-v,

I tried to run your latest example. I use your latest W5500lwIP commit an the actual stable Arduino core version 2.52.

Compiling the demo sketch results the following errors:

In file included from \Arduino\libraries\W5500lwIP/W5100lwIP.h:5:0, from W5500_dav_NEW.ino:15: Documents\Arduino\libraries\W5500lwIP/utility/lwIPeth.h: In instantiation of 'boolean LwipEthernet::begin(const uint8_t*, uint16_t) [with RawEthernet = Wiznet5100; boolean = bool; uint8_t = unsigned char; uint16_t = short unsigned int]':

W5500_dav_NEW.ino:146:23: required from here

Arduino\libraries\W5500lwIP/utility/lwIPeth.h:133:96: error: 'schedule_recurrent_function_us' was not declared in this scope

else if (!schedule_recurrent_function_us([&]() { this->handlePackets(); return true; }, 100))

Witch core-version do you use?

d-a-v commented 4 years ago

Latest git is required !

mynameisbill2 commented 4 years ago

Moin d-a-v,

I tried to run your latest example. I use your latest W5500lwIP commit an the actual stable Arduino core version 2.52.

Compiling the demo sketch results the following errors:

In file included from \Arduino\libraries\W5500lwIP/W5100lwIP.h:5:0, from W5500_dav_NEW.ino:15: Documents\Arduino\libraries\W5500lwIP/utility/lwIPeth.h: In instantiation of 'boolean LwipEthernet::begin(const uint8_t*, uint16_t) [with RawEthernet = Wiznet5100; boolean = bool; uint8_t = unsigned char; uint16_t = short unsigned int]': W5500_dav_NEW.ino:146:23: required from here Arduino\libraries\W5500lwIP/utility/lwIPeth.h:133:96: error: 'schedule_recurrent_function_us' was not declared in this scope else if (!schedule_recurrent_function_us(& { this->handlePackets(); return true; }, 100))

Witch core-version do you use?

Hi Pfannex, Have you resolved this problem? I met the same problem.

d-a-v commented 4 years ago

core 2.5.2 will not work. Git version of the core is necessary. Alternatively, you can use snapshots of the core (https://d-a-v.github.com)

d-a-v commented 4 years ago

Ethernet PR on arduino core launched: https://github.com/esp8266/Arduino/pull/6680 Merge won't happen before next core release. But I can keep alternative installable snapshots like in the post above which would include the ethernet PR.

Pfannex commented 4 years ago

Moin David,

with latest core commit dd73a18 WiFi and also ETH seems to run perfect including:

The Webserver is supported on WiFi-IP and also on ETH-IP. Both runs continuously!

In the next step we will test the lwIP function in our OmniESP-framework...

good job!

image

latest test sketch

#include <Arduino.h>

//....................................................
// WiFi
#include "ESP8266WiFi.h"
const char *ssid = "xxxxx";
const char *password = "xxxxx";

//....................................................
#define CSPIN 4 // GPIO4

#include <W5500lwIP.h>
Wiznet5500lwIP eth(SPI, CSPIN);

//#include <W5100lwIP.h>
//Wiznet5100lwIP eth(SPI, CSPIN);

int present = 0;

#include <osapi.h>
LOCAL os_timer_t eth_timer;
int led = 0;

//....................................................
// asynchronous web server
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
AsyncWebServer server(80);

//....................................................
// ntp client
#include <NTPClient.h>
#include <WiFiUdp.h>

#define NTPSERVER "91.202.42.83"
//#define NTPSERVER "0.ubuntu.pool.ntp.org"
//#define NTPSERVER "192.53.103.108"
WiFiUDP ntpUDP;
NTPClient ntpClient(ntpUDP, NTPSERVER, 3600, 20000);
unsigned long long t = 0, t0 = 0;

//....................................................
// mqtt client
#include <PubSubClient.h>
WiFiClient espClient;
PubSubClient client(espClient);
const char* mqtt_server = "192.168.1.10";
long lastMsg = 0;
char msg[50];
int value = 0;
String mqttMsg;

// mqtt callback
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.println("MQTT incomming subcribe: ");
  mqttMsg = topic;
  mqttMsg += " - ";
  for (int i = 0; i < length; i++) {
    mqttMsg += (char)payload[i];
  }
  Serial.println(mqttMsg);
}
// mqtt reconnect
void reconnect() {
  Serial.print("Attempting MQTT connection...");
  String clientId = "ESP8266Client-";
  if (client.connect(clientId.c_str())) {
    Serial.println("connected");
    client.publish("outTopic/start", "Hello from W5500!");
    client.subscribe("inTopic/#");
  } else {
    Serial.print("failed, rc=");
    Serial.print(client.state());
    Serial.println(" try again in 5 seconds");
  }
  /*
    -4 : MQTT_CONNECTION_TIMEOUT - the server didn't respond within the keepalive time
    -3 : MQTT_CONNECTION_LOST - the network connection was broken
    -2 : MQTT_CONNECT_FAILED - the network connection failed
    -1 : MQTT_DISCONNECTED - the client is disconnected cleanly
    0 : MQTT_CONNECTED - the client is connected
    1 : MQTT_CONNECT_BAD_PROTOCOL - the server doesn't support the requested version of MQTT
    2 : MQTT_CONNECT_BAD_CLIENT_ID - the server rejected the client identifier
    3 : MQTT_CONNECT_UNAVAILABLE - the server was unable to accept the connection
    4 : MQTT_CONNECT_BAD_CREDENTIALS - the username/password were rejected
    5 : MQTT_CONNECT_UNAUTHORIZED - the client was not authorized to connect
  */
}

//....................................................
void ICACHE_RAM_ATTR eth_loop(void) {
  digitalWrite(LED_BUILTIN, led);
  led = 1 - led;
  //if(present) eth.loop();
}

bool schedule_function_us(const std::function<bool(void)>& fn, uint32_t repeat_ms = 0);

//####################################################
// setup
//####################################################
void setup() {

  // starting example
  Serial.begin(115200);
  Serial.println("");
  delay(1000);
  Serial.println("starting example...");

  // starting wifi

  Serial.println("starting wifi...");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  int i = 0;
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    i++;
    if (i > 20) break;
  }
  Serial.println("");
  if (i > 20) {
    Serial.println("wifi connection failed");
  } else {
    Serial.print("wifi ip address: ");
    Serial.println(WiFi.localIP());
    Serial.print("wifi hostname: ");
    Serial.println(WiFi.hostname());
  }

  // starting ethernet
  // enable Ethernet here-------------------
  pinMode(LED_BUILTIN, OUTPUT);

  Serial.println("starting ethernet...");
  //os_timer_disarm(&eth_timer);
  //os_timer_setfn(&eth_timer, (os_timer_func_t *)eth_loop, NULL);
  //os_timer_arm(&eth_timer, 1, 1);

  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV4); // 4 MHz?
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);

  eth.setDefault(); // use ethernet for default route
  present = eth.begin();
  if (!present) {
    Serial.println("no ethernet hardware present");
    //return;
  } else {
    Serial.print("connecting ethernet");
    while (!eth.connected()) {
      Serial.print(".");
      delay(1000);
    }
    Serial.println();
    Serial.print("ethernet ip address: ");
    Serial.println(eth.localIP());
  }

  // starting web server
  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    String htmlStr = "";
    htmlStr += "<HTML>";
    htmlStr += "<HEAD>";
    htmlStr += "<meta http-equiv=\"refresh\" content=\"1\">";
    htmlStr += "<TITLE />WiFi/ETH</title>";
    htmlStr += "</head>";
    htmlStr += "<BODY>";
    htmlStr += "WiFi/ETH";
    htmlStr += "<br />";
    htmlStr += "WiFi IP: ";
    htmlStr += WiFi.localIP().toString();
    htmlStr += "<br />";
    htmlStr += "ETH IP: ";
    htmlStr += eth.localIP().toString();
    htmlStr += "<br />";
    htmlStr += "Time: ";
    htmlStr += ntpClient.getFormattedTime();
    htmlStr += "<br />";
    htmlStr += "MQTT: ";
    htmlStr += mqttMsg;
    htmlStr += "<br />";
    htmlStr += "</BODY>";
    htmlStr += "</HTML>";
    request->send(200, "text/html", htmlStr);
  });
  server.begin();

  // starting ntp client
  Serial.println("starting ntp client...");
  ntpClient.begin();

  // starting mqtt client
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  client.subscribe("inTopic");

  // ready
  Serial.println("setup complete");
}

//####################################################
// loop
//####################################################
void loop() {
  while (true)
  {
    client.loop();
    ntpClient.update();

    t = ntpClient.getEpochTime();
    if (t != t0) {
      if (!client.connected()) reconnect();

      Serial.println(ntpClient.getFormattedTime());
      Serial.print("wifi ip address: ");
      Serial.println(WiFi.localIP());
      Serial.print("ethernet ip address: ");
      Serial.println(eth.localIP());
      //Serial.println(eth.begin());

      client.publish("outTopic", ntpClient.getFormattedTime().c_str());
      t0 = t;

      uint32_t mfree;
      uint16_t mmax;
      uint8_t frag;
      ESP.getHeapStats(&mfree, &mmax, &frag);
      Serial.printf("%d %d %d\n", mfree, mmax, frag);

    }
    yield();
  }
}
d-a-v commented 4 years ago

Thanks for testing, for the report !

Pfannex commented 4 years ago

Hi David,

right now we implement your lwIP into our framework. It works pretty!

Every time the state of the ETH-connection changes we also want to change the default route.

Therefor you implemented:

template <class RawEthernet>
void LwipEthernet<RawEthernet>::setDefault ()
{
    Serial.println("set ETH to default, revise if not connected!");
    _default = true;
    if (connected())
        netif_set_default(&_netif);
}

#endif // _LWIPETH_H

How to make it switchable?

like

void LwipEthernet<RawEthernet>::setDefault (boolean state)
{
    _default = state;
     netif_set_default(&_netif);
}

or like

void LwipEthernet<RawEthernet>::setDefault ()
{
    if (connected()){
      _default = true;
    }else{
      _default = false;
    }
     netif_set_default(&_netif);
}
d-a-v commented 4 years ago

I think it would work: (why)

void LwipEthernet<RawEthernet>::setDefault (boolean enable)
{
     netif_set_default(enable? &_netif: nullptr);
}