SE5 ECEAI/eceai 2024/2025/duhr-becquet

De wiki-se.plil.fr
Aller à la navigation Aller à la recherche

Séance 1 :

Idée : voir si une main est ouverte ou fermée en étudiant le mouvement des doigts qui se ferment ou s'ouvrent.


Séance 2:

Installation de RaspberryPi OS basé sur Debian bookworm sur notre raspberry PI avec une première connection par UART

On a configuré l'access point afin de pouvoir accéder à nos raspberryPi dans le réseau 172.26.0.0.

Introduction

Dans ce module ECEAI, il nous est demandé de résilier un petit montage IoT permettant la communication entre un capteur, une gateway et un serveur cloud. De plus et c'est tout l'intérêt du module nous allons implémenter de l'intelligence artificielle à différents niveaux de la chaîne et récolter les consommations électriques pour les différentes configurations. Nous pourrons ainsi appréhender la notion de Edge Computing.

Configuration de la partie capteur Nucleo

Pour notre projet nous souhaitons récupérer les données du capteur X-NUCLEO-53L5A1. Pour cela nous utilisons l'utilitaire de stMicroelectronics nommé NanoEdge-AI-Studio. Grâce à la séction Data Logger du logiciel nous créons un fichier binaire permettant la transmission des données de la manière suivante:

- Data Rate(HZ) = 15

- Frame resolution = 64

- Frames = 32

Il suiffit ensuite de téléverser ce fichier binaire sur la Board NUCLEO-F401RE

Configuration de la RaspberryPi

Premier accès et connexion au réseau

Après avoir téléchargé un OS pour la RaspberryPI basé sur un debian bookworm, Nous montons sur notre station de travail la carte SD contenant cet OS. Il faut maintenant effectuer quelques modifications dans les fichiers de configuration afin d'avoir accès à la Raspberry par liaison série. Il suffit ensuite d'utiliser l'utilitaire minicom et de connecter la raspberry à l'AP (access point) pour pouvoir accèder à cette dernière en ssh.

ssh root@172.26.145.205

Réception des données serial

La partie capteur "bombarde" de données sur la liaison série. Nous développons alors dans un premier temps un petit programme python qui récupère ces données sur la liaison série et les affiche dans le terminal. Par la suite ces données seront transmise aux différents niveaux de l'infrastructure en charge du traitement de ces dernières.

import serial
import time

# Paramètres de la connexion série
port = "/dev/ttyACM0" 
baudrate = 115200 

try:
    # Initialiser la connexion série
    ser = serial.Serial(port, baudrate, timeout=1)

    # Délai pour s'assurer que la connexion est bien établie
    time.sleep(2)
    print(f"Connexion établie sur {port} à {baudrate} bauds")

    # Boucle pour lire les données entrantes
    while True:
        if ser.in_waiting > 0:
            data = ser.readline().decode('utf-8').rstrip() 
            print(f"Reçu: {data}")

except serial.serialutil.SerialException as e:
    print(f"Erreur: Impossible d'établir la connexion sur {port}. Détails: {e}")

finally:
    if 'ser' in locals() and ser.is_open:
        ser.close()  # Fermer la connexion série
        print("Connexion fermée.")

Communication Gateway -> Cloud

Dans cette section nous cherchons à faire communiquer la RaspberryPI 4 (gateway) et la VM SE5-duhrbecquet (cloud).

Pour cela nous choisissons d'utiliser un protocole de communication nommé MQTT:


Plus connu sous l’acronyme MQTT, le protocole Message Queuing Telemetry Transport est un protocole de messagerie léger adapté aux situations où les clients doivent utiliser peu de code et sont connectés à des réseaux peu fiables ou limités en bande passante. Il est principalement utilisé dans la communication entre machines (M2M) ou sur les types de connexions propres à l’Internet des Objets.

https://www.paessler.com/fr/it-explained/mqtt

Nous devons donc développer 2 codes:

- Un code qui pour reprendre les termes de mosquitto publie les données sur le topic Data_Stm.

- Un code qui reçoit ces données en s'abonnant au topic Data_Stm que nous pourrons déployer sur la raspberry ou la vm pour traiter les données sur l'un ou l'autre.

Premier code:

import serial
import time
import paho.mqtt.client as mqtt

