LAN8720 підключення до ESP32

LAN8720 хороше рішення для вашого проекту, якщо потрібно підключатись до Ethernet через дротове з’єднання. ESP32 підтримує дротовий Ethernet разом із бездротовою мережею, що може бути величезною перевагою для програм, які потребують дротового підключення.

LAN8720 – PHY модуль (Physical layer) фізичний рівень. Його ціль в забезпеченні доступу аналогового сигналу мережі до фізичного засобу передачі даних. Для зв’язку з мікроконтролером застосовується RMII інтерфейс.

DHCP

Статична IP-адреса

Керування реле за допомогою вебсервера

Схема модуля LAN8720

lan8720_schemantic

Підключення до ESP32

ESP32 Ethernet PHY LAN8720
GPIO 21TX-EN
GPIO 22TXD1
GPIO 19TXD0
GPIO 27CRS
GPIO 26RXD1
GPIO25RXD0
GPIO 23MDC
GPIO 18MDIO
GPIO17nINT/RETCLK
GNDNC, GND
VCC3.3V
lan8720 pinout
Приклад коду
#include <ETH.h>
#include <PubSubClient.h>

#ifdef ETH_CLK_MODE
#undef ETH_CLK_MODE
#endif
#define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT
#define ETH_POWER_PIN -1
#define ETH_TYPE ETH_PHY_LAN8720
#define ETH_ADDR 1
#define ETH_MDC_PIN 23
#define ETH_MDIO_PIN 18

static bool eth_connected = false;
const char *mqttBroker = "test.mosquitto.org";
int mqttPort = 1883;
WiFiClient lanClient;
PubSubClient mqttClient(mqttBroker, mqttPort, lanClient);

void WiFiEvent(WiFiEvent_t event)
{
    switch (event)
    {
    case ARDUINO_EVENT_ETH_START:
        Serial.println("ETH Started");
        ETH.setHostname("lan8720");
        break;
    case ARDUINO_EVENT_ETH_CONNECTED:
        Serial.println("ETH Connected");
        break;
    case ARDUINO_EVENT_ETH_GOT_IP:
        Serial.print("ETH MAC: ");
        Serial.print(ETH.macAddress());
        Serial.print(", IPv4: ");
        Serial.print(ETH.localIP());
        if (ETH.fullDuplex())
        {
            Serial.print(", FULL_DUPLEX");
        }
        Serial.print(", ");
        Serial.print(ETH.linkSpeed());
        Serial.println("Mbps");
        eth_connected = true;
        break;
    case ARDUINO_EVENT_ETH_DISCONNECTED:
        Serial.println("ETH Disconnected");
        eth_connected = false;
        break;
    case ARDUINO_EVENT_ETH_STOP:
        Serial.println("ETH Stopped");
        eth_connected = false;
        break;
    default:
        break;
    }
}

void mqtt_connect()
{
    if (!eth_connected)
    {
        return;
    }
    if (mqttClient.connect(ETH.macAddress().c_str()))
    {
        mqttClient.publish("my_topic/lan8720_mac", ETH.macAddress().c_str());
    }
}

void setup()
{
    Serial.begin(9600);
    WiFi.onEvent(WiFiEvent);
    ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE);
    mqtt_connect();
}

void loop()
{
    static unsigned int timer = 0;
    if ((millis() - timer) >= 3000)

    {
        timer = millis();
        if (mqttClient.connected())
        {
            mqttClient.publish("my_topic/uptime", String(millis() / 1000).c_str());
        }
        else
        {
            mqtt_connect();
        }
    }
    mqttClient.loop();
}

Даний приклад підключається до MQTT тестового сервера test.mosquitto.org, також на сервері є інструкції для підключення по SSL/TLS та WebSockets.

При вдалому підключенні на сервер відправляється своя мак адреса в топік “my_topic/lan8720_mac”.

 mqttClient.publish("my_topic/lan8720_mac", ETH.macAddress().c_str());

