Neste artigo abordaremos o uso do W5100 e do STM32F030 na placa Nucleo com a montagem de um Webserver utilizando o mbed.
O mbed é uma plataforma de desenvolvimento da ARM que visa diminuir o tempo de desenvolvimento com uma maior abstração do hardware. Para saber mais você pode conferir este webinar do Thiago Lima que mostra os primeiros passos na plataforma. Ainda sobre a plataforma, estou usando o compilador no browser, mas sinta-se livre para reproduzir este artigo com o mbed instalado em sua máquina. Você pode ver como fazer isto neste artigo de Thiago Lima.
Explicar o funcionamento da página não é a finalidade deste artigo, portanto assumi que você saiba HTML e CSS.
Hardware
Apesar do ethernet shield W5100 encaixar na placa Nucleo, precisamos fazer algumas ligações pois os sinais do SPI ficam no conector ICSP do shield e não são conectados com a NUCLEO.
A ligação fica a seguinte:
Tabela 1: Ligação dos pinos do Ethernet Shield com a Nucleo.
| Ethernet Shield | Nucleo |
| MOSI | PB_5 |
| MISO | PB_4 |
| SCK | PB_3 |
Veja o pinout da placa nucleo aqui.
Fundamentação teórica
Usaremos a biblioteca da Wiznet para o controle do shield, nela foram implementadas as interfaces necessárias para a troca de informações com o chip.
O que faremos é iniciar o servidor web (porta 80) e ficar aguardando o cliente conectar e requisitar a página do servidor para começar o envio. A página foi desenvolvida em HTML e estilizada com CSS.
Na página, nós usamos o protocolo de transferência HTTP 1.0, pois nesta versão o padrão de conexão não é persistente, não sendo necessário enviar no HEADER parâmetros como “Connection: close”.
A comunicação do botão é feita com GET, a página manda uma requisição “/1” para acender ou “/0” para apagar o led. A função get_request que implementei pode receber uma cadeia enorme de caracteres, basta aumentar o tamanho do Buffer passado no parâmetro da função get_request. O retorno da função devolve o tamanho da solicitação que foi feita pelo cliente.
Assim que iniciamos a conexão e disparamos os buffers com a página HTML, o navegador precisa de um parâmetro para saber que a página foi recebida, isto se faz através do número de caracteres da página. Quando o navegador recebe a quantidade de caracteres esperada, ele envia uma flag “FIN” para sinalizar o fim da transmissão de dados. Desta forma o nosso servidor encerra a conexão e o envio. É importante saber que sem receber este sinal, o servidor e o cliente ficam com a conexão ativa, isto resulta em uma página em loop no navegador. No cabeçalho nós enviamos então o parâmetro “Content-Length:” para sinalizar o tamanho da página.
Prática
Vamos abir o mbed, adicionar a placa no compilador e importar a biblioteca da Wiznet. Veja abaixo:
No canto direito superior podemos ver que a placa já foi selecionada, caso contrário é só clicar neste local, depois em “add board” e procurar sua placa no catálogo.
Crie um novo projeto vazio e crie um documento em branco chamado “main.cpp”. Agora vamos importar a biblioteca da wiznet para o projeto em questão:
Clique com o botão direito no “Projeto > Import Library > From Import Wizard”. Na barra de pesquisa procure por “wiznet_library” e adicione a biblioteca com duplo clique.
Cole o código abaixo no main.cpp.
#include "mbed.h"
#include "WIZnetInterface.h"
#define ST_NUCLEO
#define MYPORT 80
const char *IP_Addr = "192.168.25.20";
const char *IP_Subnet = "255.255.255.0";
const char *IP_Gateway = "192.168.25.1";
unsigned char MAC_Addr[6] = {0x90, 0xA2, 0xDA, 0x00, 0x9B, 0x36};
Serial pc(USBTX, USBRX);
AnalogIn adc_temp(ADC_TEMP);
DigitalOut myled(LED1);
SPI spi(PB_5,PB_4,PB_3); //(mosi, miso, sclk, ssel=nc)
WIZnetInterface ethernet(&spi,PB_6,PA_10); //(spi* , cs , reset)
char page_length[]= {"\r\nHTTP/1.0 200 OK\r\nContent-Type: text/html\r\nContent-Length: 2400\r\n\r\n"};
char page_head []= {"<!doctype html>\n\t<head>\n\t\t<style type=\"text/css\">\n\t\t\t.margem_laranja{\n\t\t\t\twidth: 98%;\n\t\t\t\theight: 40px;\n\t\t\t\tbackground-color:#F5B317;\n\t\t\t\tcolor: #FFFFFF;\n\t\t\t}\n\t\t\t.margem_cinza{\n\t\t\t\twidth: 98%;\n\t\t\t\theight: 40px;\n\t\t\t\tbackground-color:#6F6B5F;\n\t\t\t\tcolor: #FFFFFF;\n\t\t\t}\n\t\t\tbutton{\n\t\t\t\tfont-family:verdana;\n\t\t\t\tfont-size:10pt;\n\t\t\t\tbackground-color:#B0F0D2;\n\t\t\t\tborder: 50pt;\n\t\t\t\tborder-radius: 15px;\n\t\t\t\theight:15pt;\n\t\t\t\twidth:50pt;\n\t\t\t}\n\t\t</style>\n\t\t<title>Webserver</title>\n\t\t<meta http-equiv=\"refresh\" content=\"4\">\n\t\t<meta name=\"viewport\" content=\"width=320\">\n\t\t<meta name=\"viewport\" content=\"width=device-width\">\n\t\t<meta charset=\"utf-8\">\n\t\t<meta name=\"viewport\" content=\"initial-scale=1.0, user-scalable=no\">\n\t</head>"};
char page_body []= {"<body bgcolor=\"#E0FFFF\">\n\t\t<center>\n\t\t<div class=\"margem_cinza\">\n\t\t\t<a href=\"https://www.facebook.com/osembarcados\"><img src=\"https://embarcados.com.br/wp-content/uploads/2018/11/footer-facebook.png\" width=30 height=30/></a>\n\t\t\t<a href=\"https://www.linkedin.com/company/embarcados\"><img src=\"https://embarcados.com.br/wp-content/uploads/2018/11/logo-ln.png\" width=30 height=30 /></a>\n\t\t\t<a href=\"https://www.facebook.com/osembarcados\"><img src=\"https://embarcados.com.br/wp-content/uploads/2018/11/footer-youtube.png\" width=20 height=15/></a>\n\t\t</div>\n\t\t<a href=\"https://embarcados.com.br/\"><img src=\"https://embarcados.com.br/wp-content/uploads/2016/04/logo-380x124.png\"/></a>\n\t\t<div class=\"margem_laranja\"></div>\n\t\t<font size=\"7\" face=\"verdana\" color=\"#2E2E2E\">ARM Webserver </font>\n\t\t<br /><br /><br />\n\t\t<font size=\"5\" face=\"verdana\" color=\"black\">Temperatura interna</font><br /><br />\n\t\t<font size=\"7\" face=\"verdana\" color=\"black\">"};
char page_temp []={" "};
char page_body_2[]= {" °C</font><br /><br />\n\t\t<font size=\"5\" face=\"verdana\" color=\"black\">Led da placa</font><br /><br />\n\t\t<form action=\"1\" method=\"get\">\n\t\t\t<button type=submit style=\"width:200px;\" id=\"bot\" >Acender</button>\n\t\t</form><br />\n\t\t<form action=\"0\" method=\"get\">\n\t\t\t<button type=submit style=\"width:200px;\" id=\"bot\" >Apagar</button>\n\t\t</form><br /><br />\n\t\t<font size=\"2\" face=\"verdana\" color=\"black\">Webserver com STM32 Nucleo e ethernet shield W5100</font><br /><br />\n\t\t<font size=\"2\" face=\"verdana\" color=\"black\">Por: Muriel Costa</font><br />\n\t\t<font size=\"2\" face=\"verdana\" color=\"black\">Email: mrlcosta0@gmail.com</font><br />\n\t\t<font size=\"2\" face=\"verdana\" color=\"black\">Dont panic!</font><br />\n\t</body>\n</html>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"};
char get_buf []= {" "};
int get_request (char* buf_get, int size,TCPSocketConnection& client){
char buffer[300];
client.receive(buffer, sizeof(buffer) );
int get_size=0;
for(int i=0, k=0; i<sizeof(buffer) && k < 2; i++) {
if(buffer[i]==' ') {
k++;
}
if (k==1) {
buf_get[get_size] = buffer[i];
get_size++;
}
}
return get_size;
}
int main(){
pc.baud(115200);
pc.printf("Starting\r\n");
while(1) {
int ret = ethernet.init(MAC_Addr,IP_Addr,IP_Subnet,IP_Gateway);
if (!ret) {
pc.printf("Initialized, MAC: %s\r\n", ethernet.getMACAddress());
ret = ethernet.connect();
if (!ret) {
pc.printf("IP: %s, MASK: %s, GW: %s\r\n",
ethernet.getIPAddress(), ethernet.getNetworkMask(), ethernet.getGateway());
} else {
pc.printf("Error ethernet.connect() - ret = %d\r\n", ret);
exit(0);
}
} else {
pc.printf("Error ethernet.init() - ret = %d\r\n", ret);
exit(0);
}
TCPSocketServer server;
server.bind(MYPORT);
server.listen();
while (1) {
pc.printf("\nWait for new connection...\r\n");
TCPSocketConnection client;
server.accept(client);
client.set_blocking(false, 0); // Timeout=0.
pc.printf("Connection from: %s\r\n", client.get_address());
int temp = (adc_temp.read()*10);
page_temp [0]= (adc_temp.read()*10) +'0';
page_temp [1]= ((adc_temp.read()*100)-temp*10) +'0' ;
if (client.is_connected() == true){
int j = get_request(get_buf , sizeof(get_buf), client);
if(client.is_fin_received()) {
client.close();
}
client.send (page_length, sizeof(page_length));
client.send (page_head, sizeof(page_head));
client.send (page_body, sizeof(page_body));
client.send (page_temp, sizeof(page_temp));
client.send (page_body_2, sizeof(page_body_2));
pc.printf("get_buf[2] = %c \n", get_buf[2] );
if(get_buf[2] == '1'){
pc.printf("aceso \n");
myled = 1;
}else if(get_buf[2] == '0'){
pc.printf("apagado \n");
myled = 0;
}
pc.printf("printando get \n");
for(int i=0 ; i< j ; i++) {
pc.printf("%c",get_buf[i]);
}
pc.printf("\n");
}
pc.printf("\n Disconnected.\r\n");
}
}
}
Vá até o arquivo wiznet.h e descomente a linha “#define USE_W5100”, comente a linha “#define USE_W5200” e “#define USE_W5500”.
Agora vamos por partes: Preencha os parâmetros abaixo de acordo com sua rede, se você usa Windows você pode obter informações da sua rede com o comando “ipconfig” no CMD. Caso esteja no linux, você pode tentar “ip addr show”, dependendo da sua distribuição.
const char *IP_Addr = "192.168.XX.XX"; const char *IP_Subnet = "255.255.255.0"; const char *IP_Gateway = "192.168.XX.XX"
Nos vetores “page_XXXX” está a nossa página WEB. Eu separei em diversos vetores para facilitar, mas poderia estar sem problemas em apenas um vetor, porém isto dificulta a manutenção e o entendimento. O código original da página está abaixo, você pode salvá-lo em um “arquivo.htm” para abrir no seu browser.
<!doctype html>
<head>
<style type="text/css">
.margem_laranja{
width: 98%;
height: 40px;
background-color:#F5B317;
color: #FFFFFF;
}
.margem_cinza{
width: 98%;
height: 40px;
background-color:#6F6B5F;
color: #FFFFFF;
}
button{
font-family:verdana;
font-size:10pt;
background-color:#B0F0D2;
border: 50pt;
border-radius: 15px;
height:15pt;
width:50pt;
}
</style>
<title>Webserver</title>
<meta http-equiv="refresh" content="4">
<meta name="viewport" content="width=320">
<meta name="viewport" content="width=device-width">
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
</head>
<body bgcolor="#E0FFFF">
<center>
<div class="margem_cinza">
<a href="https://www.facebook.com/osembarcados"><img src="https://embarcados.com.br/wp-content/uploads/2018/11/footer-facebook.png" width=30 height=30/></a>
<a href="https://www.linkedin.com/company/embarcados"><img src="https://embarcados.com.br/wp-content/uploads/2018/11/logo-ln.png" width=30 height=30 /></a>
<a href="https://www.facebook.com/osembarcados"><img src="https://embarcados.com.br/wp-content/uploads/2018/11/footer-youtube.png" width=20 height=15/></a>
</div>
<a href="https://embarcados.com.br/"><img src="https://embarcados.com.br/wp-content/uploads/2016/04/logo-380x124.png"/></a>
<div class="margem_laranja"></div>
<font size="7" face="verdana" color="#2E2E2E">ARM Webserver </font>
<br /><br /><br />
<font size="5" face="verdana" color="black">Temperatura interna</font><br /><br />
<font size="7" face="verdana" color="black">°C</font><br /><br />
<font size="5" face="verdana" color="black">Led da placa</font><br /><br />
<form action="1" method="get">
<button type=submit style="width:200px;" id="bot" >Acender</button>
</form><br />
<form action="0" method="get">
<button type=submit style="width:200px;" id="bot" >Apagar</button>
</form><br /><br />
<font size="2" face="verdana" color="black">Webserver com STM32 Nucleo e ethernet shield W5100</font><br /><br />
<font size="2" face="verdana" color="black">Por: Muriel Costa</font><br />
<font size="2" face="verdana" color="black">Email: mrlcosta0@gmail.com</font><br />
<font size="2" face="verdana" color="black">Dont panic!</font><br />
</body>
</html>
Agora é só compilar e testar na sua placa!
Resultados
O que achou do artigo? Ficou com alguma dúvida a respeito do código? Deixe um comentário, seu feedback é muito importante pra mim!
Saiba mais
Curso mbed e FRDM KL46Z da NXP
Curso mbed e FRDM KL25Z da NXP
Aplicação da WEMOS D1 R1 como Webserver
Referências
TCP Headers with SYN and FIN Flags Set
How to create Simple Web Server with Mbed and W5100 Ethernet Shield

















Ótimo artigo, claro, abrangente e objetivo!
Muito obrigado Velrino!
Ficou muito bom, admiração por sempre procurar saber mais e repassar para os outros. Parabéns!
Muito obrigado!
Sempre buscando disseminar conhecimento
Artigo muito útil! Parabéns.
Valeu Gabriel!
Parabéns pelo artigo Muriel, muito bem escrito 🙂
Vi que para fazer webservers no Arduino, normalmente colocamos o HTML escrito no código, como você fez, daria pra deixar em arquivos separados? Talvez com algum macro pro compilador “colar” o conteúdo do HTML ali?
Valeu Rafael!
Esta página que está ao final é apenas para visualização. Eu também coloquei a página num array, dentro do main.
Grande abraço.