lasselukkari / aWOT

Arduino web server library.
MIT License
283 stars 41 forks source link

Question on Functionality Using ESP32 and W5500 #126

Closed HWEDK closed 3 years ago

HWEDK commented 3 years ago

SETUP: The build I have utilizes a W5500 wiznet 850io board with an ESP32-Wrover-E. I am programming currently with the latest ESP-IDF plugin for Arduino.

PLAN: I was able to use the Wifi, Ethernet, Webserver, and SPI libraries to connect an HTML based site either with, without, or concurrently with Ethernet and WiFi by using a processor function of sorts on the client class. I am using HTTP protocols to gain user inputs/outputs from the website locally. I would like to use the file system uploader plugin for ESP32 with littleFS or FatFS to serve the webpages and to store the values in-between other serial communication I am parsing.

SITUATION: This led me to the asynchronous library where the server.on() functions make manipulating the HTTP/HTML items easy. My issue is that when I tried to utilize the W5500 with the asynchronous library, it wouldn't open the server. I assume this is related to the issues with W5500 bypassing its internal TCP/IP engine and having to run in MAC RAW mode to function.

QUESTION: My question is then, does the AWOT library contain functionality that would allow me to use a file system with functionality similar to the asynchronous webserver functions that I could then parse and send elsewhere over serial communication, while still being able to use either Ethernet or WiFi connection--I don't need both simultaneously?

lasselukkari commented 3 years ago

Can you be a bit more specific on what you are trying to do. I'm not familiar with what you mean with "functionality that would allow me to use a file system with functionality similar to the asynchronous webserver functions".

To me it sounds that all the things you want to achieve should be straightforward to implement. If I understand correctly you want to serve html pages and read data from a http requests and send it to over serial. If so those are definitely easy to do. The library does not have built in support for serving files from a filesystem but there are plenty of examples, projects and a tutorial that shows how to get started.

If you share a bit more details about your project I may be able to help you to the right direction.

HWEDK commented 3 years ago

Thank you for your response. I can be a bit more specific on the tools needed yes. Also, I should note that my area of expertise is not software, but I am trying to make it so. That said, I do not have a major knowledge of the lower functions and libraries with ESP, but am trying to learn them as well--its more a matter of time that limits me now, as I can't rewrite an entire driver, but I have time to figure out the libraries.

First, I haven't been able to get my W5500 to work with AWOT functions like the Application app, but I have been able to connect and open the server using the base Ethernet.h code, so I know my chips work.

From the top-down, from website to serial I was hoping to store the HTML/CSS in the filesystem first. This is where the asynchronous part comes in from my understanding. The below two functions would represent calls I'd like to be able to make in some way. Functions that allow me to move data back and forth with HTTP or similar through a filesystem while the code with high memory use stays in the filesystem. This is not hard at all on Wi-Fi, but I discovered that the Asynchronous libraries that currently exist for Arduino will compile...and they will work for WiFi...but when I connect Ethernet the server doesn't register a client or anything. I need to be able to use either/or, Ethernet/WiFi for the same client connection to the webserver, whatever style of webserver that is.

//The processor functions is below just to show the base example I saw // Replaces placeholder with LED state value String processor(const String& var){ Serial.println(var); if(var == "STATE"){ if(digitalRead(ledPin)){ ledState = "ON"; } else{ ledState = "OFF"; } Serial.print(ledState); return ledState; } return String(); }

//This is the first example of using the HTTP with the asynchronous commands server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {request->send_P(200, "text/html", index_html, processor});

OR

// Route for root / web page, this example is similar to above but showcases how it can call to SPIFFS filesystem server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) { request->send(SPIFFS, "/index.html", String(), false, processor); });

Finally, I will use the filesystem requests to parse and send/receive data over serial with separate functions.

The 2nd big problem I have is in getting WiFi and Ethernet to both work, but with the other libraries too. The way I have it now, I am using libraries SPI.h, Ethernet.h, and WiFi.h with the below classes/code from those.

EthernetServer ethernetserver(60); WiFiServer wifiserver(80);

void setup(void) { //Here is the setup code for ethernet pins, IP, MAC etc.

WiFi.softAP(ssid,password); wifiserver.begin();

Ethernet.begin(mac, eip, gateway, subnet); ethernetserver.begin(); }

