LAN8720 хороше рішення для вашого проекту, якщо потрібно підключатись до Ethernet через дротове з’єднання. ESP32 підтримує дротовий Ethernet разом із бездротовою мережею, що може бути величезною перевагою для програм, які потребують дротового підключення.
LAN8720 – PHY модуль (Physical layer) фізичний рівень. Його ціль в забезпеченні доступу аналогового сигналу мережі до фізичного засобу передачі даних. Для зв’язку з мікроконтролером застосовується RMII інтерфейс.
Керування реле за допомогою вебсервера
Схема модуля LAN8720
Підключення до ESP32
ESP32 | Ethernet PHY LAN8720 |
---|---|
GPIO 21 | TX-EN |
GPIO 22 | TXD1 |
GPIO 19 | TXD0 |
GPIO 27 | CRS |
GPIO 26 | RXD1 |
GPIO25 | RXD0 |
GPIO 23 | MDC |
GPIO 18 | MDIO |
GPIO17 | nINT/RETCLK |
GND | NC, GND |
VCC | 3.3V |
Приклад коду
#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 на 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 можна побачити у моніторі серійного порту, або на вашому роутері.
Також для підключення дротової мережі до ESP32 можна використати W5500.