Також кожні 3 секунди на топік “my_topic/uptime” відправляється аптайм мікроконтролера.

if (mqttClient.connected())
{
    mqttClient.publish("my_topic/uptime", String(millis() / 1000).c_str());
}
mqtt explorer

Більш детальна робота з MQTT на ESP32


Статична IP-адреса

#include <ETH.h>
#include <PubSubClient.h>

#ifdef ETH_CLK_MODE
#undef ETH_CLK_MODE
#endif
#define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT
#define ETH_POWER_PIN -1
#define ETH_TYPE ETH_PHY_LAN8720
#define ETH_ADDR 1
#define ETH_MDC_PIN 23
#define ETH_MDIO_PIN 18

static bool eth_connected = false;
const char *mqttBroker = "test.mosquitto.org";
int mqttPort = 1883;
WiFiClient lanClient;
PubSubClient mqttClient(mqttBroker, mqttPort, lanClient);

IPAddress ip(192, 168, 1, 25);
IPAddress subnet(255, 255, 255, 0);
IPAddress gateway(192, 168, 1, 1);
IPAddress dns1(192, 168, 1, 1);
IPAddress dns2(0, 0, 0, 0);

void WiFiEvent(WiFiEvent_t event)
{
    switch (event)
    {
    case ARDUINO_EVENT_ETH_START:
        Serial.println("ETH Started");
        ETH.setHostname("lan8720");
        break;
    case ARDUINO_EVENT_ETH_CONNECTED:
        Serial.println("ETH Connected");
        break;
    case ARDUINO_EVENT_ETH_GOT_IP:
        Serial.print("ETH MAC: ");
        Serial.print(ETH.macAddress());
        Serial.print(", IPv4: ");
        Serial.print(ETH.localIP());
        if (ETH.fullDuplex())
        {
            Serial.print(", FULL_DUPLEX");
        }
        Serial.print(", ");
        Serial.print(ETH.linkSpeed());
        Serial.println("Mbps");
        eth_connected = true;
        break;
    case ARDUINO_EVENT_ETH_DISCONNECTED:
        Serial.println("ETH Disconnected");
        eth_connected = false;
        break;
    case ARDUINO_EVENT_ETH_STOP:
        Serial.println("ETH Stopped");
        eth_connected = false;
        break;
    default:
        break;
    }
}

void mqtt_connect()
{
    if (!eth_connected)
    {
        return;
    }
    mqttClient.setClient(lanClient);
    if (mqttClient.connect(ETH.macAddress().c_str()))
    {
        mqttClient.publish("my_topic/lan8720_mac", ETH.macAddress().c_str());
    }
}

void setup()
{
    Serial.begin(9600);
    WiFi.onEvent(WiFiEvent);

    ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE);
    ETH.config(ip, gateway, subnet, dns1, dns2);
    mqtt_connect();
}

void loop()
{
    static unsigned int timer = 0;
    if ((millis() - timer) >= 3000)
    {
        timer = millis();
        if (mqttClient.connected())
        {
            mqttClient.publish("my_topic/uptime", String(millis() / 1000).c_str());
        }
        else
        {
            mqtt_connect();
        }
    }
    mqttClient.loop();
}

Керування реле за допомогою вебсервера

#include <ETH.h>
#include <PubSubClient.h>
#include <ESPAsyncWebServer.h>

#ifdef ETH_CLK_MODE
#undef ETH_CLK_MODE
#endif
#define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT
#define ETH_POWER_PIN -1
#define ETH_TYPE ETH_PHY_LAN8720
#define ETH_ADDR 1
#define ETH_MDC_PIN 23
#define ETH_MDIO_PIN 18

#define RELAY_PIN 5

