Implémenter un protocole de communication binaire

Bonjour à tous,

Je suis nouveau dans le monde Arduino et je dois faire communiquer une carte Arduino avec un moteur électrique de bateau. La liaision est faite par un bus RS-485 en half-duplex.

Le système original est constitué d'un PCB maître qui envoie des commandes à ses esclaves via le bus RS-485 qui sont la manette des gaz, l'afficheur LCD, la batterie et le moteur brushless.

Mon objectif est de remplacer la manette des gaz par ma Arduino car le moteur sera installé sur un drone marin donc sans équipages.

Je possède le protocole de communication du système avec toutes les commandes mais je n'arrive pas l'implémenter dans ma carte Arduino.

Je suis parti sur le travail d'aka Barbudor sur "implémenter un protocole de communication" mais j'aimerais implémenter un protocole binaire à la place d'un protocole ASCII.

Pouvez vous me dire ce qui va changer sur l'exemple proposé dans ce sujet ?

Merci d'avance.

De mémoire, le document de Barbudor concernait la création d'un protocole partant de zéro. Dans ton cas le protocole existe déjà donc il faut que tu le codes. Tu n'as rien à inventer. Quel est ton problème?

Bonjour,

Merci pour votre réponse rapide. Je ne vois pas trop la différence en termes de codage entre le protocole ASCII et binaire.

Est-ce qu’il faut juste changer les variables type “char” en type “byte” et l’adapter à mon protocole ?

Un char c'est un octet un byte c'est aussi un octet. Par contre c'est dans la manière de les transmettre que ça change. Pour envoyer de l'ASCII on utilise print ou println. Pour envoyer du binaire on utilise write. write transmet les données sans les interpréter ou les mettre en forme. Par exemple si toto=255; print va envoyer 3 caractères ASCII 2 5 5 write va envoyer un octet

elecmania44: Bonjour,

Merci pour votre réponse rapide. Je ne vois pas trop la différence en termes de codage entre le protocole ASCII et binaire.

Est-ce qu'il faut juste changer les variables type "char" en type "byte" et l'adapter à mon protocole ?

Bonsoir en complement de la reponse de fdufnews , je pense que ton probleme est avant tout d'interfacer en hard l'uart TTL en RS485.

il y a pas mal de modules d'interface disponible , generalement basé sur un MAX485 exemple

Merci beaucoup pour vos réponses, je vais essayer d'implémenter mon protocole.

Pour répondre à Artouste, je suis déjà en possession de MAX485 pour convertir les signaux TTL de la arduino en signaux différentielles A et B.

Je pense vraiment que mon problème se trouve dans le codage de mon protocole constructeur.

Petite info supplémentaire, le code ASCII est codé sur 7 bits et non pas 8

Bien justement ça peut avoir son importance puisque le protocole existe en ASCII, pour la conversion de celui-ci en binaire, il faut vérifier que ce 8eme bit est bien transféré ;)

elecmania44: Je pense vraiment que mon problème se trouve dans le codage de mon protocole constructeur.

bonsoir A priori ce "protocole" est déjà documenté , mets un lien vers une doc que l'on puisse "regarder"

Bonjour,

Je suis en stage en entreprise et le protocole de communication est propre au constructeur des moteurs et c'est donc un document confidentiel.

Je ne peux pas le mettre en entier sur le forum mais je peux vous communiquer quelques informations indispensables à la réalisation du software.

Merci d'avance pour votre soutien.

Il y a un maître (PCB Master) et plusieurs esclaves (Moteurs, manette des gaz, afficheur, batterie, etc).

La liaison série est faite par RS-485 à 19200 Bd, 8 bits de données, 1 bit de stop et pas de parité.

Toutes les 25 ms, une requête est envoyée par le maître sur le bus.

Quand la requête a été envoyée, l'esclave correspondant doit répondre avant la fin des 25 ms sinon le maître considère que c'est un échec et renvoi une requête.

On doit attendre au moins 1560 µs entre la réception de la requête et la réponse de l'esclave.

Voila pour commencer les informations que je peux vous donner.

Et c'est quoi ton problème en fin de compte?

Je vois pas trop comment coder ceci proprement.

Je n'arrive pas à répondre à la requête du PCB Master au bon moment en utilisant des "Serial.read", "Serial.write" et des "delay".

Je m'explique, au niveau hardware le MAX485 côté maître (PCB Master) est en mode émission pour envoyer la requête sur le bus et doit se mettre en mode reception quand il attend la réponse de l'esclave.

Et bien c'est ce moment là que je n'arrive pas à capter avec mon soft. J'ai l'impression que lorsque que je fais un Serial.write avec ma Arduino, le PCB Master est déjà en mode émission.

J'espère que c'est un peu plus clair maintenant, je ne suis pas un développeur c'est pour ça que je suis parti sur une solution Arduino car je croyais m'affranchir d'une programmation C ou même C++ que je ne maîtrise pas très bien.

