Arduino – Comunicação UDP Parte1

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)

Share Button

CC BY-NC-SA 4.0 Arduino – Comunicação UDP Parte1 by Cleiton Bueno is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.