Étiquettes : , , ,

Nous allons voir dans ce tutoriel comment faire communiquer un Raspberry Pi et un ESP32 avec le protocole UDP. Lorsque des appareils sont connectés au même réseau Wifi, il peuvent communiquer très simplement en échangeant des paquets de données à l’aide du protocole UDP. Le Raspberry Pi et l’ESP32 ayant tous deux une connectivité Wifi embarqué, il est assez simple de mettre en place un protocole UDP entre les deux.

Dans cet exemple, le Raspberry Pi aura le rôle de serveur et l’ESP32 de client.

N.B.: Ce tutoriel est facilement transposable pour un ESP8266 (code client en bonus à la fin de l’article)

Matériel

  • Ordinateur
  • Raspberry Pi
  • NodeMCU ESP32 x1 ou plus (ou ESP8266)
  • Câble USB A Mâle/Micro B Mâle

Code Raspberry Pi Server

Pour communiquer à l’aide du protocole UDP, nous allons simplement créer le serveur udp qui pourra lire et écrire sur le port localPort. La librairie socket permet d »ouvrir une connexion entre deux appareils.

Le constructeur socket attend deux paramètres, la famille d’adresse (ici adresses internet) et le type de socket (ici UDP)

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

Le socket doit être lié un port de la machine sock.bind((hostname, localPort)). le fait de mettre un caractère vide à la place d’hostname (équivalent à 0.0.0.0) permet de lié le socket à toutes les interfaces locales.

#!/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.: La fonction get_ip_address() implémente une méthode pour obtenir l’adresse IP du Raspberry Pi en ouvrant un socket temporairement. Il est tout à fait possible d’utiliser la librairie os avec la commande ifconfig.

Notez l’adresse IP et le port du Raspberry Pi pour les copier dans le code client:

  • Adresse IP : 192.168.1.46
  • Port : 8888

Code ESP32 UDP Client

Dans le code client, nous allons nous connecter au serveur en utilisant l’adresse IP et le port précédemment notée (ici 192.168.1.46:8888)

N.B.: N’oubliez pas de modifier les valeurs de ssid et password afin que l’ESP32 se connecte au même réseau que le 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();
}

Résultat

Lorsque les deux cartes se connectent au Wifi, nous pouvons voir que des informations s’échangent entre les deux cartes. Il est alors possible de piloter un appareil connecté au client à partir du serveur ou inversement.

raspberrypi-esp32-server-result Communication UDP entre Raspberry Pi et ESP32
raspberrypi-esp32-client-result Communication UDP entre Raspberry Pi et ESP32

N.B.: Généralement, l’affectation des adresses IP se fait automatiquement. Comme les adresses sont définies en « dur » dans le code, il est préférable de configurer vos appareils afin qu’ils aient une adresse IP statique et non dynamique. Cela vous évitera d’avoir à modifier le code à chaque mise sous tension.

Bonus: Communication UDP entre Raspberry Pi et deux clients ESP32/ESP8266

Une fois la communication établie, il est possible de rajouter plusieurs clients. Dans cet exemple, nous rajoutons un client ESP8266

Code client UDP ESP8266

Il est facile de transformer le code pour ESP32 pour l’adapter à l’ESP8266 en modifiant le nom de la librairie Wifi. Nous modifions également la valeur du port 9696

N.B.: Lorsque vous rajoutez un client, veillez à ce qu’il ait un couple adresse/port unique.

#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();
}

Résultats

Nous pouvons voir que les adresses et les valeurs échangées par l’ESP32 et l’ESP8266 sont différentes.

raspberrypi-esp32-esp8266-server-result Communication UDP entre Raspberry Pi et ESP32
raspberrypi-esp8266-client-result Communication UDP entre Raspberry Pi et ESP32

Applications

  • Créer un réseau d’ordinateurs et/ou de microcontrôleurs pour gérer différents appareils ou capteurs

Sources