elecmania44: J'ai l'impression que lorsque que je fais un Serial.write avec ma Arduino, le PCB Master est déjà en mode émission.

Un oscilloscope permet de transformer une impression en certitude.

Ne pas oublier qu'entre le moment où le le message arrive et celui où ton programme s'en rend compte un certain temps s'est écoulé. Serial reçoit les données sous interruption mais ton programme ne le sait que:

  • lorsque tu fais un Serial.available()
  • lorsque tu itères une nouvelle fois dans la boucle loop si tu utilises serialEvent() Si ton programme doit être réactif il faut l'architecturer en conséquence.

elecmania44: J'espère que c'est un peu plus clair maintenant, je ne suis pas un développeur c'est pour ça que je suis parti sur une solution Arduino car je croyais m'affranchir d'une programmation C ou même C++ que je ne maîtrise pas très bien.

L'Arduino se programme en C++, donc je ne vois pas très bien ce que tu évites en fin de compte.

elecmania44: Il y a un maître (PCB Master) et plusieurs esclaves (Moteurs, manette des gaz, afficheur, batterie, etc).

La liaison série est faite par RS-485 à 19200 Bd, 8 bits de données, 1 bit de stop et pas de parité.

Toutes les 25 ms, une requête est envoyée par le maître sur le bus.

Quand la requête a été envoyée, l'esclave correspondant doit répondre avant la fin des 25 ms sinon le maître considère que c'est un échec et renvoi une requête.

On doit attendre au moins 1560 µs entre la réception de la requête et la réponse de l'esclave.

Voila pour commencer les informations que je peux vous donner.

bonjour les requetes et les trames en retour sont de longueurs fixes ? une requete est organisée selon quelle structure à 19200 on transmet au max ~ 1900 octets/seconde et là on est sur du half-duplex

Non les requêtes et les trames ont une longueur variable.

Dans mon cas, je dois répondre à la requête AC 14 01 89 AD.

AC : PACKET_START 14 : Adresse de la manette des gaz 01 : But de la requête 89 : CRC-8 AD : PACKET_END

La réponse doit être de la forme : AC 00 00 05 00 00 64 85 AD.

AC : PACKET_START 00 : Adresse vide car réponse 00 : Pas de requête 05 00 00 64 : corps du message comportant l'information de vitesse pour le moteur 85 : CRC-8 AD : PACKET_END

elecmania44: Non les requêtes et les trames ont une longueur variable.

Dans mon cas, je dois répondre à la requête AC 14 01 89 AD.

AC : PACKET_START 14 : Adresse de la manette des gaz 01 : But de la requête 89 : CRC-8 AD : PACKET_END

La réponse doit être de la forme : AC 00 00 05 00 00 64 85 AD.

AC : PACKET_START 00 : Adresse vide car réponse 00 : Pas de requête 05 00 00 64 : corps du message comportant l'information de vitesse pour le moteur 85 : CRC-8 AD : PACKET_END

il faut donc attendre un byte 0xAC (byte0) - verifier si le byte suivant (byte1) est 0x14 et si oui - verifier si le byte suivant (byte2) est 0x01 et si oui - sauvegarder le byte suivant (byte3) - verifier que le byte suivant (byte4) reçu est 0xAD et si oui - calculer le crc8 des byte1,byte2 (AMHA byte0 ne doit pas faire partie du CRC8 à calculer, mais c'est à verifier) - comparer le crc8 calculé à byte3

et si ok attendre 1600 µs ( au moins 1580 µs) avant d'envoyer la trame de 9 bytes en reponse (avec calcul du CRC) et retourner ensuite à attendre un 0xAC

Merci pour cette réponse claire et précise Artouste,

J'avais en tête un algorithme de la sorte mais je pensais que c'était un peu simple.

Il y a un truc qui me dérange mais c'est peut être une connerie !

Le temps de vérifier les bytes, de les sauvegarder, de calculer le CRC, de comparer le CRC, est-ce que le maître n'aura pas repris la main ?

Le problème est que je n'ai pas d'oscilloscope pour le vérifier.

elecmania44: Merci pour cette réponse claire et précise Artouste,

J'avais en tête un algorithme de la sorte mais je pensais que c'était un peu simple.

Il y a un truc qui me dérange mais c'est peut être une connerie !

Le temps de vérifier les bytes, de les sauvegarder, de calculer le CRC, de comparer le CRC, est-ce que le maître n'aura pas repris la main ?

Le problème est que je n'ai pas d'oscilloscope pour le vérifier.

A priori non, les operations de comparaisons et de calcul sont rapides la trame que tu attend est emise par le maitre en - de 3 ms et tu dispose de 25 ms pour te manifester avant qu'il réémette.

Bonjour,

  • le rs485 demande aussi un peu de rigueur au niveau hard, peux-tu nous montrer le schéma des connexions ?

  • tu n'as pas besoin d'oscillo pour déboguer du rs485, mais un analyseur logique ~10€ serait utile