static bool eth_connected = false;
bool flag_relay_status = true;
AsyncWebServer server(80);

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html><head><meta name="viewport" content="width=device-width, initial-scale=1">
<style>html{font-family: Helvetica;display: inline-block;margin: 0px auto;text-align: center;}
body{margin-top: 50px;}
.button{display: block;width: 80px;background-color: #f48100;border: none;
color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;
margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}
.button-on{background-color: #f48100;}
.button-on:active {background-color: #463c32;}
.button-off{background-color: #26282d;}
.button-off:active{background-color: #b86404;}</style>
</head><body><table align="center"><td>
<div id="btn-on" class="button button-off" onclick="btn_on()">ON</div></td>
<td><div id="btn-off" class="button button-off" onclick="btn_off()">OFF</div></td>
</table><script>status();function btn_on() {var xhr = new XMLHttpRequest();
xhr.open('GET', '/action_on');xhr.onload = function () {if (xhr.status === 200) {btn("on");}};xhr.send();}function btn_off(action) {
var xhr = new XMLHttpRequest();xhr.open('GET', '/action_off');xhr.onload = function () {if (xhr.status === 200) {btn("off");}};
xhr.send();}function btn(action) {if (action === "on") 
{document.getElementById("btn-on").className = "button button-on";document.getElementById("btn-off").className = "button button-off";} else if (action === "off") 
{document.getElementById("btn-on").className = "button button-off";document.getElementById("btn-off").className = "button button-on";}}
function status(){var xhr = new XMLHttpRequest();xhr.open('GET', '/status');xhr.onload = function () {
if (xhr.status === 200) {btn("on");} else if (xhr.status === 201){btn("off");}};xhr.send();}
</script></body></html>)rawliteral";

void WiFiEvent(WiFiEvent_t event)
{
    switch (event)
    {
    case ARDUINO_EVENT_ETH_START:
        Serial.println("ETH Started");
        ETH.setHostname("lan8720");
        break;
    case ARDUINO_EVENT_ETH_CONNECTED:
        Serial.println("ETH Connected");
        break;
    case ARDUINO_EVENT_ETH_GOT_IP:
        Serial.print("ETH MAC: ");
        Serial.print(ETH.macAddress());
        Serial.print(", IPv4: ");
        Serial.print(ETH.localIP());
        if (ETH.fullDuplex())
        {
            Serial.print(", FULL_DUPLEX");
        }
        Serial.print(", ");
        Serial.print(ETH.linkSpeed());
        Serial.println("Mbps");
        eth_connected = true;
        break;
    case ARDUINO_EVENT_ETH_DISCONNECTED:
        Serial.println("ETH Disconnected");
        eth_connected = false;
        break;
    case ARDUINO_EVENT_ETH_STOP:
        Serial.println("ETH Stopped");
        eth_connected = false;
        break;
    default:
        break;
    }
}

bool relay_on()
{
    if (flag_relay_status)
    {
        return true;
    }
    flag_relay_status = !flag_relay_status;
    digitalWrite(RELAY_PIN, flag_relay_status);

    return true;
}

bool relay_off()
{
    if (!flag_relay_status)
    {
        return true;
    }
    flag_relay_status = !flag_relay_status;
    digitalWrite(RELAY_PIN, flag_relay_status);

    return true;
}

void setup()
{
    Serial.begin(9600);
    pinMode(RELAY_PIN, OUTPUT);
    digitalWrite(RELAY_PIN, flag_relay_status);
    WiFi.onEvent(WiFiEvent);

    ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE);

    server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
              { request->send_P(200, "text/html", index_html); });

    server.on("/action_on", HTTP_GET, [](AsyncWebServerRequest *request)
              { relay_on(); request->send(200); });

    server.on("/action_off", HTTP_GET, [](AsyncWebServerRequest *request)
              { relay_off();  request->send(200); });

    server.on("/status", HTTP_GET, [](AsyncWebServerRequest *request)
              { if (flag_relay_status) { request->send(200);} 
              else { request->send(201);} });

    server.begin();
}

void loop()
{
}

У браузері перейдіть за IP адресою яку отримав LAN8720 від роутера. Вашу IP можна побачити у моніторі серійного порту, або на вашому роутері.

web

Також для підключення дротової мережі до ESP32 можна використати W5500.

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *