26

Re : Mixage de voies et liaisons I²C entre carte Arduino

Est-ce que le soft fourni par Arduino permet de faire cela ?

Oui

Est-ce que je peux avor un peu d'aide pour constituer le code directement sous avr ?

Je peux t'envoyer le code qui tourne sur la radeau

Vaut-il pas mieux que je développe une lib afin de faire profiter mes deux cartes, vue que je fais du bi-directionnel ?

Tu peux détailler (sur le plan technique) ce que sont tes deux cartes. Arduino, carte maison,... ?

Pour ce qui est de la lib, pas la peine de se précipiter à créer la n+1ème : il existe déjà pas mal de choses. Par exemple Procyon avrlib (http://www.procyonengineering.com/embedded/avr/avrlib/) est un peu ancien et n'évolue pas bcp, mais ça marche très bien. J'en ai utilisé des bouts pour le radeau.
Il y a aussi des choses intéressantes ici (http://webbot.org.uk/iPoint/ipoint) et notamment un designer de projet qui en fonction des cartes, des périphériques et d'un tas de clics et de dialogues génère le code source de base d'un projet AVR.

Start bit / Type / Lenght / Data(s) / CR16 / Stop Bit

Attention il ne s'agit pas de start bit et de stop bit, qui sont des bits de longueur particulière utilisés pour faire la signalisation d'une com série, mais de bytes de start et byte de stop, qui sont des marqueurs de trame (qu'on choisit comme on veut). D'ailleurs, si tu as la longueur du message dans tes trames, tu n'a pas besoin de stop byte.

J'ai pas trouvé d'exemple de CR16, je veux bien un coup de main la dessus.

Très étonné je suis que tu n'aies pas trouvé cela via Google, car c'est hyper répandu. Je crois même qu'Avrlib contient une routine pour cela.

Est-ce que je met tout en brut 0x000x000x01CR160x01 ou bien 0x00,0x00,0x01,CR16,0x01 ou bien 0x00 pause 0x00 pause 0x01 pause CR16 pause 0x01 ?

Je ne comprends pas ta question.

27

Re : Mixage de voies et liaisons I²C entre carte Arduino

Mes cartes sont des Arduino.
Une Arduino Méga pour la commande.
Une Arduino Uno pour le sous-marin.
Entre les deux une liaison série toute bête.

Ok, donc si pas besoin de Start et Stop si il y a un cr16 alrs ca sera Lenght/data/data/cr16.

Alors pour la question que tu n'a pas compris. Je n'arrive pas à savoir comment sera réellement la trame. Si les octets se suivent sans parsing ou pas. En gros s'il faut un caractère, un espace ou un temps entre chaque octets.

Bon ben, comme d'ab, à défaut d'avoir la science infuse, j'infuse la science wink

28

Re : Mixage de voies et liaisons I²C entre carte Arduino

Ok, donc si pas besoin de Start et Stop si il y a un cr16 alrs ca sera Lenght/data/data/cr16.

Je n'ai pas dit qu'il n'y a pas besoin de start, mais de stop (du fait de la présence de la longueur). Le start est nécessaire pour se recaler à coup sûr. Choisir par conséquent une séquence (le start peut occuper plusieurs bytes) qui ne peut pas apparaître dans les données (ou s'arranger pour encoder les données de manière à ne jamais avoir quelque chose d'identique au start).

Alors pour la question que tu n'a pas compris. Je n'arrive pas à savoir comment sera réellement la trame. Si les octets se suivent sans parsing ou pas. En gros s'il faut un caractère, un espace ou un temps entre chaque octets.

Les octets se suivent directement, et il n'y a pas de parsing à faire. On se contente de lire les octets au fur et à mesure et de les stocker ou interpréter selon le cas.

29 Dernière modification par Microbulle (12-04-2012 11:03)

Re : Mixage de voies et liaisons I²C entre carte Arduino

Ah wai, donc en fait, c'est beaucoup plus simple que je ne le pensait.

Ne jamais prendre un start qui est utilisé par les octets data. Là, ça me semble difficile car n'importe quel data, donc ocet peut avoir une valeurs comprise entre 0x00 et 0xFF. En revanche, si le start, on sait que c'est un start alors, ça ne pose plus de problème. Je vais parlé d’expérience sur I2C. Le start est un gront montant d'un temps déterminé invariable. Il est généralement plus long que les bits de la trames. Je propose quelque-chose de similaire. Le start serait toujours un 0x00. Il ne peut-être suivi que par un type compris entre 0x01 et 0xFF. On a bien un start unique si je procède ainsi.

Mise à jour du protocole:

Trame : (Start bit / Type / Lenght / Data(s) / CR16).

Type :
0x10 -> Entrée tout ou rien sur 1 data (0x00 = 0v / 0x01 = 5v)
0x11 -> Sortie tout ou rien sur 1 data (0x00 = Éteint / 0x01 = Allumer)
0x12 -> PWM sur 2 data (Data1 = temps du front haut et Data2 = total du créneau)
0x13 -> Servo ou Variateur (PWM sur 20ms) 1 Data ici on donnera un angle de 0 à 180°. 90° étant la position centrale. Un data pouvant envoyé de 0 à 255, 0 à 180 rentre dedans. plus besoin de décaler quoi que ce soit.
0x14 -> Urgence (Ce cas prendra 1 bit et est nécessaire au retour si une avarie ou une grave anomalie est détecter) 0x00 = RAS / 0x11 = Urgence
Lenght:
0x01 = 1 data
0x02 = 2 data
...
0x10 = 10 data

Comme on peut le remarqué le type à pris un chiffre supplémentaire afin de le différentier avec le 0x00 du start.

Trame type pour piloter un servo 1 basé sur la trame donné dessus: 0x00 0x13 0x02 0x05 0x03 0x2F (Sans espaces bien entenu).

Celà me semble faisable désormais. Un seul point toujours pas trouvé, c'est le CR16. Quand je demande programmation CR16 j'ai des résultat très moyen parlant de tout sauf du chechsum roll

Bon ben, comme d'ab, à défaut d'avoir la science infuse, j'infuse la science wink

30

Re : Mixage de voies et liaisons I²C entre carte Arduino

Je vais parlé d’expérience sur I2C. Le start est un gront montant d'un temps déterminé invariable.

On ne peut pas comparer I2C et comm série asynchrone car I2C est... synchrone par définition : tout est cadencé par le signal de clock, et le protocole est donc géré au niveau hardware. C'est comme lorsqu'on utilise les signaux de handshake d'une comm série (RTS, CTS, DTR,...), ce qui se pratique très rarement. Ici nous utilisons une communication asynchrone, dont la signalisation est incluse dans le flux de données (c'est le rôle du protocole), et non pas assurée par une signalisation externe.

Pour ce qui est de la différenciation du start (en comm asynchrone), il y a plusieurs stratégies. Par exemple :
- n'utiliser que 7 bits au niveau des bytes de data, et réserver 0xFF au start. Ca oblige à une petite gymnastique pour encode/décoder les bytes de data, mais rien de bien méchant (du masque et du shift en gros)
- coder les start sur 2 octets consécutifs (ex: 0xFFFF) et faire en sorte qu'on ne puisse jamais avoir cette configuration dans les data (ex: se limiter à des valeurs  entières sur 2 octets avec le bit de poids fort toujours à 0, limiter les boolean fields à 7 positions par octet ou 15 positions par short int, ...)

Celà me semble faisable désormais. Un seul point toujours pas trouvé, c'est le CR16

http://www.ccsinfo.com/forum/viewtopic.php?t=24977
C'est le 3ème hit sur un Google("crc16 algorithm")

Quand je demande programmation CR16 j'ai des résultat très moyen parlant de tout sauf du chechsum

Il est certain que si on utilise des requêtes en Français on diminue très sérieusement ses chances de résultat hmm Qu'on aime ou pas, la langue de l'informatique est l'Anglais avant tout. Il faut s'en faire une raison.

De plus tu semble avoir utilisé "CR16" dans ta requête, ce qui est erroné comme acronyme puisque c'est "CRC16", qui signifie "Cyclic Redundancy Check 16 bits"

31

Re : Mixage de voies et liaisons I²C entre carte Arduino

Punaise, je comprend plus rien !

Un coup on travaille octet par octet, un coup non !

Autre chose, vouloir faire sur 7 bits est pas la solution. Temps de cycle perdu et programme plus compmexe. Jf ne peux pas me le permettre!

Dernier point, je ne ferais pas de CRC 16 mais un CRC 8. Toujours simplifier.

Bon ben, comme d'ab, à défaut d'avoir la science infuse, j'infuse la science wink

32

Re : Mixage de voies et liaisons I²C entre carte Arduino

Un coup on travaille octet par octet, un coup non !

Là c'est moi qui ne te comprends pas.

Autre chose, vouloir faire sur 7 bits est pas la solution. Temps de cycle perdu et programme plus compmexe. Jf ne peux pas me le permettre

Tu n'es pas cohérent avec toi même là smile Ca ne te faisait pas peur de convertir du numérique en ASCII et de le parser ensuite dans l'autre sens, et là tu trouves que faire un décalage et une addition ça coûte trop cher ? Faudra m'expliquer la logique wink

Dernier point, je ne ferais pas de CRC 16 mais un CRC 8. Toujours simplifier.

Pour être honnête, je n'ai jamais utilisé de CRC dans mes communications avec le radeau et n'ai jamais eu de problème. Pas une seule trame perdue, même à 400 mètres de distance avec des antennes à même pas un mètre au-dessus de l'eau salée. Conclusion : es-tu certain que le CRC soit réellement utile ? Il y a des tas d'autres manières de gérer un incident transient au niveau de la transmission sans devoir recourir à des CRC.

33

Re : Mixage de voies et liaisons I²C entre carte Arduino

Eric a écrit:

Tu n'es pas cohérent avec toi même là smile Ca ne te faisait pas peur de convertir du numérique en ASCII et de le parser ensuite dans l'autre sens, et là tu trouves que faire un décalage et une addition ça coûte trop cher ? Faudra m'expliquer la logique wink

Je ne savais pas au départ que c'étais de l'ASCII. Bon, chu pas non plus un as de la programmation. Je fais ce que je peux avec mes connaissances. Elles s’agrandissent au fur et à la mesure des expérimentations.

Wai, et bien, j'ai envie d'employé un CRC, juste pour le plaisir de me compliqué un peu la classe. big_smile

Bon, si on en revenais à nos moutons !
Si je comprends bien tu fais une addition puis un décalage. Non ?

Maintenant, je bloque sur un autre point. Je construit une classe afin de gagner du temps plus tard en développement. Pour l'heure, je pense m'orienter vers un ensembles de commandes automatisés tel que:

- mylib.envoi(type, lenght, data1, data2).

A ce moment là, la même librairie doit pouvoir en réception sous-tirer le type, data1 et data2. Seulement, je pense à ceci:

- Si réception d'un signal sur RX
-- Passage en mode interruption
--- mylib.recep(trame)

puis dans mylib.recep() faire le traitement, les vérifications et enfin placera dans des variables chaque data.

De retour dans le loop, on récupère les données de variables modifiés par mylib.recep() et on boucle.

Chez pas si c'est clair ?

Bon ben, comme d'ab, à défaut d'avoir la science infuse, j'infuse la science wink

34

Re : Mixage de voies et liaisons I²C entre carte Arduino

Si je comprends bien tu fais une addition puis un décalage. Non ?

J'ai résumé un peu, mais ça ne va pas chercher bcp plus loin.

- Si réception d'un signal sur RX
-- Passage en mode interruption
--- mylib.recep(trame)

puis dans mylib.recep() faire le traitement, les vérifications et enfin placera dans des variables chaque data.

Pas tout à fait.

La règle de base à respecter dans tout handler d'interruption est d'être le plus bref possible. On en bannit donc tout traitement complexe. Ton handler d'interruption doit se contenter de placer les bytes reçus dans un buffer (circulaire de préférence) et de positionner un flag pour dire qu'il y a du nouveau. C'est dans la loop principale qu'on va mamailler le byte pour l'interpréter comme il se doit dans le cas où on a détecté que le flag "y'a du nouveau" a été positionné.

35

Re : Mixage de voies et liaisons I²C entre carte Arduino

Ah wai, donc dans ce cas, ma classe ne se contente que d'émettre dans un premier temps, puis de recevoir dans un second temps.

Le loop lancera des commande dans la classe pour faire les traitements.

Enfin si je comprends bien...

Bon ben, comme d'ab, à défaut d'avoir la science infuse, j'infuse la science wink

36

Re : Mixage de voies et liaisons I²C entre carte Arduino

Ben comme je ne sais pas trop ce que fait ta classe, je ne peux pas trop dire.

Tu tiens vraiment à faire du C++ ? Tu sais que les allocations dynamiques d'instances C++ et toutes ces choses là sont à considérer comme non disponibles sur une plate-forme comme un AVR ?

Un handler d'interrupt est une simple routine C qui doit être le plus efficace possible, donc à mon avis à considérer en dehors de toute considération de classe ou autre mécanisme éventuellement consommateur de cycles CPU. Ne pas oublier que pendant un service d'interruption on ne peut en général pas traiter d'autres interruptions sur des proc de la classe des AVR ou similaires. Il fut donc réduire au plus la fenêtre de temps pendant laquelle on va ignorer le reste du monde.

37

Re : Mixage de voies et liaisons I²C entre carte Arduino

Donc, c'est peut-être pas une bonne idée de faire une classe roll

Alors dans ce cas, comment je peux faire ?
Le logiciel Arduino, accepte sans mal le c++ maintenant est-ce que c'est la bonne méthode, je pense que oui au niveau théorique. Ensuite effectivement, j'ai peut-être intérêt à posé la question au niveau des spécialos Arduino...

A ce moment là, je laisse tomber la librairie, je passe en mode loop et je gère à l'ancienne sans interruptions. Personnellement c'était pratique pour un certains nombre de cas. Là, je m'interroge!

Bon ben, comme d'ab, à défaut d'avoir la science infuse, j'infuse la science wink

38

Re : Mixage de voies et liaisons I²C entre carte Arduino

L'utilisation de classes ne pose pas de problème avec Arduino, cela permet de simplifier l'écriture.
Mais surtout, ça n'a rien à voir avec l'interruption ou pas : tu peux utiliser une classe dans une boucle, ou dans une interruption.

Tu peux poser ta question ici, il y a plein de spécialistes Arduino.

39

Re : Mixage de voies et liaisons I²C entre carte Arduino

Il est clair que ça simplifie l'écriture, mais au prix d'une expansion de code non négligeable, et également d'une réduction de performances à la clé (cf l'article assez détaillé sur ce sujet de Denis BODOR dans un numéro d'Open Silicium). Ou alors cela veut dire qu'on s'interdit les virtual et autres polymorphismes. Il n'y a pas de magie : on n'a rien sans rien.

D'où la question : du fait qu'une plate-forme comme l'AVR va par nature limiter la complexité de l'application, a-t-on vraiment besoin des classes et autres concepts objet, sachant qu'on ne pourra de toute manière pas profiter de toute leurs richesses ? D'autant que le facteur d'expansion lié aux libs Arduino va également ajouter son coup de frein aux ambitions que pourra avoir l'application.

Après, c'est à chacun de trouver sa réponse selon ses goûts et contraintes.

40

Re : Mixage de voies et liaisons I²C entre carte Arduino

Je te rassure, je suis pas forcément pour écrire une lib. Il me paraissait intéressant de le faire pour l'avoir en commun dans les deux cartes.

Je peux aussi m'appuyé sur un groupe de fonctions hors loop et y faire appel quand bon me semble.

C'est cette dernière possibilité que je vais faire au final. Les fonctions seront tester dans une des cartes, externalisé puis incluse par copier/coller depuis sa source. Ainsi, on a plus de soucis.

Si nous en revenions à nos moutons, je n'ai pas le temps matériel cette semaine ni ce week-ends de coder. En revanche, la semaine prochaine ça devrais être bon. Je propose de reprendre mes travaux la semaine d'après avec la réception des bytes.

Peut-être qu'un code du type:

 void loop() {

    // Vérifier si des caractères sont reçu sur le port série
    if (Serial.available() > 0) {
      
       // Variable temporaire pour copier le byte
       byte byteRecu;
       // Lire un Byte
       byteRecu = Serial.read();
      
       // Si c'est le start bit
           // Traiter le type
           // Traiter le lenght
           // Boucler tant que c'est < à lenght
               //Traiter data
               ++
           // En fonction d'un tableau de data, affecter à la commande en fonction du type
           // Traiter CRC
    }
     
     // Retour au programme d'écriture des données
  }

Comme tu peux voir, je simplifie à l'extrème à part le CRC que je vais peut-être interdire pour un stopbit.

Pas sur par contre qu'un 0xEEEE (strat) et un 0xFFFF (stop) soit possible en direct. Je me renseignerais avant d'aller plus loin. D'abord je valide le concept, enfin l'algorithme puis ensuite, je code partie par partie. Une brique après l'autre afin de ne pas être dépassé.

Bon ben, comme d'ab, à défaut d'avoir la science infuse, j'infuse la science wink

41

Re : Mixage de voies et liaisons I²C entre carte Arduino

Si tu utilises Serial, je suppose qu'il bufferise en interne, et donc ps la peine d'aller plonger dans les routines d'interrupt. Il est vrai que la vision que j'ai du sujet est au travers du fait que j'ai toujours développé du code "bare metal", c'est à dire en C direct (avec des extraits de  libs telles que avrlib par exemple) mais sans environnement comme l'Arduino. Donc ta loop devrait fonctionner

Par contre la logique que tu exprimes dans les commentaires qui suivent le read est un peu simpliste.

Le problème qui se pose avec des éléments de trame multi-bytes (que ce soit un start marker, ou bien un de tes champs) est qu'on entre dans le domaine de la gestion de protocole (n'oublions pas qu'un protocole définit le format des échanges) et donc du parsing de flux de données (ie de bytes ici). Cela ne peut décemment se faire (sauf cas très simples) qu'à l'aide d'automates à états finis (FSA ou FSM dans la littérature).

Pour simplifier, supposons que la structure d'une de tes trames est :
- start marker (2 bytes, égal à 0xFFFF
- length byte
- consigne moteur 1 (2 bytes)
- consigne moteur 2 (2 bytes)
- état switchs (2 bytes)
- CRC (2 bytes)

Un automate résultant pourra comporter les états suivants :
- IDLE : en attente de trame à traiter
- START_DETECTED : on a détecté le premier byte du start marker
- IN_LENGTH_FIELD : on est  dans le champ "longueur"
- IN_PAYLOAD : on est en train de recevoir les n bytes de la "charge utile", c'est à dire les champs de consigne moteur et de switchs
- IN_CRC : on est en train de lire le CRC

La logique est la suivante :
1/ on démarre dans l'état IDLE, (initialisation faite avant la boucle)
2/ dans la boucle :
- si on reçoit un byte qui vaut 0xff dans cet état, on passe alors dans l'état START_DETECTED.
- une fois dans cet état, on s'attend à un autre 0xff. Lorsqu'on le reçoit, on passe dans l'état IN_LENGTH_FIELD, puisque le prochain byte sera celui qui donne la longueur du payload (6 dans notre cas). Si on reçoit autre chose, c'est une erreur, et on est certainement au milieu d'une trame dont on a raté le début. Dans ce cas, on signale l'erreur d'une manière ou d'une autre, et on se remet dans l'état IDLE.
- si on est dans l'état IN_LENGTH_FIELD le prochain byte reçu sera la longueur du payload. On le stocke et on passe dans l'état IN_PAYLOAD
- étant dans l'état IN_PAYLOAD, on reçoit et on traite les bytes reçus tant qu'on n'est pas arrivé au total correspondant à la longueur
- à ce moment-là on passe dans l'état IN_CRC
- étant en IN_CRC, les bytes reçus sont stockés et lorsqu'on arrive au compte correspondant à la longueur du CRC (2 pour un CRC16, 1 pour un CRC8), on fait la vérification d'intégrité de la trame reçue selon la règle qu'on s'est définie. Selon le résultat on positionne un flag pour indiquer si les données reçues sont valides ou non, et on revient dans l'état IDLE puisqu'on a fini de recevoir la trame.
- si le flag de validité des données est ok, on les traite. Sinon on signale l'erreur et on ignore ce qui a été reçu.

A noter que si les trames ont une longueur fixe, on peut se passer du lenght byte, puisque sa valeur est constante et connue. Dans ce cas l'état IN_LENGTH_FIELD n'a pas lieu d'être.

Ce schéma est plus ou moins celui qui est à suivre dès qu'on doit implémenter une communication entre deux entités qui échangent des données selon un protocole défini. Tu pourras trouver des tonnes d'exemples de code C qui implémentent une FSM, et dans tous les cas, ça tourne autour d'un "switch/case" basé sur l'état courant, le byte reçu étant interprété dans chacun des "case" selon le contexte, ce traitement pouvant se traduire par une commutation d'état selon la logique du protocole.

Voilà. Have fun wink

42

Re : Mixage de voies et liaisons I²C entre carte Arduino

Wai, donc à la limite, si je passe par un case, une succession de valeur, je je me casse moins la tête.

Par contre sur les deux bytes par data, la je pense pas. Un seul byte de 0x00 à 0xFF suffi. Par contre il me faut 2 data pour faire un ordre complet.

Je réserve les doubles bytes pour le start et le stop. Je l'imite le CRC au départ pour faire déjà que ça fonctionne et en avant.

Je connaissait pas le principe des idle. Bonj'aurais appris quelque chose.

Bon ben, comme d'ab, à défaut d'avoir la science infuse, j'infuse la science wink

43

Re : Mixage de voies et liaisons I²C entre carte Arduino

Disons que tu vas quand même te casser un peu la tête (sinon ce serait trop facile wink, mais le gros intérêt de cette méthode est qu'il est facile de modifier l'automate en fonction des évolutions du protocole, chose qui est impensable avec un plat de spaghetti de if-then-else, sauf si on reste dans des cas triviaux.

Par ailleurs, il existe des outils permettant de prouver la validité d'un automate en fonction de sa table de transition, et également de générer cet automate à partir des règles définissant les transitions. lex (un analyseur lexical de référence) par exemple permet cela, car un protocole n'est en fait rien d'autre que la définition d'une syntaxe de message, et analyser un protocole défini de cette manière revient donc à effectuer l'analyse lexicale d'un flux de données. Mais on peut faire sans dans un premier temps.