void loop() { // listen for incoming clients EthernetClient client = ethernetserver.available(); processClient(client, false);

// listen for incoming clients WiFiClient wifiClient = wifiserver.available(); processClient(wifiClient, true); }

void processClient(Client &client, bool fromWiFi = false) { if (client) { // If a new client connects,

// Here is the HTML/HTTP code and calls to functions performing everything currently in iterative loops

// Close the connection client.stop(); Serial.println("Client disconnected."); Serial.println(""); } }

As can be seen, this is not ideal for the part that involves serial communication or the fileserver in terms of flow, memory, etc. I'd prefer to separate out the processClient() code and use something like the asynchronous commands above. It seems to me that your handler functions could do this, but I'm all ears to a more seasoned opinion. The Ethernet is what is really making this harder, I'd have been done if it were just WiFi.

lasselukkari commented 3 years ago

All this is doable. The async in the asynchronous webserver just means that requests will not get blocked if one of them is slow for example.

Instead of using the file system for the html files I suggest you try out the awot-scripts. It can take any directory on your computer and transform it to a code that serves the files. It will use the same memory area as the filesystem implementations so there is no difference on that. The script will also compress the files with gzip and the browser will be automatically able to decompress them when it downloads them. This way the page loads will be faster and you will save some additional memory. You can read the tutorial here: https://awot.net/en/guide/tutorial.html. I also have rather many projects under my github account that do something similar that you are planning to do.

I have tested the library with the ESP32 + W5500 combo and had no issues. You say you have not been able to get it working but not why.

HWEDK commented 3 years ago

That sounds great. I will definitely try the AWOT scripts given the simplicity of my initial requirements. I'll make AWOT my current reference then for those.

As to the ESP32+W5500 issue, I have tried several different examples, and I'm not sure what I'm missing. First of all, when I set up the below code, I can connect to the IP and open a client browser session without issue. Whenever I try to use the AWOT Ethernet example, it compiles fine, and I can print the IP from the IP function, but I am unable to initiate a client connection in a browser from that IP. I have no errors or warnings, just no connection. I tried combinations of what I have below with the AWOT code, but nothing has allowed me to connect. Is this related to the pin assignment? The only difference I see is the way the app.() function gets information by not using what I am from the Arduino Ethernet.h with the ethernetserver.begin() class.

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; byte eip[] = { 192, 168, 7, 200 }; byte gateway[] = { 192, 168, 7, 1 }; byte subnet[] = { 255, 255, 255, 0 };

EthernetServer ethernetserver(80);

void setup(void) {

if defined(ESP32)

// Use the correct pin for ESP32

define USE_THIS_SS_PIN 22

if ( USE_ETHERNET || USE_ETHERNET_LARGE || USE_ETHERNET2 || USE_ETHERNET_ENC )

Ethernet.init (USE_THIS_SS_PIN);

endif

endif

Ethernet.begin(mac, eip, gateway, subnet); ethernetserver.begin();

}

void loop() { // listen for incoming clients EthernetClient client = ethernetserver.available(); processClient(client, false); }

void processClient(Client &client, bool fromWiFi = false) { if (client) {
WEBSITE IS HERE } }

Physically, the below information is how I have the pins actually connected. //// Note; ESP32-WROVER-E to W5500 850IO, or W5500 LITE chip //// MOSI: 23 //// MISO: 19 //// SCK: 18 //// SS: 22 //// Reset: 21 //// 3.3 V and Ground

lasselukkari commented 3 years ago

I have the LILYGO® TTGO T-Lite with the W5500. I tested this sketch that processes clients from Ethernet and WiFI and it seems to be working.

#include <SPI.h>
#include <WiFi.h>
#include <Ethernet.h>
#include <aWOT.h>

#define WIFI_SSID ""
#define WIFI_PASSWORD ""

#define ETH_RST   4
#define ETH_CS    5
#define ETH_SCLK  18
#define ETH_MISO  23
#define ETH_MOSI  19

EthernetServer ethernetServer(80);
WiFiServer wifiServer(80);
Application app;
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

void setupEthernet() {
  SPI.begin(ETH_SCLK, ETH_MISO, ETH_MOSI);

  pinMode(ETH_RST, OUTPUT);
  digitalWrite(ETH_RST, HIGH);
  delay(250);
  digitalWrite(ETH_RST, LOW);
  delay(50);
  digitalWrite(ETH_RST, HIGH);
  delay(350);

  Ethernet.init(ETH_CS);
  Ethernet.begin(mac);

  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.");
    while (true) {}
  }

  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
    while (true) {}
  }

  ethernetServer.begin();
  Serial.print("Ethernet IP: ");
  Serial.println(Ethernet.localIP());
}

void setupWiFi() {
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.println("Connecting WiFi");
    delay(1000);
  }
  Serial.print("WiFi IP: ");
  Serial.println(WiFi.localIP());
  wifiServer.begin();
}

void index(Request &req, Response &res) {
  res.print("Hello World!");
}

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

  setupWiFi();
  setupEthernet();

  app.get("/", &index);
}

void processClient(Client &client) {
  if (client.connected()) {
    app.process(&client);
    client.stop();
  }
}

void loop() {
  WiFiClient wifiClient = wifiServer.available();
  processClient(wifiClient);

  EthernetClient ethernetClient = ethernetServer.available();
  processClient(ethernetClient);
}

The ESP32 core has a non standard definition for the server that is not compatible with the rest of the Arduino ecosystem. If you want to use the normal Ethernet library you have to do a simple modification to the ESP32 core files.

To get the sketch compile you need to change this: https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/Server.h#L28

from

virtual void begin(int port) =0;

to

void begin() {};

I can't believe that they can't get this fixed in the ESP32 Arduino core.

HWEDK commented 3 years ago

Thank you, I'm away for a few days, but I'll try this out and see if I find any other issues then report back here so it can help--and be closed out.

HWEDK commented 3 years ago

I got it to work. The issue is not the Server.h for me, I'd already fixed all the pass by reference/type mismatch etc. issues with my project. The problem for mine was trying to use the SPI.begin() function with setting logic levels for the ethernet pins. Those instantiations did not work at all for me, and I had no problem just setting the initial pin value for MOSI/MISO etc like normal. Also, I was having trouble getting the softAP to work, not so much the wifiserver. That just took manually setting the server setup items, and passing arrays of IP etc. It didn't want to work with the functions.

Now that I have it connecting with the app.() AWOT I'll try the other items and see how they influence things.

Suffice to say, W5500 and ESP32-Wrover on the stack can work together concurrently with softAP, wifi, ethernet

lasselukkari commented 3 years ago

Suffice to say, W5500 and ESP32-Wrover on the stack can work together concurrently with softAP, wifi, ethernet

I'm closing this one.