# Paramètres de la connexion série
port = "/dev/ttyACM0"
baudrate = 115200

# Paramètres MQTT
mqtt_broker = "172.26.145.105"
mqtt_port = 1883
mqtt_pub_topic = "Data_Stm"

# Fonction pour se connecter au broker MQTT
def on_connect(client, userdata, flags, rc):
    if rc == 0:
        print("Connecté au broker MQTT")
    else:
        print(f"Erreur de connexion au broker MQTT. Code: {rc}")

# Initialiser le client MQTT
mqtt_client = mqtt.Client()
mqtt_client.on_connect = on_connect

# Connexion au broker MQTT
mqtt_client.connect(mqtt_broker, mqtt_port, 60)

# Boucle MQTT (en arrière-plan)
mqtt_client.loop_start()

try:
    # Initialiser la connexion série
    ser = serial.Serial(port, baudrate, timeout=1)

    # Délai pour s'assurer que la connexion est bien établie
    time.sleep(2)
    print(f"Connexion UART établie sur {port} à {baudrate} bauds")

    # Boucle pour lire les données et les publier sur MQTT
    while True:
        if ser.in_waiting > 0:
            # Lire les données reçues via l'UART
            data = ser.readline().rstrip()  # Lecture des données

            if data:  # Si des données sont reçues
                print(f"Reçu: {data}")
                mqtt_client.publish(mqtt_pub_topic, data)
                print(f"Données publiées sur MQTT : {mqtt_pub_topic} -> {data}")

except serial.serialutil.SerialException as e:
    print(f"Erreur: Impossible d'établir la connexion sur {port}. Détails: {e}")

finally:
    if 'ser' in locals() and ser.is_open:
        ser.close()  # Fermer la connexion série
        print("Connexion UART fermée.")

    # Arrêter la boucle MQTT
    mqtt_client.loop_stop()
    mqtt_client.disconnect()
    print("Déconnecté du broker MQTT.")

Second code:

import paho.mqtt.client as mqtt

ADDR="172.26.145.105"
PORT=1883
TOPIC="Data_Stm"

# Callback lors de la connexion au broker MQTT
def on_connect(client, userdata, flags, rc):
    print("Connecté avec le code de résultat: " + str(rc))
    client.subscribe(TOPIC)

# Callback lorsqu'un message est reçu sur le topic abonné
def on_message(client, userdata, msg):
    print(msg.payload.decode());

# Initialisation du client MQTT
client = mqtt.Client()

# Attribution des callbacks
client.on_connect = on_connect
client.on_message = on_message

client.connect(ADDR, PORT, 60)

# Boucle pour maintenir la connexion et recevoir les messages
client.loop_forever()

Configuration de la VM

Nous utiliserons xen pour la création et la gestion de notre VM. Une fois correctement configuré et lancé nous pouvons installer nos premiers services.

Nous souhaitons mettre en place le service mosquitto qui permet d'héberger un serveur mqtt. Nous le configurons pour fonctionner sur le port 1883.

Nous avons donc:

- Host : 172.26.145.105

- Port : 1883

Nous pouvons tester ce serveur MQTT en installant le bon utilitaire et en utilisant les commandes suivantes.


Terminal 1 :

mosquitto_sub -h 172.26.145.105 -p 1883 -t test

Terminal 2 :

mosquitto_pub -h 172.26.145.105 -p 1883 -t test -m "J'adore le réseau"


Génération du modèle IA

Le firmware a été généré à partir du logiciel NanoEdge AI Studio, puis téléverser sur la nucleo.

Nous avons démarrer un projet "reconnaissance de N-class" et avons choisi de travailler sur le jeux pierre feuille cisaux afin de travailler sur les 4 classes suivantes : Rock, Paper, Scissor et Rien.

La classe Rien correspond simplement au moment ou aucune main n'est détectée.

Nous faisons ainsi nos classes et lançons le benchmark sur Nanoedge.


Après plusieurs tentatives, plusieurs benchmarks sur plusieurs datasets. nous avons un modèle qui reconnait à 91% les mains proposées.

Vous remarquez tout de même sur la vidéo que les transitions s'apparente à des classe "Rock".

Résultats Modèle

Déploiement du modèle

En utilisant le logiciel nanoedgeAI et en le personnalisant. Nous arrivons à faire tourner le modèle sur la carte nucléo.