Communication Serial (usb) Unity3D <-> Arduino

Découvrez comment gérer la communication série entre Unity3D et Arduino en utilisant un script C# pour une lecture asynchrone. Tutoriel complet avec explications du code et configurations requises pour établir la connexion.

· 2 minutes de lecture
Communication Serial (usb) Unity3D <-> Arduino

Ce code Unity3D permet de gèrer la communication série de manière asynchrone, ce qui est important pour éviter de bloquer le thread principal d'Unity.

using UnityEngine;
using System.IO.Ports;
using System.Threading;
using System;

public class SerialCommunicationController : MonoBehaviour
{
    private SerialPort serialPort;
    private Thread serialThread;
    private bool isRunning = true;
    private string data;
    private readonly object dataLock = new object();

    // à changer celon vos paramettres
    private string portName = "COM8"; // Remplacez par votre port série
    private int baudRate = 9600; // Remplacez par votre port baudRate
    private int readTimeout = 5000; // Timeout de lecture en millisecondes

    void Start()
    {
        OpenSerialPort();
        serialThread = new Thread(ReadSerialData);
        serialThread.Start();
    }

    void Update()
    {
        lock (dataLock)
        {
            if (!string.IsNullOrEmpty(data))
            {
                // Vous pouvez traiter les données reçues ici
                data = string.Empty; // Réinitialiser la donnée après traitement
            }
        }
    }

    void OnApplicationQuit()
    {
        isRunning = false;
        
        if (serialThread != null && serialThread.IsAlive)
        {
            serialThread.Join(); // Attendre que le thread se termine
        }
        
        CloseSerialPort();
    }

    private void OpenSerialPort()
    {
        serialPort = new SerialPort(portName, baudRate)
        {
            ReadTimeout = readTimeout
        };
        
        serialPort.RtsEnable = true;
        serialPort.DtrEnable = true;

        try
        {
            serialPort.Open();
            Debug.Log("Serial port opened: " + portName);
        }
        catch (System.Exception ex)
        {
            Debug.LogError("Error opening serial port: " + ex.Message);
        }
    }

    private void CloseSerialPort()
    {
        if (serialPort.IsOpen)
        {
            serialPort.Close();
            Debug.Log("Serial port closed: " + portName);
        }
    }

    private void ReadSerialData()
    {
        while (isRunning)
        {
            if (serialPort.IsOpen)
            {
                try
                {
                    string incomingData = serialPort.ReadLine(); // Utiliser ReadLine pour lire une ligne complète
                    if (!string.IsNullOrEmpty(incomingData))
                    {
                        lock (dataLock)
                        {
                            data = incomingData;
                        }
                    }
                }
                catch (TimeoutException)
                {
                    // Timeout de lecture atteint, continuer la boucle
                    Debug.LogWarning("Serial read timeout");
                }
                catch (System.Exception ex)
                {
                    Debug.LogError("Error reading from serial port: " + ex.Message);
                }
            }
            Thread.Sleep(100); // Attendre un court moment avant de lire à nouveau pour éviter une surcharge du CPU
        }
    }
}

Important : Pour utiliser les ports série, configurez Unity comme suit :

  1. Allez dans Edit -> Project Settings -> Player -> Other Settings
  2. Sous "Api Compatibility Level", sélectionnez ".NET Framework"

Cette étape est importante, sinon la librarie permettant d'accéder aux ports ne sera pas possible.

Arduino

Dans ce code, nous envoyons via le port série une valeur booléenne, représentée par '1' ou '0', toutes les secondes.

const int LED_PIN = 13;  // Utilisez la LED intégrée sur la plupart des cartes Arduino
bool state = false;

void setup() {
  Serial.begin(9600);  // Initialise la communication série à 9600 bauds
  pinMode(LED_PIN, OUTPUT);
}

void loop() {
  // Inverse l'état du booléen
  state = !state;
  
  // Envoie l'état actuel via le port série
  if (state) {
    Serial.println("1");
  } else {
    Serial.println("0");
  }
  
  // Allume ou éteint la LED en fonction de l'état
  digitalWrite(LED_PIN, state);
  
  // Attend une seconde avant la prochaine itération
  delay(1000);
}

Mise en marche :

Suivez ces étapes pour établir la communication entre Unity3D et Arduino :

  1. Téléversez le code Arduino sur votre carte.
  2. Connectez l'Arduino à votre ordinateur via un câble USB.
  3. Vérifiez que l'Arduino est reconnu par votre système (vous devriez voir un nouveau port COM apparaître).
  4. Configuration de Unity3D
    • Ouvrez votre projet Unity3D.
    • Assurez-vous que le script SerialCommunicationController.cs est présent dans votre projet.
    • Dans la hiérarchie de votre scène, sélectionnez un GameObject existant ou créez-en un nouveau.
    • Ajoutez le composant SerialCommunicationController à ce GameObject en le faisant glisser depuis le dossier des scripts ou en utilisant "Add Component" dans l'inspecteur.
  5. Vérification finale et exécution
    • Vérifiez que le port série et le baud rate dans le script Unity correspondent à ceux de votre Arduino.
    • Lancez le mode Play dans Unity.