fbpixel
Etiquetas: , , ,

Neste tutorial, veremos como fazer com que um Raspberry Pi e um ESP32 se comuniquem usando o protocolo UDP. Quando os dispositivos estão ligados à mesma rede WiFi, podem comunicar de forma muito simples através da troca de pacotes de dados utilizando o protocolo UDP. Como tanto o Raspberry Pi quanto o ESP32 têm conetividade WiFi integrada, é bastante simples configurar um protocolo UDP entre os dois.

Neste exemplo, o Raspberry Pi actuará como servidor e o ESP32 como cliente.

N.B.: Este tutorial pode ser facilmente transposto para um ESP8266 (código de cliente bónus no final do artigo).

Hardware

  • Computador
  • Raspberry Pi
  • NodeMCU ESP32 x1 ou superior (ou ESP8266)
  • Cabo USB A macho

Código do servidor Raspberry Pi

Para comunicar utilizando o protocolo UDP, vamos simplesmente criar o servidor udp, que será capaz de ler e escrever na porta localPort. A biblioteca socket é utilizada para abrir uma ligação entre dois dispositivos.

O construtor do socket espera dois parâmetros, a família de endereços (neste caso, endereços Internet) e o tipo de socket (neste caso, UDP).

sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) ## Internet,UDP

O socket deve ser ligado a uma porta na máquina sock.bind((hostname, localPort)) Colocar um carácter vazio no lugar do hostname (equivalente a 0.0.0.0) permite que o socket seja ligado a todas as interfaces locais.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

#Libraries
import socket	#https://wiki.python.org/moin/UdpCommunication

#Parameters
localPort=8888
bufferSize=1024

#Objects
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)  ## Internet,UDP

# function init 
def init():
	sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
	sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) #enable broadcasting mode
	sock.bind(('', localPort))
	print("UDP server : {}:{}".format(get_ip_address(),localPort))

# function main 
def main():
	while True:
		data, addr = sock.recvfrom(1024) # get data
		print("received message: {} from {}\n".format(data,addr))
    
		sock.sendto("RPi received OK",addr)  # write data
  

# function get_ip_address 
def get_ip_address():
	"""get host ip address"""
	ip_address = '';
	s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
	s.connect(("8.8.8.8",80))
	ip_address = s.getsockname()[0]
	s.close()
	return ip_address




if __name__ == '__main__':
	init()
	main()

N.B.: A função get_ip_address() implementa um método para obter o endereço IP do Raspberry Pi abrindo um socket temporariamente. Também é possível usar a biblioteca os com o comando ifconfig.

Anote o endereço IP e a porta do Raspberry Pi para que possa copiá-los para o código do cliente:

  • Endereço IP: 192.168.1.46
  • Número do porto: 8888

Código do cliente UDP do ESP32

No código do cliente, vamos ligar-nos ao servidor utilizando o endereço IP e a porta anteriormente indicados (neste caso, 192.168.1.46:8888).

Nota: Não se esqueça de alterar os valores ssid e password para que o ESP32 se ligue à mesma rede que o Raspberry Pi.

#include <WiFi.h>
#include <WiFiUdp.h>
WiFiUDP udp;

char packetBuffer[255];
unsigned int localPort = 9999;
char *serverip = "192.168.1.46";
unsigned int serverport = 8888;

const char *ssid = "******";
const char *password = "********";

void setup() {
  Serial.begin(115200);
  // Connect to Wifi network.
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500); Serial.print(F("."));
  }
  udp.begin(localPort);
  Serial.printf("UDP Client : %s:%i \n", WiFi.localIP().toString().c_str(), localPort);
}

void loop() {
  int packetSize = udp.parsePacket();
  if (packetSize) {
    Serial.print(" Received packet from : "); Serial.println(udp.remoteIP());
    int len = udp.read(packetBuffer, 255);
    Serial.printf("Data : %s\n", packetBuffer);
    Serial.println();
  }
  delay(500);
  Serial.print("[Client Connected] "); Serial.println(WiFi.localIP());
  udp.beginPacket(serverip, serverport);
  char buf[30];
  unsigned long testID = millis();
  sprintf(buf, "ESP32 send millis: %lu", testID);
  udp.printf(buf);
  udp.endPacket();
}

Resultados

Quando as duas placas se ligam ao WiFi, podemos ver que há uma troca de informações entre as duas placas. É então possível controlar um dispositivo ligado ao cliente a partir do servidor ou vice-versa.

raspberrypi-esp32-server-result Comunicação UDP entre o Raspberry Pi e o ESP32
raspberrypi-esp32-client-result Comunicação UDP entre o Raspberry Pi e o ESP32

N.B.: Os endereços IP são geralmente atribuídos automaticamente. Como os endereços são definidos de forma “rígida” no código, é preferível configurar os seus dispositivos de modo a que tenham um endereço IP estático e não dinâmico. Deste modo, não é necessário modificar o código de cada vez que o aparelho é ligado.

Bónus: Comunicação UDP entre o Raspberry Pi e dois clientes ESP32

Uma vez estabelecida a comunicação, é possível adicionar vários clientes. Neste exemplo, adicionamos um cliente ESP8266

Código de cliente UDP ESP8266

É fácil transformar o código do ESP32 para o adaptar ao ESP8266, modificando o nome da biblioteca Wifi. Também alteramos o valor da porta 9696

Nota: Quando adicionar um cliente, certifique-se de que este tem um emparelhamento de endereços de

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
WiFiUDP udp;

char packetBuffer[255];
unsigned int localPort = 9696;
char *serverip = "192.168.1.46";
unsigned int serverport = 8888;

const char *ssid = "******";
const char *password = "******";


void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500); Serial.print(F("."));
  }
  udp.begin(localPort);
  Serial.printf("UDP Client : %s:%i \n", WiFi.localIP().toString().c_str(), localPort);
}


void loop() {
  int packetSize = udp.parsePacket();
  if (packetSize) {
    Serial.print(" Received packet from : "); Serial.println(udp.remoteIP());
    int len = udp.read(packetBuffer, 255);
    Serial.printf("Data : %s\n", packetBuffer);
    Serial.println();
  }
  delay(500);
  Serial.print("[Client Connected] "); Serial.println(WiFi.localIP());
  udp.beginPacket(serverip, serverport);
  char buf[30];
  unsigned long testID = millis();
  sprintf(buf, "ESP8266 send millis: %lu", testID);
  udp.printf(buf);
  udp.endPacket();
}

Resultadoss

Podemos ver que os endereços e os valores trocados pelo ESP32 e pelo ESP8266 são diferentes.

raspberrypi-esp32-esp8266-server-result Comunicação UDP entre o Raspberry Pi e o ESP32
raspberrypi-esp8266-client-result Comunicação UDP entre o Raspberry Pi e o ESP32

Aplicações

  • Crear una red de ordenadores y/o microcontroladores para gestionar diferentes dispositivos o sensores.

Fontes