IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Lazarus Pascal Discussion :

Problème avec TBlockSerial de la bibliothèque Synaser et Raspberry


Sujet :

Lazarus Pascal

  1. #1
    Membre émérite
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 122
    Par défaut Problème avec TBlockSerial de la bibliothèque Synaser et Raspberry
    Bonsoir à toutes et à tous,

    Dans une application GPS que je développe, j'utilise le composant TBlockSerial pour lire les infos que me délivre mon module GPS (via Bluetooth). Avec mon PC sous Windows, cela se passe bien, mais avec mon Raspberry Pi3B (Raspbian Stretch), ça plante au bout de quelques minutes avec le message d'erreur "'Timeout during operation" Voilà le code que j'exécute dans un thread:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    procedure TMyThread.Execute;
    begin
      {$IFDEF WIN32}
          PortCOM.Connect('COM21'); // Port de mon PC sous Windows
      {$ENDIF}
      {$IFDEF LINUX}
        {$IFDEF CPUARM}
          PortCOM.Connect('/dev/rfcomm0'); // Port de mon Raspberry
        {$ELSE}
          PortCOM.Connect('/dev/ttyS21');
        {$ENDIF}
      {$ENDIF}
      PortCOM.Config(4800, 8, 'N', 1, False, False);
      while not Terminated do
      begin // Réception de 6 trames toutes les secondes
        InfoNMEA:= PortCOM.Recvstring(2000); // Le fait de mettre autre chose que 2000 ne change rien à l'affaire
        if PortCOM.LasrError = ErrTimeout then
         InfoNMEA:= InfoNMEA;
        Synchronize(@Showstatus);
      end;
      PortCOM.CloseSocket;
      FreeAndNil(PortCOM);
    end;
    Grâce au débogueur, qui fonctionne bien dans le thread, je vois que ça tourne en boucle à l'intérieur de mon "while" et, comme à chaque lecture, l'erreur persiste, je passe à chaque tour par mon " InfoNMEA:=InfoNMEA;" que j'ai mis là juste pour mettre en évidence le problème. NOTA : à ce moment, InfoNMEA est une chaîne vide.

    Question, comment sort-on de cette boucle infernale ?

    Cordialement.

    Pierre

  2. #2
    Membre Expert
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Billets dans le blog
    2
    Par défaut
    Salut, peut-être en ajoutant une section critique (TCriticalSection)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    procedure TMyThread.Create;
    begin
      ....
      tcs := TCriticalSection.Create;
      ...
     
    end;
    procedure TMyThread.Execute;
    begin
       tcs.Enter;
      {$IFDEF WIN32}
          PortCOM.Connect('COM21'); // Port de mon PC sous Windows
      {$ENDIF}
      {$IFDEF LINUX}
        {$IFDEF CPUARM}
          PortCOM.Connect('/dev/rfcomm0'); // Port de mon Raspberry
        {$ELSE}
          PortCOM.Connect('/dev/ttyS21');
        {$ENDIF}
      {$ENDIF}
      PortCOM.Config(4800, 8, 'N', 1, False, False);
      while not Terminated do
      begin // Réception de 6 trames toutes les secondes
        InfoNMEA:= PortCOM.Recvstring(2000); // Le fait de mettre autre chose que 2000 ne change rien à l'affaire
        if PortCOM.LasrError = ErrTimeout then
         InfoNMEA:= InfoNMEA;
        Synchronize(@Showstatus);
      end;
      PortCOM.CloseSocket;
      FreeAndNil(PortCOM);
      tcs.Leave;
    end;
    Question : pourquoi te connecter et te déconnecter de ton port à chaque fois ? Pourquoi ne pas utiliser une variable globale dans ta classe ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    procedure TMyThread.Create;
    begin
      ....
      tcs := TCriticalSection.Create;
      ...
    // Ou a placer ailleurs
    {$IFDEF WIN32}
          PortCOM.Connect('COM21'); // Port de mon PC sous Windows
      {$ENDIF}
      {$IFDEF LINUX}
        {$IFDEF CPUARM}
          PortCOM.Connect('/dev/rfcomm0'); // Port de mon Raspberry
        {$ELSE}
          PortCOM.Connect('/dev/ttyS21');
        {$ENDIF}
      {$ENDIF}
      PortCOM.Config(4800, 8, 'N', 1, False, False);
     
    end;
    procedure TMyThread.Execute;
    begin
      tcs.Enter;  
      while not Terminated do
      begin // Réception de 6 trames toutes les secondes
        InfoNMEA:= PortCOM.Recvstring(2000); // Le fait de mettre autre chose que 2000 ne change rien à l'affaire
        if PortCOM.LasrError = ErrTimeout then
         InfoNMEA:= InfoNMEA;
        Synchronize(@Showstatus);
      end;
      PortCOM.CloseSocket;
      tcs.Leave;
    end;
     
    procedure TMyThread.Destroy;
    begin
      ...
      FreeAndNil(PortCOM);
      FreeAndNil(tcs);
      ...
    A+
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  3. #3
    Membre émérite
    Avatar de ChPr
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    2 122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : France, Val d'Oise (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 2 122
    Par défaut
    Citation Envoyé par BeanzMaster Voir le message
    Salut peut-être ne ajoutant une section critique (TCriticalSection) ...
    Je n'ai pas l'impression que cela ait modifié grand chose. Apparemment, une section critique empêche un thread concurrent d'intervenir : je n'en ai pas ici.

    Citation Envoyé par BeanzMaster Voir le message
    ..Question : pourquoi te connecter et te deconnecter de ton port à chaque fois ? pourquoi ne pas utiliser une variable globale dans ta classe ? ...
    J'ai été amené à modifier tel que suit ma procédure "Execute" car je me suis aperçu que lorsque j'avais l'erreur "ErrTimeout", le fait de me déconnecter et me reconnecter fonctionnait.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    procedure TThreadGPS.Execute;
    begin
      {$IFDEF WIN32}
          PortCOM.Connect('COM21');
      {$ENDIF}
      {$IFDEF LINUX}
        {$IFDEF CPUARM}
          PortCOM.Connect('/dev/rfcomm0');
        {$ELSE}
          PortCOM.Connect('/dev/ttyS21');
        {$ENDIF}
      {$ENDIF}
      tcs.Enter;
      Reprendre:= False;
      PortCOM.Config(4800, 8, 'N', 1, False, False);
      while (not Terminated) and (not Reprendre) do
      begin
        InfoNMEA:= PortCOM.Recvstring(2000);
        if InfoNMEA <> '' then
          Synchronize(@Showstatus);
        if PortCOM.LastError = ErrTimeout then // sur cette erreur, je vis me déconnecter puis me reconnecter
        begin
          PortCOM.Purge;
          Reprendre:= True;
          Inc(Pb); // Nombre de fois où apparaît le problème -> transmis au thread principal par "synchronise"
        end;
      end;
      tcs.Leave;
      PortCOM.CloseSocket; // Déconnexion
      if Reprendre then
        Execute // Reprise de la connexion
      else
        FreeAndNil(PortCOM);
    end;
    La parade ne semble pas totale, mais assez efficace pour l'instant. Mais je reconnais que ce n'est qu'une rustine

    Cordialement.

    Pierre

Discussions similaires

  1. Réponses: 3
    Dernier message: 12/05/2019, 13h59
  2. problème avec bibliothéque Gtk
    Par lili81 dans le forum C++Builder
    Réponses: 0
    Dernier message: 22/10/2008, 13h30
  3. problème avec la bibliothèque multimedia microsoft
    Par oduss dans le forum Microsoft Office
    Réponses: 0
    Dernier message: 05/02/2008, 11h35
  4. Problème avec la "Gestion des bibliothèques dynamiques"
    Par GoustiFruit dans le forum Delphi
    Réponses: 15
    Dernier message: 31/05/2006, 09h54
  5. Problème avec la bibliothèque glut
    Par lia dans le forum GLUT
    Réponses: 10
    Dernier message: 20/02/2006, 09h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo