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

proautobot:
Bonjour,

Je commence par décortiquer ton code supercc. Il y plain de choses que je ne connais pas et qui m’empêche de comprendre. Aussi seriez vous m'orienter vers un cours sur le CRC abordable par un débutant. Jusqu'à présent j'ai trouvé des explications, des exemples mais je ne comprend pas.

Au niveau mathématique, pour ce que j'en sais, c'est à dire pas grand chose ;-), le CRC est le reste de la division des bits du message (qui pour les mathématiciens est un polynome binaire) par une suite de bits de petite longueur (8 pour un CRC8, 16 pour un CRC16, ...) (qui pour les mathématiciens est le polynome binaire générateur). Le CRC (reste de la division) à les propriétés recherchées : court, détecte avec une grande probabilité les erreurs, et est "relativement" simple à calculer par un processeur (la division est faite par enchainements de de ou exclusifs). Le choix du polynome générateur n'est pas trivial et est déterminé en fonction de de la longueur des messages, des longueurs des potentielles erreurs, ... Bref c'est vraiment un travail de "mathématiciens". Pourtant les informaticiens les utilisent partout (en réseaux, sur les DVD, ...). Si la page wikipedia en français est trop succincte regarde la page en anglais.

Quand j'ai constaté que j'avais des d'erreurs dans certaines trames (dues principalement à des vitesses de transmission trop élevées via la bibliothèque softwareSerial) j'ai décidé d'intégrer un CRC dans chacun de mes messages. Après quelques recherches sur le net je suis tombé sur le CRC8 proposé dans le lien indiqué et l'ai recopié tel quel sans chercher à comprendre dans le détail son fonctionnement exact (comment il faisait la division polynomial par enchainements de XOR et de AND). J'ai pris la fonction et l'ai considérée comme une boite "noire" : je lui donne une chaîne de caractère et elle me retourne son CRC.

Maintenant je vais tenter de répondre à tes questions qui sont plus liées à de la programmation.

byte j, crc = 0;

c'est un peu comme:

byte j = 0;
byte crc = 0 ;

Non, c'est plutôt comme :

byte j;
byte crc=0;

Si non le j n'est jamais remis à 0 lors de l'appel de la fonction GetCRC ?

Si, à chaque début de boucle "for (j = 0; j < 8; j++)"

D'ailleur La fonction c'est une static byte. Cela fait quoi ? Jusqu’à présent j'utilisais que des "void" quelque chose.

Là c'est parce que je voulais en faire une méthode de classe, au même titre que la méthode main qui elle aussi est static (static = méthode de classe). Je détaille plus si tu veux mais c'est plus un concept de programmation objet.

//////////////////////////////

CRC7_POLY = 0x91;

Ca veux dire quoi CRC7_POLY
Je ne connais 0x91 c'est un format, un nombre ?

CRC7_POLY est le nom de la variable mémorisant le polynome binaire générateur (d'où son nom)
0x91 est la valeur binaire des coefficients non nul du polynome générateur exprimé en base 16 (0x... est le préfixe des nombres exprimés en hexadécimal, valable aussi en C/C++/...).

/////////////////////////////

crc ^= (byte) message*;*
[
J'applique un "xor au byte message et j’attribue cette valeur au byte crc. Pour "i" = 1 je lit le byte 1 du message. J'ai soit 1 soit 0. Mais comment fonctionne ce xor,
d'habitude il y a un tableau de ce type:
S A B
0 0 0
1 1 0
1 0 1
0 1 1
La j'ai rien à comparer...
[/quote]
En fait, l'écriture "a op= b", en C#/C/C++/... est équivalente à "a = a op b". Donc en fait ici on fait : "crc = crc ^ (byte) message_". Le XOR est fait entre tous les bits de crc et tous les bits de l'octet message .
Exemple
*_</em></em> <em><em><em>*crc =     1001 1010 Xor byte[i] = 1100 0011 ==============          01011001*</em></em></em> <em><em>_*
> ///////////////////////////////
> if ((crc & 1) == 1)
>
> si ((crc et 1) sont égale à 1 )
>
> Pourquoi "& 1)" ?
& est l'opération "et binaire" (idem xor ci dessus). En fait permet ici de savoir si le bit de poids faible du crc vaut 1.
> ///////////////////////////////
>
> crc >>= 1;
>
> Je me décale de 1 vers la droite, oui mais il resemble a quoi mon CRC ?
> à ca 00000000 ?
> Donc je me décale la 0[0]00000 ?
Même explication que plus haut : crc >>= 1 est équivalent à crc = crc >> 1 et donc si crc vaut initialement 10101111 il deviendra 01010111 après.
> ///////////////////////////////
>
> A la suite tu créer une génération aléatoire de position. A moi de modifier cette partie pour piloter mes servos.
Oui, en fait c'était pour simuler différentes valeurs de moteurs.
> ///////////////////////////////
>
> Passage du CRC en Hexa
> Je croyais que ToString c'était une pour une chaîne de caractère.
>
> string crcHex = crc.ToString("X");
> if(crcHex.Length==1) crcHex="0"+crcHex;
>
> la chaîne de caractère crcHex = le byte crc transformé en String au format ("X")
> Je ne comprend pas pa le ("X").
Le format X permet d'obtenir la valeur hexadécimal. J'ai décidé d'envoyé mon crc dans le message sous la forme d'une valeur hexa sur 2 digits (puisque c'est un CRC8 -> 8bits -> 2 digits hex).
> Si la taille de crcHex est de 1 caractère, le crcHex est transformé à "0"+crcHex
> Mais ca donne "0" + "1 caractère" ?
Si crc est <16 alors sa représentation hexa ne contient qu'un digit or j'en veux 2 pour simplifier le travail de l'arduino. Je pense que crc.ToString("X2"); permet d'avoir directement le résultat sur 2 digits.
> ///////////////////////////
>
> msg=crcHex+" "+msg;
>
> Pourquoi tu met un espace, c'est pris en compte dans le calcule de CRC ?
En fait mon message avant cette ligne est une chaine de caractères contenant 2 nombres (les valeurs de M1 et de M2) genre "23 112"
Je veux préfixer mon message par le crcHex, 2 digits hexa pour obtenir le message final à envoyer. Si crcHex vaut "A8" :
"A8 23 112"
Ce message sera décodé sur l'arduino (cf. le programme arduino) :
if(sscanf(line, "%x %d %d", &crc, &val1, &val2) !=3) { ... }
> ///////////////////////////
>
> WriteLine(msg);
>
> C'est quoi la différence avec Write(msg) ?
Elle rajoute un retour à la ligne. Mon protocole est basé sur l'envoi de lignes terminées par un retour chariot ('\n').
> ////////////////////////////
>
>
> (on retire '\n' final). avec .TrimEnd(); ?
Oui, cf la doc de C#. Je te rappelle que c'est toi qui fait du C#, pas moi :wink:
> ////////////////////////////
>
> if(response != "0") {
> Console.WriteLine ("Erreur !");
> Environment.Exit(1);
> }
>
> Pourquoi on arrête le programme si il y a une erreur, c'est pas mieux de renvoyer le message au moins 3 fois ?
> C'est pour cette raison que ton code n'est pas dans "le standard" ?
Si c'est mieux de réessayer, j'ai juste voulu te donner un point de départ :wink:
> ///////////////////////////
>
> // pour une attente entre les messages
> //Thread.Sleep(500);
>
> Thread.Sleep(500); c'est un peu comme un delay ? j'ai pas cette bibliothèque sur unity.
> Je suis obligé d'utiliser des co-routines ou des Time.time ...
Oui, c'est comme un delay. Fait avec ce que tu as ou ne fait rien (les messages défileront à toute allure).
> Voilà, ça en fait un paquet de questions désolé. Mais ca m'aideras à aborder le CRC16 de hbachetti.
>
> Je suis dans le dure je croix =) à bientôt.
Bon courage pour la suite :wink:_