Opa, pessoal tudo belezinha? Depois de um tempo sem postar nada de Arduino com o Ethernet Shield e o foco saiu bastante com comunicação serial (USB CDC) agora vou postar como realizar a comunicação de um computador, servidor local ou remoto com um Arduino via Ethernet, nessa primeira parte vou mostrar a biblioteca que utilizei arduino_uip escrita por Norbert Truchsess baseado na Stack uIP de Adam Dunkels, porém neste caso esta biblioteca foi escrita especialmente para um ENC28J60 que é o que eu precisei e a uIP foi a base para eu construir a minha própria quando fiz minha monografia.
A biblioteca completa com exemplos pode ser adquirida no link abaixo:
https://github.com/ntruchsess/arduino_uip
Esta biblioteca possui suporte completo para aplicação cliente/servidor TCP e UDP além de recursos ARP, ICMP, DHCP e DNS, mas o foco deste post é UDP.
Acho que não tem segredo quanto baixar a biblioteca e copia no diretório libraries do Arduino tanto em Linux quanto em Windows, no caso estou usando Arduino IDE 1.0.5 e arduino_uip 1.0.1.
Nosso pequeno projeto consiste em baseado num IP fornecido iremos enviar a string “copa2014” eu pensei em “copa2014SQN” hehe mas “copa2014” ta em ritmo ainda :), então vamos lá…
#include <UIPEthernet.h> #define AGUARDE 5 EthernetUDP udp; //Criando o objeto udp da nossa librarie void setup() { Serial.begin(9600); // Meu MAC Address do Ethernet Shield uint8_t mac[6] = {0x00,0x11,0xAE,0xFF,0xA4,0x05}; // Meu IP do Ethernet Shield Ethernet.begin(mac,IPAddress(192,168,0,10)); } void loop() { int success; //Inicia a montagem do pacote para enviar ao host especificado // No caso 192.168.0.90 é o IP do meu servidor(destino) e 5005 é a porta UDP success = udp.beginPacket(IPAddress(192,168,0,90),5005); Serial.print("Init Packet: "); Serial.println(success); // Envia string "copa2014" via UDP success = udp.write("copa2014"); //success recebe o numero de bytes enviados Serial.print("bytes enviado: "); Serial.println(success); // Finaliza o pacote enviado, retorna 1 para sucesso e 0 para erro success = udp.endPacket(); Serial.print("End Packet: "); Serial.println(success); // Informa o IP Remoto Serial.print("IP Remoto: "); Serial.println(udp.remoteIP()); // Informa a Porta Remota Serial.print("Porta Remota: "); Serial.println(udp.remotePort()); // Encerra este socket udp.stop(); delay(AGUARDE*1000); //Aguarda 5s, altere AGUARDE pelo tempo em segundos }
Acho que ficou bem comentado e bem direto, temos o IP do Arduino e depois IP do servidor e a porta que você pode trocar ambos, agora vamos ver o código utilizado do lado do servidor.
#!/usr/bin/python import socket UDP_IP = "192.168.0.90" # IP do meu servidor UDP_PORT = 5005 # Aqui devo usar a mesma porta que coloquei no Arduino SIZE_PACKET=8 # Tamanho da string que o Arduino ira enviar sock = socket.socket(socket.AF_INET, # Internet socket.SOCK_DGRAM) # DGRAM é para UDP e para TCP seria SOCK_STREAM sock.bind((UDP_IP, UDP_PORT)) # Chamo o bind para associar a porta ao IP no meu sock print 'Iniciando UDP Server Arduino...' print 'IP: '+str(UDP_IP) print 'Porta: '+str(UDP_PORT) while True: data, addr = sock.recvfrom(SIZE_PACKET) """ Recebo o pacote de dados "copa2014" 8 bytes e o endereço """ print "" print "IP Arduino Remoto:", addr[0] print "Mensagem recebida:", data if len(data) == SIZE_PACKET: print "Pacote recebido!" else: print "Falha ao receber pacote!"
Salvei este código com o nome ArduinoUDPServer.py, no caso estou utilizando uma VM Linux e você deve setar a permissão +x (execução) para todos.
Agora vamos iniciar a aplicação Python e ver a saída:
cleiton@linuxVM:~/projetos/python/udp$ ./ArduinoUDPServer.py Iniciando UDP Server Arduino... IP: 192.168.0.90 Porta: 5005
Agora ligando o Arduino + EthernetShield já com o firmware gravado, vamos monitorar pelo Monitor Serial da própria IDE:
Init Packet: 1 bytes enviado: 8 End Packet: 1 IP Remoto: 192.168.0.90 Porta Remota: 5005 Init Packet: 1 bytes enviado: 8 End Packet: 1 IP Remoto: 192.168.0.90 Porta Remota: 5005
Após ligar o Arduino + Ethernet Shield vamos ver como esta nossa aplicação ArduinoUDPServer.py que ficara em um loop infinito:
cleiton@linuxVM:~/projetos/python/udp$ ./ArduinoUDPServer.py Iniciando UDP Server Arduino... IP: 192.168.0.90 Porta: 5005 IP remote: 192.168.0.10 received message: copa2014 Pacote recebido! IP remote: 192.168.0.10 received message: copa2014 Pacote recebido! IP remote: 192.168.0.10 received message: copa2014 Pacote recebido! IP remote: 192.168.0.10 received message: copa2014 Pacote recebido!
Hum, legal heim? Mas e se nosso programa em Python mostrar na tela Data/Hora de cada recebimento seria legal para acompanhar, vamos tentar?
#!/usr/bin/python import socket from datetime import datetime UDP_IP = "192.168.0.90" # IP do meu servidor UDP_PORT = 5005 # Aqui devo usar a mesma porta que coloquei no Arduino SIZE_PACKET=8 # Tamanho da string que o Arduino ira enviar sock = socket.socket(socket.AF_INET, # Internet socket.SOCK_DGRAM) # DGRAM é para UDP e para TCP serial SOCK_STREAM sock.bind((UDP_IP, UDP_PORT)) # Chamo o bind para associar a porta ao IP no meu sock print 'Iniciando UDP Server Arduino...' print 'IP: '+str(UDP_IP) print 'Porta: '+str(UDP_PORT) while True: # Pegando Data e hora hoje = datetime.now() dia = hoje.day mes = hoje.month ano = hoje.year hora = hoje.hour minuto = hoje.minute segundo = hoje.second data, addr = sock.recvfrom(SIZE_PACKET) """ Recebo o pacote de dados "copa2014" 8 bytes e o endereço """ print "" print dia,"/",mes,"/",ano," ",hora,":",minuto,":",segundo print "IP Arduino Remoto:", addr[0] print "Mensagem recebida:", data if len(data) == SIZE_PACKET: print "Pacote recebido!" else: print "Falha ao receber pacote!"
Vamos ver agora como fica a saída do nosso ArduinoUDPServer.py baseado no envio de 5 segundos que configuramos no Arduino:
cleiton@linuxVM:~/projetos/python/udp$ ./ArduinoUDPServer.py Iniciando UDP Server Arduino... IP: 192.168.0.90 Porta: 5005 29 / 5 / 2014 20 : 47 : 49 IP remote: 192.168.0.10 received message: copa2014 Pacote recebido! 29 / 5 / 2014 20 : 47 : 50 IP remote: 192.168.0.10 received message: copa2014 Pacote recebido! 29 / 5 / 2014 20 : 47 : 55 IP remote: 192.168.0.10 received message: copa2014 Pacote recebido! 29 / 5 / 2014 20 : 48 : 0 IP remote: 192.168.0.10 received message: copa2014 Pacote recebido! 29 / 5 / 2014 20 : 48 : 5 IP remote: 192.168.0.10 received message: copa2014 Pacote recebido!
Espero que tenham gostado e vamos aguardar o próximo!
Dica: Hum, usei Python em uma VM Linux, pensou em usar esta aplicação no RaspberryPI ou BeagleBone Black para comunicar? :)
Duvida ou problemas post nos comentários.
Até a próxima!
Referências
Norbert Truchsess
https://docs.python.org/2/library/socket.html
https://github.com/ntruchsess/arduino_uip
http://en.wikipedia.org/wiki/UIP_(micro_IP)
Arduino – Comunicação UDP Parte1 by Cleiton Bueno is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.