RS485 breakout fonctionnement RTS

Bonjour à tous,

J'ai rencontré un problème lors de la mise en oeuvre du RS485 breakout de chez Sparkfun : SparkFun Transceiver Breakout - RS-485 - BOB-10124 - SparkFun Electronics?

Pour situé, je souhaite mettre en place une communication asynchrone half-duplex multi-point avec détection de collision (je ne sais pas encore comment...). En gros 3 arduino qui discutent quand et avec qui y veulent ^^.

Pour l'instant, avec deux arduino, ça fonctionne pas mal avec ce code :

Code Arduino 1 :

digitalWrite(RTS1,HIGH);
Serial3.write(100); // Adresse
Serial3.write(1); // Longueur de la data à suivre
Serial3.write(valeur);

Code Arduino 2 :

void loop() 
{
  // Lecture sur le port série 1
  digitalWrite(RTS1,LOW);
  
  if (Serial1.available() > 0)
  {
    int adresse = Serial1.read();    
    
    Serial.print("Adresse : ");
    Serial.print(adresse);
    Serial.println();    
    
    switch(adresse)
    {
       case 100:
         while(Serial1.available() < 1); // Attente de l'octet dans le buffer de lecture
         longueur = Serial1.read();
         Serial.print("Longueur a suivre : ");
         Serial.println(longueur);
         selection_action(longueur);
         break;
         
       default:
         delay(0);
    } 
  }     
}

void selection_action(int NB_OCTETS)
{
   int DATA[NB_OCTETS];
   
   for(int i = 0 ; i < NB_OCTETS ; i++) // On rempli le tableau d'octets 
   { 
     while(Serial1.available() < 1); // Attente des données entre chaque tour de boucle 
     DATA[i] = Serial1.read(); // Stockage des valeurs dans le tableau
     
     Serial.println(DATA[i]); // Affichage des valeurs 
   }
}

Après j'ai voulu implémenter le retour (renvoi du message reçu) donc côté Arduino 1, j'ai fait :

digitalWrite(RTS1,HIGH);
Serial3.write(100); // Adresse
Serial3.write(1); // Longueur de la data à suivre
Serial3.write(valeur);
digitalWrite(RTS1,LOW);

Et là, ça ne fonctionne plus. Mon hypothèse : le signal Enable (RST1) est mis à l'état bas avant la fin de transmission de la trame
Si je rajoute un delay(5) entre le dernier Serial3.write et le digitalWrite(RTS1,LOW), pas de problème ça fonctionne à nouveau.

Je voudrais donc trouver une condition qui permette de dire : "c'est bon j'ai fini de transmettre" sans utiliser la fonction delay().

Merci d'avance.

Le truc c'est que la librairie Serial n'est pas bloquante, le buffer est "chargé" en continu, donc effectivement ton digitalWrite(LOW) se produit avant la fin de la trame. Tu peux utiliser la fonction Serial.flush() qui comme son nom ne n'indique plus depuis la version 1.0 de l'IDE, permet d'attendre la fin de l'émission = Serial.flush() - Arduino Reference

Super merci!

Exactement ce que je cherchais. J'étais resté dans l'idée flush=vider le buffer...

Pour ce qui est de la gestion des collision, t'aurais pas quelques infos ?

La gestion de la collision repose généralement sur l'écoute, par l'émetteur, des données qu'il envoie.
L'émetteur compare ce qu'il a envoyé avec ce qu'il reçoit.

  • S'il les données sont intègres alors il n'y a pas eu de collision.
  • Si les données sont modifiées alors il y a eu collision. Dans ce cas là il faut renvoyer le message. Il y a plusieurs stratégies pour gérer ce renvoie. Une stratégie assez courante est basée sur une attente d'une durée aléatoire. Chaque carte dispose d'une "graine" différente pour l'initialisation du générateur de nombres aléatoires afin de maximiser la chance que 2 cartes ne réémettent pas au même moment.Si ma mémoire est bonne c'est le principe utilisé en Ethernet token ring.

La gestion des collisions impose quelques contraintes sur le protocole. Dans la mesure où il peut y avoir réémission d'un paquet de données, ces paquets doivent être identifiés pour que le doublon soit connu du récepteur. il faut donc avoir une entête indiquant l'ID de l'émetteur, l'ID du destinataire et un numéro unique identifiant le message (unique par émetteur et sur une période de temps suffisante pour éviter toute ambiguïté).
Il faut aussi un contrôle de cohérence (CRC) et une fin de message afin que le destinataire puisse s'assurer que le message reçu est valide.
Après c'est le protocole qui va définir si le destinataire redemande l'émission du message perdu ou s'il repose uniquement sur le contrôle fait par l'émetteur.

fdufnews:
La gestion de la collision repose généralement sur l'écoute, par l'émetteur, des données qu'il envoie.
...Si ma mémoire est bonne c'est le principe utilisé en Ethernet token ring.

Bonjour fdufnews
le token ring , il me semble n'avais justement pas à gerer les collisions, le reseau transmettant le jeton d'autorisation de proche en proche.
Tu ne pense pas plutôt au CSMA/CD ?
ça rajeuni pas tout ça ! :grin:

Ok,

ça semble assez complexe à coder...

Une manière simple de gérer les collisions et de rajouter un autre fil qui sert à indiquer la "prise de parole"

Tu peux développer un peu ?

Tu pense à quoi comme signal ?

Une ligne en plus, avec une résistance de pull up vers 5V. Un pin par arduino : quand tu veux entamer une communication, tu vérifies l'état de la ligne : +5V = dispo, 0V = déjà une com en cours. Si c'est libre, tu passes l'entrée en sortie, digitalWrite(LOW) et tu réalises ta com. Une fois terminée tu libères la ligne en repassant en INPUT.

D'accord, c'est bien ce que je pensais mais je vois tout même un problème majeur à cette solution. L’intérêt du RS485 étant de pouvoir communiquer sur de longues distance (via la paire différentielle) tout en présentant une certaine immunité aux parasites, je me vois mal faire transiter le type de signal que tu décris. Sur un réseau de quelques dizaines de cm, pourquoi pas, mais malheureusement pas dans mon cas.

Une ligne qui passe 5 à 0 V ??! Tu peux faire des kilomètres ...