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

Composants VCL Delphi Discussion :

Problème de déclenchement d'évènements dans un timer


Sujet :

Composants VCL Delphi

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Développeur Objet
    Inscrit en
    Janvier 2006
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Objet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 21
    Points : 7
    Points
    7
    Par défaut Problème de déclenchement d'évènements dans un timer
    Je développe actuellement une application pour gérer une carte controleur d'une machine (qui effectue des mesures) via le port série.

    Cette carte à un fonctionnement tout à fait basique :
    - pour démarrer la machine : envoe du caractère 'D'
    - pour demander une mesure : envoi du caractère 'M'
    Ce que renvoi la carte :
    - machine démarrée : envoi de 'O'+entrée
    - mesure (après demande : envoi de la mesure (sur 2 octets) + entrée
    - arrêt du processus : envoi de 'E'+entrée

    Le développement de l'application dans un formulaire n'a pas pris beaucoup de temps. Mais je n'arrive pas à la faire passer sous forme de thread.

    J'ai l'impression que le trigger ne déclenche jamais lorsqu'il est dans le timer.

    Je me base sur le composant APro (Async Professionnal) 4.06 pouir la communication via port série.

    voici le code de mon thread, mon évènement sur arrivée de caractère dans le port série est désactivé :

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
     
    unit Etuve_GeFran_Thread;
    interface
    uses
      SysUtils, Classes, OoMisc, AdPort, Dialogs, Windows,ExtCtrls;
    type
      Thread_Etuve_GeFran = class(TThread)
        Etuve_ComPort : TApdComPort;
        CTimer:TTimer;
        procedure Trigger_EndProcess(CP : TObject; Count : Word);
      private
        process_on : boolean;
        procedure StartProcess;
        // lance le processus
        function GetMesure : double;
        // renvoie la valeur de la mesure en cours
        procedure TakeMesure(Sender: TObject);
        // demande de mesure et
        // sauvegarde du résultat dans la base de données
      protected
        // procedure d'exécution
        procedure Execute; override;
      public
        // constructeur
        constructor create( numPort : integer ; timer : integer );
      end;
    implementation
    const
      // constantes pour le calcul de la température
      a : double = 0.59814453;
      b : double = -112.5;
    ///////////////////////////////////////////////////////////////////////////
    // Procédures et fonction du Thread ///////////////////////////////////////
    // private ///////////////////////////////////////////////////
    // Procédure de démarrage du processus //
    Procedure Thread_Etuve_GeFran.StartProcess();
    var
      buffer : string;
    begin
      // envoi de la demande de démarrage
      Etuve_ComPort.Output:='D';
      // Attente des 2 caractères
      while not Etuve_ComPort.CharReady do begin end;//while
      buffer := Etuve_ComPort.GetChar;
      while not Etuve_ComPort.CharReady do begin end;//while
      buffer := buffer+Etuve_ComPort.GetChar;
      if ( (buffer = 'O'+char($0D)) and (not process_on) ) then
      begin
        process_on := true;
        Ctimer.Enabled:=true;
      end;
    end;//procedure
    // Fonction retournant la valeur en °C que mesure la sonde //
    Function Thread_Etuve_GeFran.GetMesure: double;
    var
      x : integer;
      buffer : string;
    begin
      // demande de température
      Etuve_ComPort.Output:='M';
      while not Etuve_ComPort.CharReady do begin end;//while
      buffer := Etuve_ComPort.GetChar;
      while not Etuve_ComPort.CharReady do begin end;//while
      buffer := buffer+Etuve_ComPort.GetChar;
      if ( (buffer = 'E'+char($0D)) and (process_on) ) then
      begin
        process_on := false;
        Ctimer.Enabled := false;
      end
      else
      begin
        while not Etuve_ComPort.CharReady do begin end;//while
        buffer := buffer+Etuve_ComPort.GetChar;
      end;//if
      x := (byte(buffer[1])*256)+(byte(buffer[2]));
      result := a*x+b;
    end;//function
    procedure Thread_Etuve_Gefran.TakeMesure(Sender: TObject);
    var
      mesure : double;
    begin
      // enregistrement de la mesure
      mesure := GetMesure;
      // Stockage de la mesure dans la base de données
      // ...
    end;//procedure
    // Trigger  de contrôle des entrées de caractères par le port série
    Procedure Thread_Etuve_Gefran.Trigger_EndProcess(CP : TObject; Count : Word);
    begin
    {  setlength(buffer,count);
      Etuve_ComPort.GetBlock(pointer(buffer)^,count);
      // test de la chaîne résultat
      if count = 2 then
      begin
        // mise en marche?
        if ( (buffer = 'O'+char($0D)) and (not process_on) ) then
        begin
          process_on := true;
        end//if
        else
        begin
          // fin de process?
          if ( (buffer = 'E'+char($0D)) and (process_on) ) then
          begin
            process_on := false;
            Etuve_ComPort.Open := false
          end//if
          else
          begin
            // erreur
            // signal d'erreur
          end;//if
        end;
      end
      else
      begin
        if count = 3 then
        begin
        end//if
        else
        begin
          // erreur
          // signal d'erreur
        end;
      end;  }
    end;//Trigger
    // protected //////////////////////////////////////////////////
    // Etuve_GeFran_Thread / Exécutable //
    procedure Thread_Etuve_GeFran.Execute;
    begin
      // ouverture du port de communication série
      Etuve_ComPort.Open := true;
      StartProcess;
    //  Ctimer.Enabled:=true;
      Etuve_ComPort.Open := false;
    end;//Execute
    // public /////////////////////////////////////////////////////
    // constructeur //
    constructor Thread_Etuve_GeFran.Create( numPort : integer ; timer : integer );
    begin
      FreeOnTerminate := true;
      //timer_thread := timer;       y
      process_on := false;
      inherited Create(false);
      Etuve_ComPort := TApdComPort.Create(nil);
      Ctimer:=TTimer.create(nil);
      Ctimer.enabled:=false;
      CTimer.Interval:=timer;
      CTimer.OnTimer:=TakeMesure;
      with Etuve_ComPort do
      begin
        Open := False;
        Baud := 19200;        // vitesse - baud
        ComNumber := numPort; // numéro de port
        DataBits:=8;
        Parity:=pnone;
    //    OnTriggerAvail := Trigger_EndProcess;
       end;//with
    end;//constructor
    end.//Thread

    PS: Je travaille sous Delphi 7

  2. #2
    Membre confirmé
    Avatar de Philippe Gormand
    Inscrit en
    Mars 2002
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 330
    Points : 647
    Points
    647
    Par défaut
    Analyser le problème.

    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
    constructor Thread_Etuve_GeFran.Create( numPort : integer ; timer : integer );
    begin
      FreeOnTerminate := true;
      //timer_thread := timer;       y
      process_on := false;
      inherited Create(false);
      // Pourquoi créer les objets à nil et non pas avec Self 
      // Avec Nil, il sont sensés n'avoir aucune référence
      Etuve_ComPort := TApdComPort.Create(nil);
      Ctimer:=TTimer.create(nil);
      Ctimer.enabled:=false;
      // Quelle est la valeur d'interval ?? <timer> 
      ?????CTimer.Interval:=timer;
      CTimer.OnTimer:=TakeMesure;
      with Etuve_ComPort do
      begin
        Open := False;
        Baud := 19200;        // vitesse - baud
        ComNumber := numPort; // numéro de port
        DataBits:=8;
        Parity:=pnone;
    //    OnTriggerAvail := Trigger_EndProcess;
       end;//with
    end;//constructor
    end.//Thread
    Je suggère une modification ici.

    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
    procedure Thread_Etuve_Gefran.TakeMesure(Sender: TObject);
    var
      mesure : double;
    begin
       // Stoper le timer pour laisser le temps à la fonction
       // GetMesure de terminer sont travail (avant redéclanchement
       // du Timer.
       CTimer.Enabled := False;
      // enregistrement de la mesure
      mesure := GetMesure;
      // Stockage de la mesure dans la base de données
      // Remetre en fonction le Timer si nécessaire
       If process_on Then CTimer.Enabled := True;
    end;//procedure

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Développeur Objet
    Inscrit en
    Janvier 2006
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Objet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 21
    Points : 7
    Points
    7
    Par défaut
    Je n'y avait pas pensé... merci . Je m'en vais tester...

    Sinon pour la création avec 'nil', je ne fais que suivre les directive qu'on me donne. On avait essayé de se servir de self, mais il me semble que ca plantait à la compilation.

    et la valeur du timer est de 1000.

    Mais en fait je souhaiterais que le trigger déclanche même lorsque le timer décompte, afin d'éviter que si on a le timer à 10min on ne soit pas obligé d'attendre ces 10 minutes pour savoir qu'il faut sortir du thread...

    Vous y voyez une solution plus efficace?

  4. #4
    Futur Membre du Club
    Homme Profil pro
    Développeur Objet
    Inscrit en
    Janvier 2006
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Objet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 21
    Points : 7
    Points
    7
    Par défaut
    J'ai tenté avec la modification mais le trigger ne déclenche toujours pas sur l'arrivée des caractères. Il n'y aurait rien qui en bloquerrait l'exécution? ou qui empècherait la détection de caractères dans le buffer d'entrée?

  5. #5
    Membre confirmé
    Avatar de Philippe Gormand
    Inscrit en
    Mars 2002
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 330
    Points : 647
    Points
    647
    Par défaut OnTriggerAvail
    Dans ton code, dans le constructeur, la ligne d'association de
    lévénement,est en commentaire.
    Donc, OnTriggerAvail ne déclanche rien du tout.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //    OnTriggerAvail := Trigger_EndProcess;

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Développeur Objet
    Inscrit en
    Janvier 2006
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Objet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 21
    Points : 7
    Points
    7
    Par défaut
    Non mais ca c'est normal C'est moi qui l'avait mis off pour quelques tests. J'ai précisé dans mon prmier post qu'il éttait désactivé dans le code.

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Développeur Objet
    Inscrit en
    Janvier 2006
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Objet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 21
    Points : 7
    Points
    7
    Par défaut
    Je met la dernière version du code que j'utilise, ici le trigger est activé. J'ai observé que le trigger se déclenchait si je coupait le port série à la fin de 'Execute'. Mais bon... cela déclenche une erreur pendant l'execution du trigger étant donné que le port est fermé .

    Quelqu'un sait si cela vien de delphi ou du composant? (Ou d'une bétise que j'aurais glissé dans le code, mais là ca fait 4 jours que je cherche et je ne trouve rien )

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
     
    unit Etuve_GeFran_Thread;
     
    interface
     
    uses
      SysUtils, Classes, OoMisc, AdPort, Dialogs, Windows,ExtCtrls;
    type
      Thread_Etuve_GeFran = class(TThread)
        Etuve_ComPort : TApdComPort;
        CTimer:TTimer;
        procedure Trigger_EndProcess(CP : TObject; Count : Word);
      private
        process_on : boolean;
        procedure StartProcess;
        // lance le processus
        function GetMesure : double;
        // renvoie la valeur de la mesure en cours
        procedure TakeMesure(Sender: TObject);
        // demande de mesure et
        // sauvegarde du résultat dans la base de données
      protected
        // procedure d'exécution
        procedure Execute; override;
      public
        // constructeur
        constructor create( numPort : integer ; timer : integer );
      end;
     
    implementation
     
    const
      // constantes pour le calcul de la température
      a : double = 0.59814453;
      b : double = -112.5;
     
    ///////////////////////////////////////////////////////////////////////////
    // Procédures et fonction du Thread ///////////////////////////////////////
     
    // private ///////////////////////////////////////////////////
     
    // Procédure de démarrage du processus //
    Procedure Thread_Etuve_GeFran.StartProcess();
    var
      buffer : string;
    begin
      // envoi de la demande de démarrage
      Etuve_ComPort.Output:='D';
    {
      // Attente des 2 caractères
      while not Etuve_ComPort.CharReady do begin end;//while
      buffer := Etuve_ComPort.GetChar;
      while not Etuve_ComPort.CharReady do begin end;//while
      buffer := buffer+Etuve_ComPort.GetChar;
      if ( (buffer = 'O'+char($0D)) and (not process_on) ) then
      begin
        process_on := true;
        Ctimer.Enabled:=true;
      end;
    }
    end;//procedure
     
    // Fonction retournant la valeur en °C que mesure la sonde //
    Function Thread_Etuve_GeFran.GetMesure: double;
    var
      x : integer;
      buffer : string;
    begin
      // demande de température
      Etuve_ComPort.Output:='M';
    {
      while not Etuve_ComPort.CharReady do begin end;//while
      buffer := Etuve_ComPort.GetChar;
      while not Etuve_ComPort.CharReady do begin end;//while
      buffer := buffer+Etuve_ComPort.GetChar;
      if ( (buffer = 'E'+char($0D)) and (process_on) ) then
      begin
        process_on := false;
        Ctimer.Enabled := false;
      end
      else
      begin
        while not Etuve_ComPort.CharReady do begin end;//while
        buffer := buffer+Etuve_ComPort.GetChar;
      end;//if
      x := (byte(buffer[1])*256)+(byte(buffer[2]));
      result := a*x+b;
    }
    end;//function
     
    procedure Thread_Etuve_Gefran.TakeMesure(Sender: TObject);
    var
      mesure : double;
    begin
      CTimer.Enabled := False;
      // enregistrement de la mesure
      mesure := GetMesure;
      // Stockage de la mesure dans la base de données
      // Remetre en fonction le Timer si nécessaire
       If process_on Then CTimer.Enabled := True;
    end;//procedure
     
    // Trigger  de contrôle des entrées de caractères par le port série
    Procedure Thread_Etuve_Gefran.Trigger_EndProcess(CP : TObject; Count : Word);
    var
      buffer : string;
    begin
      setlength(buffer,count);
      Etuve_ComPort.GetBlock(pointer(buffer)^,count);
      // test de la chaîne résultat
      if count = 2 then
      begin
        // mise en marche?
        if ( (buffer = 'O'+char($0D)) and (not process_on) ) then
        begin
          process_on := true;
        end//if
        else
        begin
          // fin de process?
          if ( (buffer = 'E'+char($0D)) and (process_on) ) then
          begin
            process_on := false;
            Etuve_ComPort.Open := false
          end//if
          else
          begin
            // erreur
            // signal d'erreur
          end;//if
        end;
      end
      else
      begin
        if count = 3 then
        begin
        end//if
        else
        begin
          // erreur
          // signal d'erreur
        end;
      end;
    end;//Trigger
     
    // protected //////////////////////////////////////////////////
     
    // Etuve_GeFran_Thread / Exécutable //
    procedure Thread_Etuve_GeFran.Execute;
    begin
      if not process_on then
      begin
        // ouverture du port de communication série
        Etuve_ComPort.AutoOpen := false;
        Etuve_ComPort.Open := true;
        StartProcess;
        Ctimer.Enabled:=true;
      //  Etuve_ComPort.Open := false;
      end;//if
    end;//Execute
     
    // public /////////////////////////////////////////////////////
     
    // constructeur //
    constructor Thread_Etuve_GeFran.Create( numPort : integer ; timer : integer );
    begin
      FreeOnTerminate := true;
      //timer_thread := timer;       y
      process_on := false;
      inherited Create(false);
      Etuve_ComPort := TApdComPort.Create(nil);
      Ctimer:=TTimer.create(nil);
      Ctimer.enabled:=false;
      CTimer.Interval:=timer;
      CTimer.OnTimer:=TakeMesure;
      with Etuve_ComPort do
      begin
        Open := False;
        Baud := 19200;        // vitesse - baud
        ComNumber := numPort; // numéro de port
        DataBits:=8;
        Parity:=pnone;
        OnTriggerAvail := Trigger_EndProcess;
       end;//with
    end;//constructor
     
    end.//Thread

  8. #8
    Membre confirmé
    Avatar de Philippe Gormand
    Inscrit en
    Mars 2002
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 330
    Points : 647
    Points
    647
    Par défaut ComPort suite
    Je ne vois rien dans le code, le paramétrage de l'événement
    OnTriggerAvail (réception d'un caractère particulié ?).

    De plus, après avoir passé la propriété Enabled du timer, il faut
    immédiatement passer le Thread en pause. Si non, il continu son
    process sans attendre la fin d'exécution du Timer. En effet c'est un
    message WINDOWS indépendant du Thread qui gère le Timer.
    C'est ensuite la fin d'exécution dela procédure du Timer qui devrait
    réactiver le Thread pour poursuivre le process (Thread_Etuve_GetFran.Resume).
    Enfin c'est dans cette voie qu'il faut chercher à mon avis, sans
    oublier dans la configuration de l'object PorCom le caractère de
    retour qui doit déclancher l'événement OnTriggerAvail.

  9. #9
    Membre émérite
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 504
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 504
    Points : 2 776
    Points
    2 776
    Billets dans le blog
    10
    Par défaut
    Tu peux essayer de mettre le code
    sleep(10)
    dans les boucles d'attente des caractères

    Et aussi gérer ta propre fonction Timer dans la partie execute du Thread
    en incrémentant une variable de type integer suivit d'une instruction sleep
    dans une boucle while d'attente de laquelle tu sors lorque le modulo de la division du nombre par une constante est égal à 0.

    J'ai rencontré ce problème il y a quelques années dans un processus industriel et je crois me souvenir l'avoir réglé de cette manière.

  10. #10
    Membre averti

    Homme Profil pro
    Inscrit en
    Octobre 2003
    Messages
    908
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 908
    Points : 447
    Points
    447
    Par défaut
    Euh petite question suite a ce que tu as dis Philippe Gormand, ça veut dire que ce st que le thread Principal qui pourra intercepter le message ?

  11. #11
    Membre confirmé
    Avatar de Philippe Gormand
    Inscrit en
    Mars 2002
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 330
    Points : 647
    Points
    647
    Par défaut TTimer
    Non.

    Ca veux dire que l'objet TTimer est completement automome et
    qu'il intercepte le message WINDOWS timer. Quelque soit le
    Thread qui le contient, l'événement OnTimer du TTimer se déclenchera
    tent que ça propriété Enabled sera à True.

    ALWEBER a dit.
    Tu peux essayer de mettre le code
    sleep(10)
    dans les boucles d'attente des caractères
    Cela ne résoudra rien, bien au contraire. Donc je repose la
    question. Comment ou quest ce qui peut provoquer l'événement
    OnTriggerAvail pour que l'objet PortCom puisse faire l'acquisition
    des retours de données ?


  12. #12
    Futur Membre du Club
    Homme Profil pro
    Développeur Objet
    Inscrit en
    Janvier 2006
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Objet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 21
    Points : 7
    Points
    7
    Par défaut
    L'arrivée d'un (ou plusieurs) octet(s) dans le buffer d'entrée du port série.

  13. #13
    Membre émérite
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 504
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 504
    Points : 2 776
    Points
    2 776
    Billets dans le blog
    10
    Par défaut
    Pour que je puisse t'aider peux tu me donner quelques indications
    sur la fonction execute. Cette fonction devrait tourner en boucle je ne vois rien de tel. D'autre part cette fonction devrait contenir un terminate pour s'autodétruire lorsque son travail est terminé.

  14. #14
    Futur Membre du Club
    Homme Profil pro
    Développeur Objet
    Inscrit en
    Janvier 2006
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Objet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 21
    Points : 7
    Points
    7
    Par défaut
    Etant donné que tout ce que j'ai tenté jusqu'ici ne fonctionne pas, je vais réespliquer mon problème en intégralité.

    Je cherche à développer un thread communiquant avec un périphérique renvoyant des mesures.

    Le thread me sert donc pour l'acquisition de mesure et leur sauvegarde.

    La machine (périphérique) avec lequel je communique fonctionne de manière simple :

    Je lui envoi un caractère 'D' pour demarrer.
    Pour me confirmer le demarrage la machine me renvoi 'O'+entrée.
    Une fois la session j'effectue mes mesures toutes les 10 minutes.
    Pour cela j'envoie le caractère 'M'. La machine me renvoie la mesure qu'elle effectu sur 3 octets.
    Le problème vien du fait qu'a tout moment après le demarrage la machine peut me renvoyer les caractères 'E'+entrée m'indiquant la fin du cycle de mesure. Et à ce moment là je ne suis plus sensé envoyer de demande de mesure.

    Pour effectuer mes mesures j'utilise un timer qui déclenche ma procédure d'envoi de caractère et qui attend la réception de la mesure.
    Et pour la réception du signal de fin j'utilise un trigger se déclenchant sur l'arrivée d'un ou plusieurs caractères dans le buffer.

    Je souhaiterai que dès que je reçois le signal de fin le timer se stoppe, et non pas qu'il attende la fin de son cycle pour se stopper.

    Mais je suis loin de connaître les subtilités de Delphi (je développe avec ce langage depuis quelques jours) et j'ai put passer a côté de choses importantes.

    Si quelqu'un à une idée sur la manière dont il faut s'y prendre je suis preneur (Je rappelle que la méthode que j'utilise actuellement ne fonctionne pas).

  15. #15
    Membre averti

    Homme Profil pro
    Inscrit en
    Octobre 2003
    Messages
    908
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 908
    Points : 447
    Points
    447
    Par défaut
    Philippe Gormand:
    Ca veux dire que l'objet TTimer est completement automome et
    qu'il intercepte le message WINDOWS timer. Quelque soit le
    Thread qui le contient, l'événement OnTimer du TTimer se déclenchera
    tent que ça propriété Enabled sera à True.
    Donc pourquoi dans ce cas la, pourquoi son thread ne pourrait pas fonctionner ?
    vu que dans la procédure Execute il n'y a meme pas de boucle, le thread n'est pas occupé a faire autre chose, il devrai pouvoir aller executer OntriggerAvail.

  16. #16
    Membre confirmé
    Avatar de Philippe Gormand
    Inscrit en
    Mars 2002
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 330
    Points : 647
    Points
    647
    Par défaut
    J'avais envoyé un précédent message qui n'est pas passé.


    Il y a une grosse bourde dans la procedure execute.

    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
    procedure Thread_Etuve_GeFran.Execute;
    begin
      if not process_on then
      begin
        // ouverture du port de communication série
        Etuve_ComPort.AutoOpen := false;
        Etuve_ComPort.Open := true;
     
        // la procedure n'est exécuté qu'une fois et le Thread continu
        StartProcess;
       // Bien qu'indépendant, le TTimer est contenu par le Thread
       // Si le Thread s'arrete, le TTimer aussi.
        Ctimer.Enabled:=true;
      //  Etuve_ComPort.Open := false;
      end;//if
    end;//Execute
    La procédure StartProcess();


    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
     
    // Procédure de démarrage du processus //
    Procedure Thread_Etuve_GeFran.StartProcess();
    var
      buffer : string;
    begin
      // envoi de la demande de démarrage
      Etuve_ComPort.Output:='D';
    {
      // Attente des 2 caractères
      while not Etuve_ComPort.CharReady do begin end;//while
      buffer := Etuve_ComPort.GetChar;
      while not Etuve_ComPort.CharReady do begin end;//while
      buffer := buffer+Etuve_ComPort.GetChar;
      if ( (buffer = 'O'+char($0D)) and (not process_on) ) then
      begin
        process_on := true;
        Ctimer.Enabled:=true;
      end;
    }
    end;//procedure
    Le Thread passe une fois dans la procédure StartProcess();
    puis s'arrete.
    Le mieux est d'utiliser une boucle du genre Repeat Until qui doit
    se terminer sur la condition d'une réception correcte, puis terminer
    l'action du Thread (Terminate).
    Attention au boucles tros rapides qui risquent de bloquer le système.
    Cela m'est déja arrivé. J'ai eu à traiter ce genre de problème de
    réception RS232 dans un Thread, mais il y a longtemps. Il faudrait
    que je cherche dans mes archives, mais je n'ai pas assez de temps
    en ce moment. Je suggère à ArkSquall de chercher des tutos sur le
    web, et de se plonger dans l'aide de DELPHI.

    Bon courage. Je serait absent la semaine prochaine, mais si je trouve un
    bon exemple, je transmetrais.

    A+

  17. #17
    Membre confirmé
    Avatar de Philippe Gormand
    Inscrit en
    Mars 2002
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 330
    Points : 647
    Points
    647
    Par défaut Suite
    Salut. Je ne tenais plus, alors j'ai beaucoup modifié ton code. Je ne garantis pas que ça marche, mais c'est dans cette voie qu'il faut
    chercher. Je n'ai pas ton composant, donc je n'ai pas pu vérifier.


    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
     
    unit Etuve_GeFran_Thread;
     
    interface
     
    uses
      SysUtils, Classes, OoMisc, AdPort, Dialogs, Windows,ExtCtrls;
    type
      Thread_Etuve_GeFran = class(TThread)
        Etuve_ComPort : TApdComPort;
        CTimer:TTimer;
        procedure Trigger_EndProcess(CP : TObject; Count : Word);
      private
        process_on : boolean;
        procedure StartProcess;
        // lance le processus
        procedure TakeMesure(Sender: TObject);
        // demande de mesure et
        // sauvegarde du résultat dans la base de données
      protected
        // procedure d'exécution
        procedure Execute; override;
      public
        // constructeur
        constructor create( numPort : integer ; timer : integer );
      end;
    Var
       Resultat : Double;
    implementation
    var
      x : integer;
    const
      // constantes pour le calcul de la température
      a : double = 0.59814453;
      b : double = -112.5;
    ///////////////////////////////////////////////////////////////////////////
    // Procédures et fonction du Thread ///////////////////////////////////////
    // private ///////////////////////////////////////////////////
    // Procédure de démarrage du processus //
    Procedure Thread_Etuve_GeFran.StartProcess();
    var
      buffer : string;
    begin
      // envoi de la demande de démarrage
      Etuve_ComPort.Output:='D';
    end;
    //------------------------------------------------------------------------
    procedure Thread_Etuve_Gefran.TakeMesure(Sender: TObject);
    var
      mesure : double;
    begin
      CTimer.Enabled := False;
      // Demande de lecture
      Etuve_ComPort.Output:='M';
    end;
    //------------------------------------------------------------------------
    // Trigger  de contrôle des entrées de caractères par le port série
    Procedure Thread_Etuve_Gefran.Trigger_EndProcess(CP : TObject; Count : Word);
    var
      buffer : string;
    begin
      // Réception
      setlength(buffer,count);
      Etuve_ComPort.GetBlock(pointer(buffer)^,count);
      // Attente des 2 caractères
      // test de la chaîne résultat
      if count = 2 then
      begin
        // mise en marche?
        if ( (buffer = 'O'+char($0D)) and (not process_on) ) then
        begin
          process_on := true;
        end//if
        else
        begin
          // fin de process?
          if ( (buffer = 'E'+char($0D)) and (process_on) ) then
          begin
            process_on := false;
            Etuve_ComPort.Open := false
            Fin := True;
          end
          else
          begin
             // GetMesure
             x := (byte(buffer[1])*256)+(byte(buffer[2]));
             resultat := a*x+b;
             // Stockage de la mesure dans la base de données
             // Remetre en fonction le Timer si nécessaire
             If process_on Then CTimer.Enabled := True;
             Fin := True;
          end;//if
        end;
      end
      else
      begin
        if count = 3 then
        begin
        end//if
        else
        begin
          // erreur
          // signal d'erreur
          Fin := True;
        end;
      end;
    end;//Trigger
    //------------------------------------------------------------------------
    // protected //////////////////////////////////////////////////
    // Etuve_GeFran_Thread / Exécutable //
    procedure Thread_Etuve_GeFran.Execute;
    begin
      if not process_on then
      begin
        // ouverture du port de communication série
        Etuve_ComPort.AutoOpen := false;
        Etuve_ComPort.Open := true;
        StartProcess;
        Ctimer.Enabled:=true;
        Repeat
           Sleep(100);
        Until Fin;
        Etuve_ComPort.Open := false;
        Ctimer.Enabled:=False;
        Terminate;
      end;//if
    end;//Execute
    //------------------------------------------------------------------------
    // public /////////////////////////////////////////////////////
    // constructeur //
    constructor Thread_Etuve_GeFran.Create( numPort : integer ; timer : integer );
    begin
      FreeOnTerminate := true;
      //timer_thread := timer;       y
      process_on := false;
      inherited Create(false);
      Etuve_ComPort := TApdComPort.Create(nil);
      Ctimer:=TTimer.create(nil);
      Ctimer.enabled:=false;
      CTimer.Interval:=500;
      CTimer.OnTimer:=TakeMesure;
      with Etuve_ComPort do
      begin
        Open := False;
        Baud := 19200;        // vitesse - baud
        ComNumber := numPort; // numéro de port
        DataBits:=8;
        Parity:=pnone;
        OnTriggerAvail := Trigger_EndProcess;
       end;//with
    end;//constructor
    end.//Thread
    En tout cas, c'est comme cela que j'attaquerais.

    Bon courage.

  18. #18
    Futur Membre du Club
    Homme Profil pro
    Développeur Objet
    Inscrit en
    Janvier 2006
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Objet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 21
    Points : 7
    Points
    7
    Par défaut
    Merci c'est cool. Je vais voir ce que je peux en faire.

  19. #19
    Membre émérite
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 504
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 504
    Points : 2 776
    Points
    2 776
    Billets dans le blog
    10
    Par défaut
    Voici un petit exemple pour mieux comprendre les threads. j'ai reproduit de manière succinte ton cahier des charges. Tu double clic dans la listBox pour provoquer les évènements. Si tu as besoin de quelques explications n'hésite pas

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    unit Ex20a;
    interface
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      ExtCtrls, StdCtrls;
    type
      TForm1 = class(TForm)
        Panel1: TPanel;
        Timer1: TTimer;
        ListBox1: TListBox;
        Memo1: TMemo;
        procedure ListBox1DblClick(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
        procedure FormActivate(Sender: TObject);
      private
      public
      end;
      TThread1 = class(TThread)
      private
        fPanel1 : TPanel ;
        fSl1 : TStrings ;
        fTimer1: TTimer;
        LW1 : Longword ;
      protected
        procedure Execute; override;
      public
        constructor Create(Panel1 : TPanel; Sl1 : TStrings; Timer1: TTimer);
      end ;
    var
      Form1: TForm1;
      Thread1 : TThread1;
      St_ATraiter : string ;
    implementation
    {$R *.DFM}
    procedure TThread1.Execute;
    begin
      while true do
      begin
        sleep (10) ;
        LW1 := LW1 + 1 ;
        if LW1 mod 100 = 0 then
          FPanel1.Caption := IntToStr (LW1  Div 100) ;
        if St_ATraiter<>'' then
          case St_ATraiter[1] of
          'D' : FSl1.add ('Ordi envoi D à Automate') ;
          'O' : FSl1.add ('Automate envoi O à Ordi') ;
          'M' : FSl1.add ('Ordi envoi M à Automate') ;
          '0'..'9' : FSl1.add ('Automate envoi '+St_ATraiter+' à Ordi') ;
          'E' : begin
            FSl1.add ('Automate envoi E à Ordi') ;
            Thread1.Terminate ;
            fTimer1.Enabled := false ;
          end ;
          end ;
        St_ATraiter := '' ;
        if Terminated then
          Exit;
      end ;
    end ;
    constructor TThread1.Create(Panel1 : TPanel; Sl1 : TStrings;Timer1: TTimer);
    begin
      fPanel1 := Panel1 ;
      fSl1 := sl1 ;
      LW1 := 0 ;
      FreeOnTerminate := True;
      inherited Create(False);
    end ;
     
    procedure TForm1.ListBox1DblClick(Sender: TObject);
    var
      c1 : char ;
    begin
      c1 := ListBox1.items[ListBox1.ItemIndex ][1] ;
      case c1 of
      'D' : begin
            Thread1 := TThread1.Create(Panel1,Memo1.Lines,Timer1) ;
            Timer1.Enabled := true ;
            Memo1.lines.clear ;
            St_ATraiter := 'D' ;
          end ;
      'O','E' : St_ATraiter := c1 ;
      'N' : St_ATraiter := intToStr(Random(900)+100) ;
      end ;
    end;
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      St_ATraiter := 'M' ;
    end;
    procedure TForm1.FormActivate(Sender: TObject);
    begin
    With ListBox1.items do
    begin
      clear ; add ('D') ;  add ('O') ;  add ('N') ;  add ('E') ;
    end ;
    Timer1.Interval := 9000 ;
    end;
    end.

Discussions similaires

  1. [Symfony2][Calendrier] problème de déplacement des événements dans wdCalendar.
    Par basboustunis dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 0
    Dernier message: 23/04/2014, 15h54
  2. Problème évènements dans clips imbriqués
    Par Aboshan441 dans le forum ActionScript 1 & ActionScript 2
    Réponses: 2
    Dernier message: 05/04/2008, 14h15
  3. [C#] Problème déclenchement événement dans page_load
    Par LE NEINDRE dans le forum ASP.NET
    Réponses: 1
    Dernier message: 17/01/2008, 13h51
  4. Problème de compteur dans un timer
    Par mcspawn dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 21/12/2007, 19h23
  5. [VB.NET 2005]Problème de déclenchement d'évènements
    Par LTourist dans le forum Windows Forms
    Réponses: 4
    Dernier message: 04/07/2006, 16h39

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