Unity3D, Port-série, Arduino : comment augmenter la rapidité de transmission.

Je poste un exemple modifié de ce que j'utilise. Par curiosité j'ai fait le code C# (en mono sous GNU/Linux). Désolé s'il ne répond pas aux standards (je ne développe pas en C#). Tu devras adapter pour Windows le nom du port série.

Ce code est adapté, je pense, à ton problème (ligne au format "val1 val2" pour les valeurs des 2 moteurs).

Je sécurise par un CRC8 (plus léger pour l'arduino) et un accusé de réception indiquant l'éventuel problème.

A la vitesse de 115200 bauds le programme est capable d'émettre (et de recevoir l’acquittement) de 500 couples de valeurs (lignes) par seconde.

Le programme C# :

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

/*
   Émission en boucle (1000) de lignes contenant 2 entiers.

   Un CRC8 est ajouté en début de ligne pour validation par le récepteur.

   Le récepteur renvoie :

 * "0" : ok
 * "1" : mauvais format de ligne.
 * "2" : mauvais CRC

 Arrêt du programme si erreur détectée.
*/

public class TestUsb {

 // from pololu.com (https://www.pololu.com/docs/0J44/6.7.6)

 static byte GetCRC(String message) {
 byte j, crc = 0;
 const byte CRC7_POLY = 0x91;
 int i;

 int length=message.Length;

 for (i = 0; i < length; i++)
 {
 crc ^= (byte) message[i];

 for (j = 0; j < 8; j++)
 {
 if ((crc & 1) == 1)
 crc ^= CRC7_POLY;
 crc >>= 1;
 }
 }
 return crc;
 }

 static public void Main ()
 {

 Random rnd = new Random();

 SerialPort serial;
 serial = new SerialPort();

 serial.PortName = "/dev/ttyUSB0";
 serial.Parity = Parity.None;
 serial.BaudRate = 115200;
 serial.DataBits = 8;
 serial.StopBits = StopBits.One;
 serial.Open ();

 // Pour laisser le temps à la carte arduino de rebooter

 Console.WriteLine ("Wait arduino reboot (2s) ...");
 Thread.Sleep(2000); 

 // On émet (à fond) 1000 couples (m1 m2)

 for(int i=0; i<1000; ++i) { 

 int m1=rnd.Next(0,255);
 int m2=rnd.Next(0,255);

 string msg=m1+" "+m2;

 // Calcul du CRC 8

 byte crc=GetCRC(msg);


 // falsifie le CRC pour test détection mauvais crc
 // crc++;

 // falsifie le message pour détection mauvais format
 //msg="123 bad";


 // CRC en hexa sur 2 octets (simplification du code coté arduino)
 string crcHex = crc.ToString("X");
 if(crcHex.Length==1) crcHex="0"+crcHex;

 // Ajout du CRC en début de message
 msg=crcHex+" "+msg;

 Console.WriteLine ("Envoi : \""+msg+"\"");

 // envoi 
 serial.WriteLine(msg);

 // attente de la réponse (on retire '\n' final).
 string response=serial.ReadLine().TrimEnd();

 // Affichage de la réponse 
 Console.WriteLine ("Recu ("+i+") : \""+response+"\"");

 if(response != "0") {
 Console.WriteLine ("Erreur !");
 Environment.Exit(1);
 } 

 // pour une attente entre les messages
 //Thread.Sleep(500);
 }
 serial.Close ();
 }
}

Le programme Arduino :

/*
Lecture en boucle sur le port série de lignes ASCII au format :

CRC8 VAL1 VAL2

  * CRC8 la représentation ASCII en hexadécimal sur 2 caractères du CRC 8
    de "VAL1 VAL2".
  * VALn la représentation ASCII d'un entier.

A l'issue d'une lecture, un code de retour est émis sur le port série :

  * "0" : ok
  * "1" : mauvais format de ligne.
  * "2" : mauvais CRC
*/

const int maxChars=20; // nombre de caractères maxi d'une ligne

// CRC8 from pololu.com (https://www.pololu.com/docs/0J44/6.7.6)

const unsigned char CRC7_POLY = 0x91;

unsigned char getCRC(char *message, int length)
{
    unsigned char i, j, crc = 0;

    for (i = 0; i < length; i++)
    {
        crc ^= message[i];
        for (j = 0; j < 8; j++)
        {
            if (crc & 1)
                crc ^= CRC7_POLY;
            crc >>= 1;
        }
    }
    return crc;
}


// Fonction fgets inspirée de la version POSIX.
// Évite de manipuler des String (fragmentation du tas).

char *fgets(char *s, int size, Stream &stream) {
    int cpt=0;
    char c;

    while(1) {
        if(stream.available()) {
            c = stream.read();
            if(c=='\r') continue; // skip Windows \r
 if(cpt<size-1) s[cpt++]=c;
            if(c=='\n') break ;
        }
    }
 s[cpt]=0;
    return s;
}

// Initialisation du port série

void setup() {
    Serial.begin(115200);
    while (!Serial);
}

// lecture en boucle des lignes

void loop() {
 char line[maxChars]; // espace pour stocker la ligne lue
 int val1, val2, crc, crc2;

 // Lecture (bloquante) d'une ligne en provenance du port série
 fgets(line, maxChars, Serial);

 // retire l'\n' final

 line[strlen(line)-1]=0;

 // décodage de la ligne reçue

 if(sscanf(line, "%x %d %d", &crc, &val1, &val2) !=3) {
 // renvoie "1" : ligne au format invalide
 Serial.println("1");
 return;
 }
 else { 
 // vérification du CRC (+3 car le CRC ne s'applique qu'aux données 
 // utiles)

 crc2=getCRC(line+3, strlen(line+3));
 if(crc!=crc2) {
 // renvoie "2" : mauvais CRC
 Serial.println(2);
 return;
 }
 else {
 // renvoie "0" : tout est ok
 Serial.println(0);  
 }
 }

 // arrivé à ce point du programme il y a une forte probabilité que 
 // val1 et val2 soient valides.

 // ...
}

Tu en fait ce que tu veux, mais méfie toi, je ne garanti pas qu'il est exempt d'erreurs de codage.

Sinon oui, sous GNU/Linux la carte reboot aussi à l'ouverture du port série par défaut en C#. J'évite cela sous GNU/Linux en C en fixant des valeurs précises de configuration via la commande stty. Si cela te dérange il faudra que tu te renseignes pour C# sous Windows.

PS 1 : désolé pour l'indentation qui disparaît a la moindre édition du post...?!?

PS 2 : je n'ai pas testé sous Windows (mais ai pris en compte, normalement, la terminaison de ligne différente par rapport à GNU/Linux).

A+