Atendendo a algumas demandas, a Crescer desenvolveu um shield ethernet utilizando o LAN8720, pensado especificamente para funcionar com ESP32.
A CPB 32 permite conexão com WiFi, ler os sensores através dos pinos analógicos, acionar relés, pinos isolados por optoacopladores e outras ferramentas. A CPB MINI 32 é uma versão reduzida da anterior, a principal diferença é o fato de não possuir optoacopladores e relés. Nas figuras a seguir podemos ver as duas placas, sendo a preta a CPB 32 e a branca e MINI 32.
Para mais informações sobre o LAN8720 sugerimos a leitura do outro blog, onde mostramos como utilizar o módulo ethernet comercial. No blog de hoje vamos ver como utilizar o nosso shield ethernet nas duas placas.
Sumário
1. Shield Ethernet
O nosso shield foi desenvolvido especificamente para funcionar com as nossas placas que utilizam ESP32, porém, pode também ser utilizado com outros microcontroladores e outras placas, respeitando as ligações dis pinos.
Seu tamanho e disposição dos pinos permitem seu encaixe perfeito nas CPB 32 e MINI 32, pois, segue o mesmo padrão dos shields de Arduino. Na figura a seguir podemos ver o shield.
Na figura abaixo temos o pinout do shield, eles estão posicionados de modo que possam ser conectados nos pinos da ESP32 indicado na tabela a seguir.
O shield ethernet possui um jumper, indicado na figura a seguir, que é utilizado para interligar o GND do LAN8720 com o do “mundo externo”, nesse caso o dispositivo de rede que ele está conectado. Com base nos testes realizados, recomenda-se utilizar ela com o jumper aberto.
2. Preparando a CPB MINI 32
Para utilizar o shield com a CPB MINI 32 é necessário fazer uma pequena modificação na placa, para conectar o GPIO 0 à barra de pino correspondente a ele do shield. Como pode ser visto na figura a seguir:
Ele é conectado à CPB diretamente, como mostrado na figura a seguir:
3. Preparando a CPB 32
Para utilizar o shield com a CPB 32 devemos também ligar o GPIO 0 ao pino correto, próximo ao botão de reset temos o pad para acesso ao GPIO, ligação pode ser vista na figura a seguir:
Devido ao consumo de corrente do shield é aconselhado utilizar um regulador de tensão externo, para reduzir a dissipação de potência do LM1117. Veja como fazer essa alteração clicando no link. Após as modificações esse é o resultado:
Depois de feitas as modificações o shield é conectado à CPB diretamente, como mostrado na figura a seguir:
4. Programa exemplo
Como base utilizamos os exemplos SimpleWiFiServer e ETH_LAN8720, disponíveis na IDE do Arduino, podem ser encontrados em Arquivos -> Exemplos -> WiFi. O objetivo aqui é adaptar o SimpleWiFiServer para funcionar com o shield utilizando as funções mostradas no ETH_LAN8720.
Foi utilizada a CPB 32 com a topologia mostrada na figura a seguir, porém, funciona perfeitamente com a CPB MINI 32, afinal temos o mesmo microcontrolador em ambas.
A conexão com a rede será feita via ethernet, porém, utilizamos o WiFi para criar o Web Server, onde serão acessados os dados. Portanto, o primeiro passo é remover do SimpleWiFiServer as funções referentes a conexão WiFi com a rede, destacadas na figura a seguir.
Agora o próximo passo é colocar a biblioteca ETH.h e as definições dos pinos em que o shield está conectado, para as nossas placas, que utilizam ESP32, essa definição será sempre a mesma. Podem ser colocados logo após a inclusão da biblioteca WiFi.h.
#include <ETH.h>
//DEFINIÇÃO DOS PINOS PARA COMUNICAR COM A SHIELD ETHERNET ETH_LAN8720
// Pino do sinal de habilitação para o oscilador de cristal externo (-1 para desabilitar para fonte APLL interna)
// Tipo de Ethernet PHY
#define ETH_TYPE ETH_PHY_LAN8720
// Endereço I2C de Ethernet PHY (0 ou 1 para LAN8720)
#define ETH_ADDR 1
#define ETH_PHY_ADDR 1
// Pino do sinal de relógio I2C para Ethernet PHY
#define ETH_CLK_MODE ETH_CLOCK_GPIO0_IN
//#define ETH_CLK_MODE ETH_CLOCK_GPIO15_IN
static bool eth_connected = false;
No setup vamos inicializar o shield, com a função ETH.begin(), onde devemos informar a ela os pinos 5 (PHY_POWER), 13 (MCD), 18 (MDIO). Também iniciamos a função WiFiEvent, que é responsável por executar a comunicação do shield.
WiFiServer server(80);
void setup()
{
Serial.begin(115200);
pinMode(32, OUTPUT);// Pino do relé
WiFi.onEvent(WiFiEvent); //Executa a função de comunicação da Shield
ETH.begin( PHY1 , 5, 13, 18 , ETH_PHY_LAN8720); //Inicia a Shield com os pinos configurados
server.begin();
}
A função WiFiEvent é a seguinte:
void WiFiEvent(WiFiEvent_t event)
{
switch (event) {
case SYSTEM_EVENT_ETH_START:
Serial.println("ETH Started");
//set eth hostname here
ETH.setHostname("esp32-ethernet");
break;
case SYSTEM_EVENT_ETH_CONNECTED:
Serial.println("ETH Connected");
break;
case SYSTEM_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 SYSTEM_EVENT_ETH_DISCONNECTED:
Serial.println("ETH Disconnected");
eth_connected = false;
break;
case SYSTEM_EVENT_ETH_STOP:
Serial.println("ETH Stopped");
eth_connected = false;
break;
default:
break;
}
}
No loop a única alteração foi o pino que é acionado, no exemplo original é o pino 5 aqui vamos utilizar o 32, para acionar um relé da placa. Agora podemos carregar o código na placa, assim que ele se conectar na rede podemos pegar o IP do dispositivo através da serial, como podemos ver na figura a seguir.
Acessando esse IP no navegador poderemos ligar e desligar o relé da placa, clicando na opção indicada, como podemos ver na figura a seguir:
Para mais informações sobre a biblioteca ETH.h veja os outros exemplos presentes na IDE do Arduino ou veja essa pasta no GitHub.
Gostou do conteúdo? tenta fazer esse exemplo aí, quando conseguir compartilha nas redes sociais e marca a gente @crescer_automacao!
Autor: Thales Ferreira
ANEXO - Código exemplo
#include <WiFi.h>
#include <ETH.h>
//DEFINIÇÃO DOS PINOS PARA COMUNICAR COM A SHIELD ETHERNET ETH_LAN8720
// Pino do sinal de habilitação para o oscilador de cristal externo (-1 para desabilitar para fonte APLL interna)
// Tipo de Ethernet PHY
#define ETH_TYPE ETH_PHY_LAN8720
// Endereço I2C de Ethernet PHY (0 ou 1 para LAN8720)
#define ETH_ADDR 1
#define ETH_PHY_ADDR 1
// Pino do sinal de relógio I2C para Ethernet PHY
#define ETH_CLK_MODE ETH_CLOCK_GPIO0_IN
//#define ETH_CLK_MODE ETH_CLOCK_GPIO15_IN
static bool eth_connected = false;
WiFiServer server(80);
void setup()
{
Serial.begin(115200);
pinMode(32, OUTPUT);// Pino do relé
WiFi.onEvent(WiFiEvent); //Executa a função de comunicação da Shield
ETH.begin( PHY1 , 5, 13, 18 , ETH_PHY_LAN8720); //Inicia a Shield com os pinos configurados
server.begin();
}
int value = 0;
void loop(){
WiFiClient client = server.available(); // listen for incoming clients
if (client) { // if you get a client,
Serial.println("New Client."); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
// the content of the HTTP response follows the header:
client.print("Click <a href=\"/H\">here</a> to turn the LED on pin 5 on.<br>");
client.print("Click <a href=\"/L\">here</a> to turn the LED on pin 5 off.<br>");
// The HTTP response ends with another blank line:
client.println();
// break out of the while loop:
break;
} else { // if you got a newline, then clear currentLine:
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
// Check to see if the client request was "GET /H" or "GET /L":
if (currentLine.endsWith("GET /H")) {
digitalWrite(32, HIGH); // GET /H turns the LED on
}
if (currentLine.endsWith("GET /L")) {
digitalWrite(32, LOW); // GET /L turns the LED off
}
}
}
// close the connection:
client.stop();
Serial.println("Client Disconnected.");
}
}
void WiFiEvent(WiFiEvent_t event)
{
switch (event) {
case SYSTEM_EVENT_ETH_START:
Serial.println("ETH Started");
//set eth hostname here
ETH.setHostname("esp32-ethernet");
break;
case SYSTEM_EVENT_ETH_CONNECTED:
Serial.println("ETH Connected");
break;
case SYSTEM_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 SYSTEM_EVENT_ETH_DISCONNECTED:
Serial.println("ETH Disconnected");
eth_connected = false;
break;
case SYSTEM_EVENT_ETH_STOP:
Serial.println("ETH Stopped");
eth_connected = false;
break;
default:
break;
}
}
Comments