Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème de timing de lecture de trame RS485

lecture d'un port série RS485

    10 septembre 2020 à 14:50:51

    l

    -
    Edité par MrNeokonan. 5 octobre 2020 à 17:01:13

    • Partager sur Facebook
    • Partager sur Twitter
      10 septembre 2020 à 16:34:17

      MrNeokonan. a écrit:

      Je souhaite qu'il lise qu'à partir de la trame maitre qui concerne le seconde esclave. 

      Peut-être ai-je mal saisi la situation, mais pour savoir quelle trame lui est destiné il faut toutes les lire. Enfin je pense ?
      • Partager sur Facebook
      • Partager sur Twitter
        10 septembre 2020 à 16:47:21

        Bonjour, as tu regardé du coté de ce qui existe déjà ?:

        https://github.com/stephane/libmodbus

        • Partager sur Facebook
        • Partager sur Twitter
          10 septembre 2020 à 16:57:36

          Bonjour, 

          Oui Thetui, il faut toutes les lire, tu peux regarder mon schéma fait sur Paint, où tu peux voir à quoi ressemble l'envoie des trames du maitre. 

          Dès que je detecte quelque chose sur le port série, ma fonction lecture commence. 

          Sauf qu'il lis la trame du 1 ère esclave et moi je veux skipé ça et je veux qu'il lise qu'à partir du second esclave.

          Les trames sont très rapides et suis ce principe :

          Maitre requete 1 - reponse Esclave 1 - Maitre requete 2 - réponse Esclave 2 - Maitre requete 1 - reponse Esclave 1 - Maitre requete 2 - Reponse Esclave 2

          Moi je veux que ma fonction lecture, ne lise que la requête destinée à l'esclave 2. 

          Merci pour ton lien bxdfr mais je préfère faire ma propre librairie pour mieux comprendre ce que je fais, même si c'est plus compliqué. Je vais jeter un coup d'oeil pour voir si ça m'aide

          • Partager sur Facebook
          • Partager sur Twitter
            10 septembre 2020 à 17:34:41

            Ton code est très désagréable à lire avec toutes ces lignes vide inutiles !
            • Partager sur Facebook
            • Partager sur Twitter
              10 septembre 2020 à 20:50:24

              "Sauf qu'il lis la trame du 1 ère esclave et moi je veux skipé ça et je veux qu'il lise qu'à partir du second esclave.

              Moi je veux que ma fonction lecture, ne lise que la requête destinée à l'esclave 2. "


              C'est bizarre comme principe.
              Normalement, un esclave doit toujours être en attente d'une trame de requête du maître et ne sait pas à priori si elle lui est adressée ou pas. Il va donc lire la trame, voir si c'est à lui qu'elle s'adresse, et si ce n'est pas le cas attendre qu'une nouvelle lui parvienne.

              -
              Edité par zoup 10 septembre 2020 à 20:50:42

              • Partager sur Facebook
              • Partager sur Twitter
                11 septembre 2020 à 4:13:54

                Il y a une description intéressante de ceci dans le lien suivant:
                https://www.technologuepro.com/cours-systemes-embarques/cours-systemes-embarques-Bus-RS485-MODBUS-Prifibus.htm
                C'est comme si j'envoyais un message à la télévision demandant à MrNeokonan. de communiquer avec moi.
                J'ose espérer que d'autres ne me contacteront pas à ta place ...
                (je regarderai mon afficheur téléphonique ...)
                • Partager sur Facebook
                • Partager sur Twitter

                Le Tout est souvent plus grand que la somme de ses parties.

                  11 septembre 2020 à 8:54:51

                  h

                  -
                  Edité par MrNeokonan. 5 octobre 2020 à 17:00:57

                  • Partager sur Facebook
                  • Partager sur Twitter
                    11 septembre 2020 à 15:03:06

                    Je n'ai pas regardé ton code ...
                    Ton maître doit en premier envoyer un message que tous les esclaves reçoivent.
                    Le message doit contenir l'identification de l'esclave à qui le maître veut parler.
                    Les esclaves sont en mode lecture en attente de l'ordre du maître leur étant dédié.
                    Les esclaves ne parlent au maître que s'ils reçoivent un ordre de le faire de la part du maître.
                    Une fois le message envoyé, le maître attend la réponse (durant un certain temps, c'est là que le timing intervient)
                    Le maître fait un certain nombre d'essais, après quoi il déclare l'esclave comme mort.

                    • Partager sur Facebook
                    • Partager sur Twitter

                    Le Tout est souvent plus grand que la somme de ses parties.

                      11 septembre 2020 à 16:21:56

                      Je comprends, mais mon problème n'est pas le fait de recevoir la trame du maitre. 

                      C'est de pas la recevoir au bon moment à cause de ma fonction fcntl(serial_port, F_SETFL, 10).

                      Est ce que tu pourrais mieux m'expliquer cette fonction car je pense que je dois mal la comprendre. Surtout l'argument F_SETFL.

                      Je pense que c'est ça qui doit foutre la merde dans mes timings. 

                      Ou sinon c'est mon paramétrage du port RS485.

                      • Partager sur Facebook
                      • Partager sur Twitter
                        14 septembre 2020 à 10:16:19

                        Bonjour à tous, 

                        je fais un UP du sujet car je n'ai pas trouvé la solution à mon problème. Je ne nais si mon problème est clair ou si vous avez besoin de plus de détail. 

                        Pour résumer : je veux juste lire la trame du maitre qui est adressé à l'esclave 2, en suivant le schéma que je fais là haut. Pas la trame destiné à l'esclave 1. 

                        Sachant que la première trame du maitre, qui arrive et que je lis est toujours celle destinée à l'esclave 1. 

                        • Partager sur Facebook
                        • Partager sur Twitter
                          14 septembre 2020 à 11:51:15

                          MrNeokonan. a écrit:

                          Pour résumer : je veux juste lire la trame du maitre qui est adressé à l'esclave 2, en suivant le schéma que je fais là haut. Pas la trame destiné à l'esclave 1. 

                          C'est là où je ne te suis plus. Il ne faut pas procéder ainsi: il faut lire TOUTES les trames et ensuite les analyser pour déterminer si on est destinataire ou non. Le premier octet de la trame donnant l'adresse de l'esclave, ça ne sera pas compliqué.

                          -
                          Edité par zoup 14 septembre 2020 à 11:51:24

                          • Partager sur Facebook
                          • Partager sur Twitter
                            14 septembre 2020 à 12:25:40

                            Je suis d'accord qu'il faut lire toutes trames. On ne peux pas faire autrement. 

                            Mais il y a un problème avec ça, je vais t'expliquer. 

                            Je stocke la trame dans un tableau de char qui s'appelle lecture.

                            Donc lecture[0] = adresse esclave

                            lecture[1]=code écriture ou code lecture

                            lecture[2]= adresse registre 

                            ect...

                            Dans mon programme, je reprend ces variables lectures, que je renvoie avec ma fonction write. 

                            Donc je renvois lecture[0], lecture[1] ect...

                            Sachant que je suis l'esclave 2, si lecture[0] n'est pas à égal à 2, cela veut dire que la trame que je lis, ne m'est pas adressé car je le répète, je suis l'esclave 2. 

                            Donc il faut que je lise la trame destiné à l'esclave 2.

                            Le seul moyen que j'ai trouvé c'est de faire une boucle while pour lire en boucle le port série. 

                            while lecture[0]!=2) 

                            {

                              int flag = fcntl(serial_port,F_GETFL,0);    

                               fcntl(serial_port,F_SETFL,10);   

                                read(serial_port, lecture, size of lecture)

                            }

                            Sauf que ça ne fonctionne pas tout le temps, des fois je il arrive à chopper la bonne trame, des fois non. 

                            Donc il y a un problème sur la fonction fcntl, donc avec le flag.

                            Ou c'est mon paramétrage de mon port RS485. 

                            • Partager sur Facebook
                            • Partager sur Twitter
                              14 septembre 2020 à 18:41:51

                              MrNeokonan. a écrit:

                              Sauf que ça ne fonctionne pas tout le temps, des fois je il arrive à chopper la bonne trame, des fois non. 

                              Ce qu'il serait intéressant de savoir c'est si tu arrives à capturer TOUTES les trames (même celles qui ne te sont pas destinées) sans en louper.

                              MrNeokonan. a écrit:

                              Ou c'est mon paramétrage de mon port RS485.

                              Je ne pense pas: si la configuration était incorrecte, tu n'aurais jamais reçu une trame correcte.

                              Désolé de ne pas t'apporter plus de réponse concernant l'utilisation de fcntl et des flags, car je ne l'ai que très peu utilisé. J'utilise plutôt des bibliothèques de gestion du port série, plutôt en C++

                              Sinon, ton programme est destiné à fonctionner sur un PC?

                              PS: après relecture de ton code, il y a un truc qui m'embête:

                              read(serial_port, lecture, sizeof(lecture));

                              La lecture de trames de données sur le port série n'est pas trivial.

                              Que se passe-t-il si la lecture est déclenchée au milieu de la réception d'une trame? Réponse : la trame n'est pas complète. Et du coup la suivante ne le sera pas non plus.

                              L'idéal serait de stocker les données dans un buffer permettant de stocker plusieurs trames et de "piocher" dedans de manière à n'y lire que des trames complètes que tu effacerais au fur et à mesure de leur lecture.

                              A des fins de test, il serait intéressant de créer un gros buffer et d'y enregistrer tout ce qui est lu sur le port série de manière à stocker quelques dizaines de trames, puis de visualiser le contenu de ce buffer de manière à voir si la succession de trames a été lue correctement.

                              -
                              Edité par zoup 14 septembre 2020 à 18:53:36

                              • Partager sur Facebook
                              • Partager sur Twitter
                                15 septembre 2020 à 8:50:00

                                Bonjour Zoup, c'est déjà très gentil de vouloir m'aider donc je te remercie. 

                                Pour te répondre, oui j'arrive à recevoir toutes les trames. Oui j'ai déjà essayé de mettre la trame reçue dans un gros buffer et voir ce qu'il choppe en premier dans la lecture. La première fois qui lis la trame donc celle destinée à l'esclave 1, est presque toujours la bonne. 

                                Donc je reçois bien toutes les trames dans ce gros buffer les uns à la suite des autres. Voilà ce qui concerne le test avec un gros buffer pour stocker quelques trames.

                                Concernant la configuration du RS485, je suis d'accord que si c'était mal paramétré, je recevrai rien du tout. Sauf qu'il y a TELLEMENT D'option qu'on peut rajouter dans le paramétrage du rs485, que je me dis qu'il y a une option ou une ligne de commande qui est essentiel et qui manque.

                                De plus, le rs485 fonctionne avec un bit de stop. Alors pourquoi quand je lis en boucle la trame, il ne s'arrête pas au bit de stop, puis le stocke dans mon char tableau, puis relis à nouveau la trame pours s'arrêter au bit stop, puis le restocke dans le char ect...

                                Ce bit stop il sert à rien ou quoi?

                                De plus, qu'est ce qui te choque dans cette ligne de commande ? 

                                read(serial_port, lecture, sizeof(lecture));

                                Surement le sizeof? car si j'ai déclaré un char[100] lecture, pas sa taille ça sera 100 alors que pas forcément, moi je veux qu'il s'arrete à la taille de la trame du maitre donc au bit stop. 

                                C'est très compliqué les timings quand tu reçois en boucle infinie, les trames.

                                J'espère trouver une solution

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  15 septembre 2020 à 20:21:45

                                  MrNeokonan. a écrit:

                                  De plus, le rs485 fonctionne avec un bit de stop. Alors pourquoi quand je lis en boucle la trame, il ne s'arrête pas au bit de stop, puis le stocke dans mon char tableau, puis relis à nouveau la trame pours s'arrêter au bit stop, puis le restocke dans le char ect...

                                  Ce bit stop il sert à rien ou quoi?

                                  Ca n'a rien à voir. Le bit stop est géré par l'UART. Le bit stop sert à assurer la resynchronisation de l'horloge de réception (n'oublions pas qu'on est dans une transmission asynchrone, donc sans transmission de l'horloge entre émetteur et récepteur). Le bit stop permet donc de s'assurer que le bit start générera une transition du signal lors de l'émission d'un nouveau caractère.

                                  MrNeokonan. a écrit:

                                  Donc je reçois bien toutes les trames dans ce gros buffer les uns à la suite des autres. Voilà ce qui concerne le test avec un gros buffer pour stocker quelques trames.

                                  Dans ce cas, tu n'as plus de problème de réception, mais un problème de traitement des trames. Il te faut donc scanner ce buffer à la recherche d'un début de trame, vérifier que la trame est correcte en calculant et comparant son CRC, puis l'interpréter si l'adresse de l'esclave est la bonne.

                                  -
                                  Edité par zoup 15 septembre 2020 à 20:22:07

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    16 septembre 2020 à 8:42:27

                                    Je ne pensais pas que le bit stop servait à ça. Je pensais qu'il indiquait la fin de la trame. C'est bizarre, dans les sources que j'ai lu, le bit stop en protocole modbus, est à la fin de la trame. 

                                    Pourquoi renseigner t'on un bit stop ou deux bit stop dans le paramétrage du port série ?

                                    Pour la solution de scanner le buffer à la recherche d'un début de trame, c'est une bonne idée mais elle fonctionnera pas tout le temps. Imagine que je scanne pour chercher la valeur "2" qui signifiera que c'est l'esclave "2", qui dit qu'il n'y a pas un autre "2" dans la trame qui sera lié à une data ou un numéro de registre, ect...

                                    Si ton idée de scanner est différent de la mienne, je veux bien que tu me dises comment tu ferais pour scanner. 

                                    Je te remercie

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      16 septembre 2020 à 15:18:25

                                      MrNeokonan. a écrit:

                                      Je ne pensais pas que le bit stop servait à ça. Je pensais qu'il indiquait la fin de la trame. C'est bizarre, dans les sources que j'ai lu, le bit stop en protocole modbus, est à la fin de la trame. 

                                      Je serais curieux de voir ces sources. En Modbus RTU, le protocole de transmission "normal" d'un caractère est 1 start, 8 bits de données, 1 bit en parité paire, 1 stop. Il arrive qu'il y ait 2 stop en modbus ascii, mais je doute que tu utilises ce protocole qui est beaucoup moins courant.

                                      MrNeokonan. a écrit:

                                      Pourquoi renseigner t'on un bit stop ou deux bit stop dans le paramétrage du port série ?

                                      Pour des raisons (pré)historiques n'ayant plus court depuis bien longtemps, il était parfois nécessaire de repousser l'arrivée du caractère suivant par un bit stop supplémentaire, d'où les 2 bits stop. Sur l'UART d'un PC par exemple, on peut même avoir sous certaines conditions 1,5 bit stop.

                                      MrNeokonan. a écrit:

                                      Pour la solution de scanner le buffer à la recherche d'un début de trame, c'est une bonne idée mais elle fonctionnera pas tout le temps. Imagine que je scanne pour chercher la valeur "2" qui signifiera que c'est l'esclave "2", qui dit qu'il n'y a pas un autre "2" dans la trame qui sera lié à une data ou un numéro de registre, ect...

                                      C'est pour cela qu'il faut vérifier que c'est une trame correcte en testant le CRC comme je te l'ai proposé plus haut.

                                      MrNeokonan. a écrit:

                                      Si ton idée de scanner est différent de la mienne, je veux bien que tu me dises comment tu ferais pour scanner. 

                                      Si je sais que mon esclave a pour adresse 2, je cherche le premier 2 que je trouve dans le buffer, je regarde le caractère suivant qui me donne la fonction exécutée, puis éventuellement les informations sur la longueur de la trame, je calcule le CRC et le compare aux 2 derniers octets de la trame supposée.
                                      Si les CRC correspondent, c'est gagné.
                                      S'ils ne correspondent pas, je cherche le 2 suivant et je recommence jusqu'à ce que la trame soit correcte.
                                      C'est peut-être fastidieux, mais dans tous les cas, tu aurais dû calculer le CRC pour t'assurer qu la trame avait été transmise sans erreur.
                                      Ce qui est BEAUCOUP plus compliqué (et qu'on ne fait pas souvent) c'est de vérifier les timings inter caractères et inter trame pour respecter strictement le protocole.

                                      -
                                      Edité par zoup 16 septembre 2020 à 15:20:15

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        16 septembre 2020 à 16:09:17

                                        Oui effectivement, j'ai fait une fonction qui permet de calculer le CRC.

                                        Mais ça m'a l'air fastidieux mais ça reste une solution possible. Mais surtout que ça va me bouffer du temps de chercker toute la trame lecture, de vérifier le crc ect... 

                                        Pourquoi il n'y a pas un un meilleure moyen de gérer le flag car je pense que la solution se trouve au niveau de la fonction fnctl() et de la gestion des flags. 

                                        Genre j'aimerais que ça fasse ça : 

                                        mettre le flag à 1 au début de réception de la première trame du maitre, mettre le flag à 0 à la fin de la réception de la trame du maitre, mettre le flag à 1 au début de la trame de l'esclave 1, mettre le flag à 0 à la fin de la trame de l'esclave 1 et ainsi de suite.

                                        Comme ça j'aurai une bonne lecture des trames, au bon format, ni trop tôt, ni trop tard. 

                                        • Partager sur Facebook
                                        • Partager sur Twitter

                                        Problème de timing de lecture de trame RS485

                                        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                        • Editeur
                                        • Markdown