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

Automation Discussion :

[Modbus] rs485 2 fils / rs 232


Sujet :

Automation

  1. #1
    Futur Membre du Club
    Inscrit en
    Décembre 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut [Modbus] rs485 2 fils / rs 232
    Bonjours a tous,

    Voila, je dois établir un communication entre un PC et un régulateur West 6100+.
    Je dois aller, avec un petit programme que j'ai conçu en delphi, écrire une valeur de température dans un registre d'alarme.
    Dans un premier temps, et ayant qu'un seul West donc un seul esclave, je souhaite envoyer la valeur en broadcast (pas répose de l'esclave dans ce cas).

    Mon programme envoi bien la trame sur le port serie (testé avec hyper terminal sur un deuxieme port, et les deux port reliés entre eux).

    donc, je pense a deux probleme, soit ma trame n'est pas valide, soit mon convertisseur rs232/rs485 est mal configuré.



    la trame que j'envoie est par exemple pour 0°c: 00 06 000D 0000 79EF

    00 etant l'adresse de braodcast
    06 la fonction modbus écriture d'un registre
    000D adresse du registre
    0000 la valeur 0°c en hexa
    79EF est mon CRC sous la formr Poid faible/Poid fort

    mon covertisseur >> http://radiospares-fr.rs-online.com/...hTerm=627-4572

    mon régulateur >> http://www.westinstruments.com/uploa...l_(French).pdf


    En vous remerciant par avance,

    Cordialement,

    Jonathan

    EDIT: Je suis entrain de penser a quelque chose, j'envoi ma trame telle quelle: 0006000D000079EF grace au composant Delphi Tcomport (j'ai suivi l'exelent tutoriel de nono40) avec l'instruction "writestr" mais en aucun cas je converti ma trame en octets, serait-ce mon probleme?

  2. #2
    Expert éminent sénior

    Avatar de Nono40
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2002
    Messages
    8 640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2002
    Messages : 8 640
    Points : 19 101
    Points
    19 101
    Par défaut
    Pour le convertisseur, j'ai déjà utilisé ce modèle. Tu as déjà le comutateur de prise de ligne à régler : sur TxON (vu que tu n'attend pas de réponse)

    Pour l'autre commutateur DCE/DTE tu as une chance sur deux suivant ton cablage

    Coté Delphi avec WriteStr c'est possible mais il faudrait que tu nous montre comment tu remplis la chaine.

    PS : content que mon tuto t'est étét utile.
    Delphi :
    La F.A.Q. , 877 réponses à vos questions !
    264 sources à consulter/télécharger !

  3. #3
    Membre habitué
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 90
    Points : 126
    Points
    126
    Par défaut
    Hello,

    Citation Envoyé par GingermaN Voir le message
    la trame que j'envoie est par exemple pour 0°c: 00 06 000D 0000 79EF

    00 etant l'adresse de braodcast
    06 la fonction modbus écriture d'un registre
    000D adresse du registre
    0000 la valeur 0°c en hexa
    79EF est mon CRC sous la formr Poid faible/Poid fort
    Comment calcules-tu le CRC ?
    Perso, sur la trame que tu indiques (00 06 00 0D 00 00), je trouve 19 D8...

  4. #4
    Futur Membre du Club
    Inscrit en
    Décembre 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    Tout d'abord merci de vous être intéressés au sujet.

    @Nono40 :
    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
    //////////////////// Assemblage et envoi de la trame ///////////////////////////
    procedure TForm1.ButEnvoiClick(Sender: TObject);
    var
      CRC,CRC_Lo,CRC_Hi:string;
    begin
    {ouverture du port COM}
      comport1.Connected:=true;
      ButEnvoi.Enabled:=false;
    {Conversion de la valeur de l'alarme en Hexa}
    ConcatenerValAlarme:=PanChiffre1.caption+PanChiffre2.caption+PanChiffre3.caption;
      ValeurAlarme:=StrToInt(ConcatenerValAlarme);
      Data:=inttohex(ValeurAlarme,4);
    {Construction de l'entete de la trame}
      Esclave:=IntToHex(StrToInt(CbxEsclave.Text),2);
      CodeFonction:=IntToHex(StrToInt(EditCdFct.Text),2);
      NumPara6100:=IntToHex(StrToInt(EditNumPara6100.Text),4);
    {Assemblage de la trame sans CRC16}
      TrameModbus:=Esclave+CodeFonction+NumPara6100+Data;
      LabValAlmHex2.Caption:=Data;
    {Calcul de CRC16}
      CRC:=CalcCRC16(TrameModbus);
      LabValCRC2.Caption:=CRC;
    {Transformation du CRC en Pf/PF}
      CRC_Lo:=CRC[3]+CRC[4];
      CRC_Hi:=CRC[1]+CRC[2];
    {Assemblage de la trame complete}
      TrameModbusCRC16:=TrameModbus+CRC_lo+CRC_Hi;
      LabTrameEnv2.Caption:=TrameModbusCRC16;
    {écriture de la trame sur le port COM}
      comport1.WriteStr(TrameModbusCRC16);
    {fermeture de port COM}
      comport1.Connected:=false;
      ButEnvoi.Enabled:=true;
    end;
    ////////////////////////////////////////////////////////////////////////////////
    Par contre, j'ai testé en rebouclant mon port COM1 sur le 2 et connectant l'hyper terminal sur le 2 je reçois bien la trame.

    @ Poil_dur

    Voici ma fonction de calcul de mon CRC:

    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
    /////////////////////// Fonction de calcul du CRC-16 ///////////////////////////
    Function calcCRC16(trame:string):string;
    var
      octet:char;
      ajout:boolean;
      CRC16:WORD;
      i,j:integer;
    begin
      CRC16 := $FFFF;
      for i := 1 to length(trame) do
      begin
        octet := trame[i];
        CRC16 := (CRC16) xor ord(octet);
        for j := 1 to 8 do
        begin
          Ajout := odd (CRC16) ;
          CRC16 := CRC16 div 2;
          if ajout then CRC16 := CRC16 xor $A001;
        end;
      end;
      result := IntToHex(CRC16, 4);
    end;
    ////////////////////////////////////////////////////////////////////////////////
    Voila, en tout ca encore merci, car cela fait maintenant une semaine que je tourne en rond.

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 26
    Points : 34
    Points
    34
    Par défaut
    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
    // Compute checksum
    function TModBus.CRC16(Buf: TMBusBuf; Len: Word): Word;
    var
    	CS: Word;
      Index, Shift: integer;
    begin
    	CS := $FFFF;
    	for Index := 0 to Len-1 do
    	begin
        	CS := CS xor Byte(Buf[Index]);
    	  	for Shift := 0 to 7 do
        	begin
      			if (CS and $0001) = $0001 then
      			begin
         			CS := CS shr 1;
            	CS := CS xor $A001;
            end
         		else
         			CS := CS shr 1;
      		end;
    	end;
    	result := CS;
    end;

  6. #6
    Expert éminent sénior

    Avatar de Nono40
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2002
    Messages
    8 640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2002
    Messages : 8 640
    Points : 19 101
    Points
    19 101
    Par défaut
    Tu confods affichage hexadécimal sous forme de chaine et binaire.
    Pas exemple si Chaine:'01' et que tu envoiezs chaine sur le liaison série, tu vas envoyer le caractère '0' puis le caractère '1'. Donc en fait tu vas envoyer la valeur 48 (acractère 0) puis la valeur 49 (caractère 1).

    Il ne faut pas utiliser inttohex pour calculer une trame à envoyer. Tu dois ajouter les caractères à la chaine sans les transformer. Delphi à cet avantage qu'un caractère #0 ne gène pas.

    D'autre part sur les mots de 16 bits (adresse) il faut tenir compte du sens des deux octects
    Voici un extrait de ton code tel qu'il faudrait le faire :
    Code delphi : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    {Construction de l'entete de la trame}
      Esclave:=Chr(StrToInt(CbxEsclave.Text));
      CodeFonction:=Chr(StrToInt(EditCdFct.Text));
      Valeur := StrToInt(EditNumPara6100.Text);
      NumPara6100:=Chr(Valeur Shr 8)+chr(Valeur And 255);
    {Assemblage de la trame sans CRC16}
      TrameModbus:=Esclave+CodeFonction+NumPara6100+Data;
    En faisant comme cela tu auras les octets corrects à envoyer, mais attention, si tu les mets dans un .caption ce ne sera pas lisible. de même que l'affichage dans un hyperterminal ne le sera pas.
    Delphi :
    La F.A.Q. , 877 réponses à vos questions !
    264 sources à consulter/télécharger !

  7. #7
    Futur Membre du Club
    Inscrit en
    Décembre 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    Citation Envoyé par GingermaN
    EDIT: Je suis entrain de penser a quelque chose, j'envoi ma trame telle quelle: 0006000D000079EF grace au composant Delphi Tcomport (j'ai suivi l'exelent tutoriel de nono40) avec l'instruction "writestr" mais en aucun cas je converti ma trame en octets, serait-ce mon probleme?
    Excuse moi nono40, je suis un boulet , je voulais dire binaire. Donc ça viens bien de la. MERCI Nono40 je vais essayer et je te tiens au courant.

    Yom3k, Tu utilises une librairie modbus? que représente le type TMbusBuf?
    La variable Len corespond a ma trame?
    Je commence a etre un peu perdu avec ce CRC-16 j'ai 6-7 version différente de calcul et a chaque le resultat est different

    En tout cas merci de vous etre penché sur mon cas.


  8. #8
    Futur Membre du Club
    Inscrit en
    Décembre 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    Donc est ce que la sa vous semble mieux? je ne peux pas encore testé car le systeme est en fonctionnement.

    Donc pour la construction de la trame et l'envoi:
    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
    //////////////////// Assemblage et envoi de la trame ///////////////////////////
    procedure TForm1.ButEnvoiClick(Sender: TObject);
    var
      CRC:word;
    begin
    
    {ouverture du port COM}
       comport1.Connected:=true;
       ButEnvoi.Enabled:=false;
    
    {Conversion de la valeur de l'alarme en Hexa}
      ConcatenerValAlarme:=PanChiffre1.caption+PanChiffre2.caption+PanChiffre3.caption;
      ValeurAlarme:=StrToInt(ConcatenerValAlarme);
      Data:=inttohex(ValeurAlarme,4);
      LabValAlmHex2.Caption:=Data;
    
    
    {Construction de l'entete de la trame}
      {Esclave:=IntToHex(StrToInt(CbxEsclave.Text),2);
      CodeFonction:=IntToHex(StrToInt(EditCdFct.Text),2);//ancienne version
      NumPara6100:=IntToHex(StrToInt(EditNumPara6100.Text),4);}
      Esclave:=Chr(StrToInt(CbxEsclave.Text));
      CodeFonction:=Chr(StrToInt(EditCdFct.Text));
      Valeur := StrToInt(EditNumPara6100.Text);
      NumPara6100:=Chr(Valeur Shr 8)+chr(Valeur And 255);
      DataBin:= chr(valeurAlarme);
    
    {Assemblage de la trame sans CRC16}
      TrameModbus:=Esclave+CodeFonction+NumPara6100+DataBin;
    
    
    {Calcul de CRC16}
      CRC:=CalcCRC16(TrameModbus);
    
    {Transformation du CRC en Pf/PF}
      CRC:=Swap(CRC);
      LabValCRC2.Caption:=intToSTr(CRC);
    
    {Assemblage de la trame complete}
      TrameModbusCRC16:=TrameModbus+chr(CRC);
      LabTrameEnv2.Caption:=(TrameModbusCRC16);
    
    {fermeture de port COM}
      comport1.Connected:=false;
      ButEnvoi.Enabled:=true;
    end;
    ////////////////////////////////////////////////////////////////////////////////
    et pour le calcul du CRC-16, par contre ce n'est pas la version de Yome3k car je n'ai pas su l'adapter, ne sachant pas a quoi correspond TMbusBuf. C'est une des autres nombreuse version que l'on m'a proposé.

    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
    /////////////////////// Fonction de calcul du CRC-16 ///////////////////////////
    function calcCRC16(s: string): word;
    var
      i, j: integer;
      w, x: word;
    begin
      w := $FFFF;
      for i := 1 to length(s) do
      begin
        x := ord(s[i]);
        w := w xor x;
        for j := 1 to 8 do
        begin
          if W and $0001 = $0001 then
          begin
            w := w shr 1;
            w := w xor $A001;
          end
          else
            w := w shr 1;
        end;
      end;
      result := w;
    end;
    Voila en esperant que vous jetterai un petit coup d'oeil

    Et si, aussi nono, sur le bornier du convertisseur, est- ce qu'il faut relier T+ a R+ et T- a R- et est ce que si je branche l'alim externe de celui-ci, il faut mettre un commun sur la borne5 du bornier?


  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    26
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 26
    Points : 34
    Points
    34
    Par défaut
    Je joint le code de mon composant (basé sur TComPort) :

    Code delphi : 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
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
     
    unit MBusCPort;
    {$I CPort.inc}
     
    interface
     
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      CPort;
     
    const
    	Buf_Size    = 260;
    	Max_Words   = 127;
      Max_Bits    = 2040;
     
      MBus_Func_ReadCoilStatus        = 1;
      MBus_Func_ReadInputStatus       = 2;
    	MBus_Func_ReadNHoldingRegister  = 3;
      MBus_Func_ReadNInputRegister    = 4;
      MBus_Func_WriteCoil             = 5;
      MBus_Func_Write1Register        = 6;
      MBus_Func_WriteNCoil            = 15;
      MBus_Func_WriteNRegister        = 16;
     
      BitWeight : array[0..7] of byte = (1, 2, 4, 8, 16, 32, 64, 128);
     
     
    type
    	TMBusBuf     = array[0..Buf_Size-1] of Byte;
     
      TMBusErrCode = (MBus_OK,MBus_ERR_SEND, MBus_ERR_READ,
                    MBus_ERR_NOANSWER,MBus_ERR_ANSWER,MBus_ERR_EXCEPTION,
                    MBus_ERR_DIFFUSION,MBus_ERR_NUMBER);
     
      TMBusReqType = (InputRegister, HoldingRegister, InputStatus, CoilStatus);
     
      TMBusWordsArray   = array[0..Max_Words-1] of smallint;
      TMBusBitsArray    = array[0..Max_Bits-1] of byte;
     
      TModBus = class(TCustomComPort)
      private
        FSlaveNum     : Byte;
        FAddress   	  : Word;
        FNumElements	: Word;
        FRequestSz  	: Word;
        FAnswerSz   	: Word;
        FFuncCode     : Byte;
        FRequestBuf 	: TMBusBuf;
        FAnswerBuf  	: TMBusBuf;
        FErrorCode    : TMBusErrCode;
        FWordsArray   : TMBusWordsArray;
        FBitsArray    : TMBusBitsArray;
      protected
        procedure DoAfterOpen; override;
        procedure DoError(Errors: TComErrors); override;
        procedure DoRxChar(Count: Integer); override;
      public
        constructor Create(AOwner: TComponent); override;
        function CRC16(Buf: TMBusBuf; Len: Word): Word;
        function AnalyseAnswer(Buf: TMBusBuf; Len: Word): TMBusErrCode;
        procedure BuildHeader(var Buf: TMBusBuf; SlaveNum: Byte; FuncCode: Byte; Address: Word; NumElements: Word = 0);
        procedure ReadNRegister(SlaveNum: Byte; Address: Word; NumElements: Word; RequestType: TMBusReqType);
        procedure WriteNRegister(SlaveNum: Byte; Address: Word; NumElements: Word; Value: array of Word);
        procedure Write1Register(SlaveNum: Byte; Address: Word; Value: Word);    
        procedure WriteNCoil(SlaveNum: Byte; Address: Word; NumElements: Word; Value: array of Byte);
        procedure WriteCoil(SlaveNum: Byte; Address: Word; Value: Boolean);
        procedure ReadCoilInputStatus(SlaveNum: Byte; Address: Word; NumElements: Word; RequestType: TMBusReqType);      
     
        property SlaveNum     : Byte read FSlaveNum write FSlaveNum;
        property Address    	: Word read FAddress write FAddress;
        property NumElements	: Word read FNumElements write FNumElements;
        property FuncCode   	: Byte read FFuncCode write FFuncCode;
        property RequestSz  	: Word read FRequestSz write FRequestSz;
        property AnswerSz   	: Word read FAnswerSz write FAnswerSz;        
        property RequestBuf 	: TMBusBuf read FRequestBuf write FRequestBuf;
        property AnswerBuf  	: TMBusBuf read FAnswerBuf write FAnswerBuf;
        property ErrorCode    : TMBusErrCode read FErrorCode write FErrorCode;
        property WordsArray   : TMBusWordsArray read FWordsArray write FWordsArray;
        property BitsArray    : TMBusBitsArray read FBitsArray write FBitsArray;    
      published
        property Connected;
        property BaudRate;
        property Port;
        property Parity;
        property StopBits;
        property DataBits;
        property DiscardNull;
        property EventChar;
        property Events;
        property Buffer;
        property FlowControl;
        property Timeouts;
        property SyncMethod;
     
      end;
     
    procedure Register;
     
    implementation
     
     
    procedure Register;
    begin
      RegisterComponents('ModBus', [TModBus]);
    end;
     
    constructor TModBus.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      Timeouts.ReadInterval := 100;
      Timeouts.ReadTotalMultiplier := 100;
      Timeouts.ReadTotalConstant := 100;
    end;
     
    procedure TModBus.DoAfterOpen;
    begin
      inherited DoAfterOpen;
    end;
     
    procedure TModBus.DoRxChar(Count: Integer);
    begin
      inherited DoRxChar(Count);
    end;
     
    procedure TModBus.DoError(Errors: TComErrors);
    begin
    //  Application.ProcessMessages;
      if Errors = [] then Exit;
      inherited DoError(Errors);
    end;
     
     
     
     
    // Compute checksum
    function TModBus.CRC16(Buf: TMBusBuf; Len: Word): Word;
    var
    	CS: Word;
      Index, Shift: integer;
    begin
    	CS := $FFFF;
    	for Index := 0 to Len-1 do
    	begin
        	CS := CS xor Byte(Buf[Index]);
    	  	for Shift := 0 to 7 do
        	begin
      			if (CS and $0001) = $0001 then
      			begin
         			CS := CS shr 1;
            	CS := CS xor $A001;
            end
         		else
         			CS := CS shr 1;
      		end;
    	end;
    	result := CS;
    end;
     
     
     
    // Analyse answer packet
    function TModBus.AnalyseAnswer(Buf: TMBusBuf; Len: Word): TMBusErrCode;
    var
    	CS: Word;
      H, L: Byte;
    begin
    	if (Len > 4) then
      begin
      	CS := CRC16(Buf, Len - 2);
        H := Byte(Buf[Len - 1]);
        L := Byte(Buf[Len - 2]);
        if (H = Byte(HI(CS))) and (L = Byte(LO(CS))) then
        begin
          if (Buf[1] > 128) then Result := MBus_ERR_EXCEPTION else Result := MBus_OK;
        end
        else
          Result := MBus_ERR_ANSWER;
      end
      else
        Result := MBus_ERR_NOANSWER;
    end;
     
     
     
    // Build packet header
    procedure TModBus.BuildHeader(var Buf: TMBusBuf; SlaveNum: Byte; FuncCode: Byte; Address: Word; NumElements: Word = 0);
    begin
    	Buf[0] := Byte(SlaveNum);
      Buf[1] := Byte(FuncCode);
      Buf[2] := Byte(HI(Address));
      Buf[3] := Byte(LO(Address));
      if NumElements > 0 then
      begin
        Buf[4] := Byte(HI(NumElements));
        Buf[5] := Byte(LO(NumElements));
      end;
    end;
     
     
     
     
    procedure TModBus.ReadNRegister(SlaveNum: Byte; Address: Word; NumElements: Word; RequestType: TMBusReqType);
    var
    	CS, I, J: word;
      N, Sz: word;
    begin
      // Store param
      FSlaveNum := SlaveNum;
      FAddress := Address;
      FNumElements := NumElements;
      FErrorCode := MBus_ERR_READ;
     
      // Func type
      case RequestType of
        InputRegister   : FFuncCode := MBus_Func_ReadNInputRegister;
        HoldingRegister : FFuncCode := MBus_Func_ReadNHoldingRegister;
      else
        FFuncCode := MBus_Func_ReadNInputRegister;
      end;
     
      // Build the request
      BuildHeader(FRequestBuf, FSlaveNum, FFuncCode, FAddress, FNumElements);
      CS := CRC16(FRequestBuf, 6);
      FRequestBuf[6] := Byte(LO(CS));
      FRequestBuf[7] := Byte(HI(CS));
      Sz := 5+2*FNumElements;
     
      // Send the request
      if Connected then
      begin
        FRequestSz := 8;
        ClearBuffer(True, True);
        Write(FRequestBuf, FRequestSz);
        FAnswerSz := Read(FAnswerBuf, Sz);
        FErrorCode := AnalyseAnswer(FAnswerBuf, FAnswerSz);
        // Get data
        if FErrorCode = MBus_OK then
        begin
          J := 0;
          N := Word(FAnswerBuf[2]) div 2;
          for I := 0 to N do
          begin
            FWordsArray[I] := (byte(FAnswerBuf[J+3])*256)+(byte(FAnswerBuf[J+4]));
            Inc(J, 2);
          end;
        end;
      end;
     
    end;
     
     
     
    // Write n register
    procedure TModBus.WriteNRegister(SlaveNum: Byte; Address: Word; NumElements: Word; Value: array of Word);
    var
    	CS, I ,J: Word;
    begin
      // Store param
      FSlaveNum := SlaveNum;
      FAddress := Address;
      FNumElements := NumElements;
      FErrorCode := MBus_ERR_SEND;
     
      // Build the request
      FFuncCode := MBus_Func_WriteNRegister;
    	BuildHeader(FRequestBuf, FSlaveNum, FFuncCode, FAddress, FNumElements);
      I := 6;
      FRequestBuf[I] := Byte(FNumElements * 2); Inc(I);
      for J := 0 to FNumElements-1 do
      begin
        FRequestBuf[I] := Byte(HI(Value[J])); Inc(I);
        FRequestBuf[I] := Byte(LO(Value[J])); Inc(I);
      end;
      CS := CRC16(FRequestBuf, I);
      FRequestBuf[I] := Byte(LO(CS)); Inc(I);
      FRequestBuf[I] := Byte(HI(CS)); Inc(I);
      if Connected then
      begin
        FRequestSz := I;
        ClearBuffer(True, True);
        Write(FRequestBuf, FRequestSz);
        FAnswerSz := Read(FAnswerBuf, 8);
        FErrorCode := AnalyseAnswer(FAnswerBuf, FAnswerSz);
      end;
     
    end;
     
     
     
     
    // Write one register
    procedure TModBus.Write1Register(SlaveNum: Byte; Address: Word; Value: Word);
    var
    	CS: Word;
    begin
      // Store param
      FSlaveNum := SlaveNum;
      FAddress := Address;
      FNumElements := 1;
      FErrorCode := MBus_ERR_SEND;
     
      // Build the request
      FFuncCode := MBus_Func_Write1Register;
    	BuildHeader(FRequestBuf, FSlaveNum, FFuncCode, FAddress);
      FRequestBuf[4] := Byte(HI(Value));
      FRequestBuf[5] := Byte(LO(Value));
      CS := CRC16(FRequestBuf, 6);
      FRequestBuf[6] := Byte(LO(CS));
      FRequestBuf[7] := Byte(HI(CS)); 
      if Connected then
      begin
        FRequestSz := 8;
        ClearBuffer(True, True);
        Write(FRequestBuf, FRequestSz);
        FAnswerSz := Read(FAnswerBuf, 8);
        FErrorCode := AnalyseAnswer(FAnswerBuf, FAnswerSz);
      end;
     
    end;
     
     
     
     
    // Write n coil
    procedure TModBus.WriteNCoil(SlaveNum: Byte; Address: Word; NumElements: Word; Value: array of Byte);
    var
    	CS: Word;
      I, I_Bit, NumBit: Word;
      B	: Byte;
    begin
      // Store param
      FSlaveNum := SlaveNum;
      FAddress := Address;
      FNumElements := NumElements;
      FErrorCode := MBus_ERR_SEND;
     
      // Build the request
      FFuncCode := MBus_Func_WriteNCoil;
    	BuildHeader(FRequestBuf, FSlaveNum, FFuncCode, FAddress, FNumElements);
      I := 0;
      I_Bit := 0;
      NumBit := 0;
      B := 0;
      while I_Bit < FNumElements do
      begin
      	if NumBit = 0 then Inc(I);
        if Value[I_Bit] = 1 then B := B or BitWeight[NumBit];
        FRequestBuf[6 + I]:= B;
        if NumBit >= 7 then
        begin
          B := 0;
          NumBit := 0;
        end
        else
          Inc(NumBit);
        Inc(I_Bit);
      end;
      FRequestBuf[6] := Byte(I);
      CS := CRC16(FRequestBuf, 7 + I);
      FRequestBuf[7 + I] := Byte(LO(CS));
      FRequestBuf[8 + I] := Byte(HI(CS));
     
      if Connected then
      begin
        FRequestSz := 9 + I;
        ClearBuffer(True, True);
        Write(FRequestBuf, FRequestSz);
        FAnswerSz := Read(FAnswerBuf, 8);
        FErrorCode := AnalyseAnswer(FAnswerBuf, FAnswerSz);
      end;
    end;
     
     
     
     
    // Write one coil
    procedure TModBus.WriteCoil(SlaveNum: Byte; Address: Word; Value: Boolean);
    var
    	CS: Word;
      V: Byte;
    begin
      // Store param
      FSlaveNum := SlaveNum;
      FAddress := Address;
      FNumElements := 1;
      FErrorCode := MBus_ERR_SEND;
     
      // Build the request
      FFuncCode := MBus_Func_WriteCoil;
    	BuildHeader(FRequestBuf, FSlaveNum, FFuncCode, FAddress);
      if Value then V := $FF else V := 0;
      FRequestBuf[4] := V;
      FRequestBuf[5] := 0;
      CS := CRC16(FRequestBuf, 6);
      FRequestBuf[6] := Byte(LO(CS));
      FRequestBuf[7] := Byte(HI(CS));
     
      if Connected then
      begin
        FRequestSz := 8;
        ClearBuffer(True, True);
        Write(FRequestBuf, FRequestSz);
        FAnswerSz := Read(FAnswerBuf, 8);
        FErrorCode := AnalyseAnswer(FAnswerBuf, FAnswerSz);
      end;
    end;
     
     
     
    // Read coil/input status
    procedure TModBus.ReadCoilInputStatus(SlaveNum: Byte; Address: Word; NumElements: Word; RequestType: TMBusReqType);
    var
    	CS, I, J: word;
      N, Sz: word;
    begin
      // Store param
      FSlaveNum := SlaveNum;
      FAddress := Address;
      FNumElements := NumElements;
      FErrorCode := MBus_ERR_READ;
     
      // Func type
      case RequestType of
        InputStatus   : FFuncCode := MBus_Func_ReadInputStatus;
        CoilStatus    : FFuncCode := MBus_Func_ReadCoilStatus;
      else
        FFuncCode := MBus_Func_ReadCoilStatus;
      end;
     
      // Build the request
      BuildHeader(FRequestBuf, FSlaveNum, FFuncCode, FAddress, FNumElements);
      CS := CRC16(FRequestBuf, 6);
      FRequestBuf[6] := Byte(LO(CS));
      FRequestBuf[7] := Byte(HI(CS));
      Sz := 5 + FNumElements div 8;
      if (FNumElements mod 8) > 0 then Inc(Sz);
     
      // Send the request
      if Connected then
      begin
        FRequestSz := 8;
        ClearBuffer(True, True);
        Write(FRequestBuf, FRequestSz);
        FAnswerSz := Read(FAnswerBuf, Sz);
        FErrorCode := AnalyseAnswer(FAnswerBuf, FAnswerSz);
        // Get data
        if FErrorCode = MBus_OK then
        begin
          N := Word(FAnswerBuf[2]);
          for I := 0 to N-1 do
            for J := 0 to 7 do
            begin
              if (Byte(FAnswerBuf[I+3]) and BitWeight[J]) = BitWeight[J] then
                FBitsArray[J+(I*8)] := 1
              else
                FBitsArray[J+(I*8)] := 0;
            end;
        end;
      end;
     
     
     
    end;
     
    end.

  10. #10
    Futur Membre du Club
    Inscrit en
    Décembre 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    Merci Yome3k.

    Donc le code de ce composant, je l'enregistre en .pas et et je l'instal dans le package de Comport si j'ai bien suivi?

    Désolé je ne suis pas tres calé en POO

    En tout cas encore merci de me filer cette source, je vais d'abord essayer de la décrypter pour un apprendre un maximum. merci!

    Ah oui et donc du coup tout ce qui concerne la communication serie de mon code je peux l'enlever, et dans mon Unit principal je rajoute le MbusCport.pas dans les uses et je fais direct l'appel de tes fonctions?

    heureusement que je fais le pont, je vais pouvoir reprendre mon prog entierement

    C'est mon patron qui va etre content

    A plus tard et merci

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 8
    Points : 10
    Points
    10
    Par défaut
    Ci-joint un bout de code (ancien, désolé) qui exploite le composant:

    Code delphi : 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
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
     
    unit Main;
     
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, Cport, MBusCPort, StdCtrls, ComCtrls, Spin, ExtCtrls;
     
    type
      TMainForm = class(TForm)
        CPort_Settings: TButton;
        CPort_Open: TButton;
        CPort_Close: TButton;
        StatusBar: TStatusBar;
        MBusPanel: TPanel;
        VarAdrEdit: TSpinEdit;
        Label2: TLabel;
        VarLengthEdit: TSpinEdit;
        Label3: TLabel;
        RequestBtn: TButton;
        FunctionCBox: TComboBox;
        Label4: TLabel;
        Label5: TLabel;
        ValueEdit: TSpinEdit;
        BitCBox: TCheckBox;
        Bevel1: TBevel;
        SlaveAdrEdit: TSpinEdit;
        Label1: TLabel;
        Panel1: TPanel;
        RequestMemo: TMemo;
        ResultMemo: TMemo;
        Label6: TLabel;
        Label7: TLabel;
        Logo: TImage;
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure CPort_SettingsClick(Sender: TObject);
        procedure CPort_OpenClick(Sender: TObject);
        procedure CPort_CloseClick(Sender: TObject);
        procedure RequestBtnClick(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
     
    var
      MainForm: TMainForm;
      MBus: TModBus;
      Msg, Status: string;
      ReqNo: integer = 0;
     
    implementation
     
    {$R *.dfm}
     
     
     
     
    procedure TMainForm.FormCreate(Sender: TObject);
    begin
      MBus := TModBus.Create(self);
      MBus.Name := 'MBus';
      MBus.LoadSettings(stIniFile, '.\MBusCom.ini');
    end;
     
    procedure TMainForm.FormDestroy(Sender: TObject);
    begin
      MBus.Free;
    end;
     
    procedure TMainForm.CPort_SettingsClick(Sender: TObject);
    begin
      MBus.ShowSetupDialog;
      MBus.StoreSettings(stIniFile, '.\MBusCom.ini');
    end;
     
    procedure TMainForm.CPort_OpenClick(Sender: TObject);
    var
      Msg: string;
    begin
      MBus.Open;
      if MBus.Connected then
      begin
        Msg := 'COM port opened';
        MBusPanel.Visible := True;
        CPort_Open.Enabled := False;
        CPort_Settings.Enabled := False;
        CPort_Close.Enabled := True;
      end
      else
        Msg := 'Error COM port';
      StatusBar.SimpleText := Msg;
      ResultMemo.Clear;
      RequestMemo.Clear;
      ReqNo := 0;
    end;
     
    procedure TMainForm.CPort_CloseClick(Sender: TObject);
    var
      Msg: string;
    begin
      CPort_Settings.Enabled := True;
      CPort_Close.Enabled := False;
      CPort_Open.Enabled := True;
      MBusPanel.Visible := False;
      MBus.Close;
      if not MBus.Connected then
        Msg := 'COM port closed'
      else
        Msg := 'Error COM port';
      StatusBar.SimpleText := Msg;
    end;
     
    procedure TMainForm.RequestBtnClick(Sender: TObject);
    var
      RequestType: TMBusReqType;
      I: integer;
      ArW: array of Word;
      ArB: array of Byte;
    begin
      Inc(ReqNo);
     
      with MBus do
      begin
     
        // Func type
        case FunctionCBox.ItemIndex of
          0: ReadCoilInputStatus(SlaveAdrEdit.Value, VarAdrEdit.Value, VarLengthEdit.Value, CoilStatus);
          1: ReadCoilInputStatus(SlaveAdrEdit.Value, VarAdrEdit.Value, VarLengthEdit.Value, InputStatus);
          2: ReadNRegister(SlaveAdrEdit.Value, VarAdrEdit.Value, VarLengthEdit.Value, HoldingRegister);
          3: ReadNRegister(SlaveAdrEdit.Value, VarAdrEdit.Value, VarLengthEdit.Value, InputRegister);
          4: WriteCoil(SlaveAdrEdit.Value, VarAdrEdit.Value, BitCBox.Checked);
          5: Write1Register(SlaveAdrEdit.Value, VarAdrEdit.Value, ValueEdit.Value);
          6: begin
              SetLength(ArB, VarLengthEdit.Value);
              for I := 0 to VarLengthEdit.Value - 1 do ArB[I] := Byte(BitCBox.Checked);
              WriteNCoil(SlaveAdrEdit.Value, VarAdrEdit.Value, VarLengthEdit.Value, ArB);
            end;
          7: begin
              SetLength(ArW, VarLengthEdit.Value);
              for I := 0 to VarLengthEdit.Value - 1 do ArW[I] := ValueEdit.Value;
              WriteNRegister(SlaveAdrEdit.Value, VarAdrEdit.Value, VarLengthEdit.Value, ArW);
            end;
        else
          Exit;
        end;
     
        // Error code
        case ErrorCode of
          MBus_OK: Status := 'Request ok';
          MBus_ERR_EXCEPTION: Status := 'Exception';
          MBus_ERR_ANSWER: Status := 'Answer error';
          MBus_ERR_NOANSWER: Status := 'No answer';
        else
          Status := 'Unknown error';
        end;
        StatusBar.SimpleText := Status;
     
        // Request string
        Msg := 'Request ' + IntToStr(ReqNo) + ':';
        for I := 0 to RequestSz - 1 do
          AppendStr(Msg, IntToStr(ord(RequestBuf[i])) + '-');
     
        RequestMemo.Lines.Add('-- Request string ' + IntToStr(ReqNo) + ' --');
        RequestMemo.Lines.Add(Msg);
     
        // Result
        if ErrorCode = MBus_OK then
        begin
     
          ResultMemo.Lines.Add('-- Result of request ' + IntToStr(ReqNo) + ' --');
     
          // ReadRegister result
          if FuncCode in [MBus_Func_ReadNHoldingRegister, MBus_Func_ReadNInputRegister] then
          begin
            for I := 0 to NumElements - 1 do
            begin
              ResultMemo.Lines.Add('%MW' + IntToStr(Address + I) + '=' + IntToStr(WordsArray[I]));
            end;
          end
          // ReadCoilInput status result
          else if FuncCode in [MBus_Func_ReadCoilStatus, MBus_Func_ReadInputStatus] then
          begin
            for I := 0 to NumElements - 1 do
            begin
              ResultMemo.Lines.Add('%M' + IntToStr(Address + I) + '=' + IntToStr(BitsArray[I]));
            end;
          end
          // Other
          else
            ResultMemo.Lines.Add('Done');
     
        end;
      end;
    end;
     
    end.

  12. #12
    Futur Membre du Club
    Inscrit en
    Décembre 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    Bonjour Yome,

    Lorsque je compile MBusCPort.pas voici ce que j'obtiens

  13. #13
    Futur Membre du Club
    Inscrit en
    Décembre 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut


    Re bonjours tout le monde,

    Aujourd'hui le systeme n'est pas en fonctionnement, donc j'ai pu tester si j'avais une communication entre le PC et le régulateur et...rien, nada...

    j'ai utilisé ce que j'avais mis dans ce post au niveau du code
    Citation Envoyé par GingermaN
    Donc est ce que la sa vous semble mieux? je ne peux pas encore testé car le systeme est en fonctionnement.

    Donc pour la construction de la trame et l'envoi:
    Code :

    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
    //////////////////// Assemblage et envoi de la trame ///////////////////////////
    procedure TForm1.ButEnvoiClick(Sender: TObject);
    var
      CRC:word;
    begin
    
    {ouverture du port COM}
       comport1.Connected:=true;
       ButEnvoi.Enabled:=false;
    
    {Conversion de la valeur de l'alarme en Hexa}
      ConcatenerValAlarme:=PanChiffre1.caption+PanChiffre2.caption+PanChiffre3.caption;
      ValeurAlarme:=StrToInt(ConcatenerValAlarme);
      Data:=inttohex(ValeurAlarme,4);
      LabValAlmHex2.Caption:=Data;
    
    
    {Construction de l'entete de la trame}
      {Esclave:=IntToHex(StrToInt(CbxEsclave.Text),2);
      CodeFonction:=IntToHex(StrToInt(EditCdFct.Text),2);//ancienne version
      NumPara6100:=IntToHex(StrToInt(EditNumPara6100.Text),4);}
      Esclave:=Chr(StrToInt(CbxEsclave.Text));
      CodeFonction:=Chr(StrToInt(EditCdFct.Text));
      Valeur := StrToInt(EditNumPara6100.Text);
      NumPara6100:=Chr(Valeur Shr 8)+chr(Valeur And 255);
      DataBin:= chr(valeurAlarme);
    
    {Assemblage de la trame sans CRC16}
      TrameModbus:=Esclave+CodeFonction+NumPara6100+DataBin;
    
    
    {Calcul de CRC16}
      CRC:=CalcCRC16(TrameModbus);
    
    {Transformation du CRC en Pf/PF}
      CRC:=Swap(CRC);
      LabValCRC2.Caption:=intToSTr(CRC);
    
    {Assemblage de la trame complete}
      TrameModbusCRC16:=TrameModbus+chr(CRC);
      LabTrameEnv2.Caption:=(TrameModbusCRC16);
    
    {fermeture de port COM}
      comport1.Connected:=false;
      ButEnvoi.Enabled:=true;
    end;
    ////////////////////////////////////////////////////////////////////////////////
    et pour le calcul du CRC-16, par contre ce n'est pas la version de Yome3k car je n'ai pas su l'adapter, ne sachant pas a quoi correspond TMbusBuf. C'est une des autres nombreuse version que l'on m'a proposé.


    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
    /////////////////////// Fonction de calcul du CRC-16 ///////////////////////////
    function calcCRC16(s: string): word;
    var
      i, j: integer;
      w, x: word;
    begin
      w := $FFFF;
      for i := 1 to length(s) do
      begin
        x := ord(s[i]);
        w := w xor x;
        for j := 1 to 8 do
        begin
          if W and $0001 = $0001 then
          begin
            w := w shr 1;
            w := w xor $A001;
          end
          else
            w := w shr 1;
        end;
      end;
      result := w;
    end;
    Voila en esperant que vous jetterai un petit coup d'oeil

    Et si, aussi nono, sur le bornier du convertisseur, est- ce qu'il faut relier T+ a R+ et T- a R- et est ce que si je branche l'alim externe de celui-ci, il faut mettre un commun sur la borne5 du bornier?
    et pour le convertisseur j'ai tout essayé

    T-0N
    DCE
    R+ >> A
    R- >> B
    T+ T- reliés entre eux

    J'ai essayé l'inverse, enfin toutes les combinaison possibles...

    Ce dont je suis certain c'est la LED TD ne s'allume j'amais, mais le convertisseur est bien alimenté donc mon port marche.



    En plus je n'ai que le journée pour pouvoir tester, la prod reprend demain...

    EDIT: News n°1: J'ai réussis a faire clignoter la LED TD du convertisseur, donc j'envoie bien quelque chose
    La config du convertisseur: T+ >> A ; T- >> B ; switch1 sur DCE ; Swicth 2 sur SIM; Switch 3 sur T RTS - R ON. Bon le régu ne réagit pas, mais deja j'envoie quelque chose, Si vous aviez une petite idée.

    News n°2: Euh...quelque soit la position du switch 2 TD clignote et en position T-ON R-ON les deux led s'allument, ce qui semble logique car les deux circuits (transmission et reception) sont activés.
    Logiquement, la sa dev rait communiquer, non? donc cela doit surement venir du programme...

    News n°3: J'ai tenté d'envoyé une trame en dur (00 06 000D 0004 181B) en tapant la ligne de code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    TrameModbusCRC16:=chr(0)+chr(6)+chr(0)+chr(13)+chr(0)+chr(4)+chr(27)+chr(24);
    Comport1.WriteStr(TrameModbusCRC16);
    Mais cela ne fonctionne pas non plus... je desespere les gens

  14. #14
    Expert éminent sénior

    Avatar de Nono40
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2002
    Messages
    8 640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2002
    Messages : 8 640
    Points : 19 101
    Points
    19 101
    Par défaut
    Au niveau cablage, pour le moment tu peux laisser R+ et R- débranchés car tu ne traite pas la réponse. Laisse aussi le commut sur T-ON afin d'être sur que le convertesseur soit en état d'émission.

    Es-tu sur que ton régulateur réagit bien aux requètes adressées en diffusion (esclave 0) ?

    Ton CRC est mal mis dans la trame. La trame réelle est :
    8: 00 06 00 0D 00 04 18 1B[........]<EMMISSION>
    Il faut que tu inverses chr(27)et chr(24)
    Contrairement aux champs adresse et valeur, les octets du CRC sont en litle indian, faut pas chercher, c'est comme ça

    Nota :
    Si jamais tu dois traiter la réponse, je te souhaite bon courage par contre avec ce type de convertisseur. Il est bien en 4 fils mais en 2 fils tu vas avoir un mal fou à basculer le signal RTS au bon moment. Quand on travaille ne deux fils en émission réception il faut utiliser un convertisseur à basculement automatique en haut impédance directement en fonction du flux de données.
    Mais ceci n'est pas le problème du moment.
    Delphi :
    La F.A.Q. , 877 réponses à vos questions !
    264 sources à consulter/télécharger !

  15. #15
    Futur Membre du Club
    Inscrit en
    Décembre 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut


    Sa ne fonctionne toujours pas, je ne comprend pas d'ou ca viens.

    D'apres la doc, le regulateur prend bien en compte l'adresse 0.
    J'ai mis le convertisseur sur T-ON, SIM et DCE (les trois switch)
    le cable utilisé est un cable blindé.
    J'ai vérifié toutes les connexions
    En effet j'avis oublié d'inverser les poids fort et faible, mais malgres le changement sa ne marche pas.
    Lorsque que j'envoie ma trame, le voyant TD clignote donc j'envoie bien quelque chose.

    La carte optionnelle (RS485) que j'ai rajouté dans mon régulateur est bien reconnu par celui-ci.

    La franchement je ne vois pas...

    A moins que la carte optionnelle soit defectueuse
    ou que le régulateur soit sourd et muet
    ou qu'il n'aime pas ma tronche

    A moins que se soit moi qui soit defectueux

  16. #16
    Membre habitué
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 90
    Points : 126
    Points
    126
    Par défaut
    Citation Envoyé par GingermaN Voir le message
    D'apres la doc, le regulateur prend bien en compte l'adresse 0.
    [...]
    Lorsque que j'envoie ma trame, le voyant TD clignote donc j'envoie bien quelque chose.
    L'adresse 0, en MODBUS, c'est l'adresse de diffusion générale...
    Ce qui permet d'envoyer une requète à tous les équipements, mais sans attendre de réponse.
    C'est spécifié dans le protocole, et c'est un peu logique: si tu as 200 équipements sur la liaison MODBUS, ils ne vont pas tous répondre, sinon, bonjour le bordel !

    Pour que le régulateur réponde, il faut que tu ne t'adresses qu'à lui...
    C'est quoi, son adresse esclave ?

  17. #17
    Futur Membre du Club
    Inscrit en
    Décembre 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    Bonjour Poilr dur,

    Je fais un broadcast car, d'apres ce que j'ai pu lire, on peut faire aussi de l'écriture en broadcast et n'ayant qu'un seul esclave (adresse 1) il n'y a que lui qui recoit la trame, ce qui m'évitait de gerer un trame réponse (vu mon niveau ).

    Donc en gros le systeme c'est:

    Un régulateur de température qui possède plusieurs alarme, suivant ce que l'on a faire le seuil de température a ne pas dépasser n'est pas le meme, et pour modifier la valeur de l'alarme c'est trop compliqué pour les opérateur (Allé dans les menu de config,...) donc je fais ce petit programme, qui va écrire dans le registre correspondant a la valeur de l'alarme (addr 13 d'ou le 000D).

    Et donc quand j'envoie ma trame, la valeur d'alarme n'est pas modifiée...

  18. #18
    Expert éminent sénior

    Avatar de Nono40
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2002
    Messages
    8 640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2002
    Messages : 8 640
    Points : 19 101
    Points
    19 101
    Par défaut
    Tu es bien sur du débit, parité, etc ?

    Pour le broadcast c'est bien dans la doc du régulateur que tu l'as lu ?

    Essaye quand même de mettre une adresse modbus dans ton régulateur et d'envoyer la trame à cette adresse. Même si tu ne traite pas la réponse le régulateur va en tenir compte.

    J'espère surtout que ce changement de seuil n'est pas critique au process car normalement : on contrôle le retour pour être sur que le régulateur ai changé de consigne
    Delphi :
    La F.A.Q. , 877 réponses à vos questions !
    264 sources à consulter/télécharger !

  19. #19
    Futur Membre du Club
    Inscrit en
    Décembre 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    Bonjour Nono,

    Pour tout ce qui est parametre de communication c'est bon, 9600 Baud/s, pas de parité, 1 bit de stop, 8 bits de données, et contröle de flux...aucu...eh ben non, mince, comport est reglé sur controle de flux Hardware sa viens peut etre de la...qu'est ce que tu en penses?

    Sinon oui pour le broadcast c'est bien marqué dans la doc du régulateur
    ici page 131/180

    Je vais quand meme essayé d'envoyer ma trame avec l'adresse 1 entre deux prod.

    Sinon je veux bien essayer de gerer la trame réponse, mais deja que j'ai du mal avec la requete ... et en plus je ne peux pas changer de convertisseur

    Sinon d'ou est-ce que sa pourrai venir?

    Cordialement

    Gingerman

  20. #20
    Futur Membre du Club
    Inscrit en
    Décembre 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut


    Avec l'adresse 1 sa marche , Le seul truc c'est que je lui envoi une valeur d'alarme a 4 et lui se met a 0,4, donc il me reste a trouver d'ou ca vient mais bon, je communique C'est deja un grand pas.

    Si vous avez une idée pour le 4 qui se transforme en 0,4 sur le régu...

    Mais encore merci a vous, je metterai mon petit prog dans les sources quand il sera opérationel

    Allé go go regler se probleme!

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. DLL/Composants Modbus RS-232
    Par bfespi69 dans le forum C++Builder
    Réponses: 6
    Dernier message: 06/01/2011, 09h03
  2. Communication Modbus convertisseur RS485 et relais REX521
    Par thecleverland dans le forum Automation
    Réponses: 2
    Dernier message: 23/06/2009, 20h11
  3. Ecriture / Lecture RS485 MODbus
    Par Fabien50 dans le forum Windows Forms
    Réponses: 0
    Dernier message: 21/04/2009, 09h29
  4. Codes Fonctions MODBUS/RS485
    Par Fabien50 dans le forum C++
    Réponses: 3
    Dernier message: 20/04/2009, 09h20
  5. Connection RS485 vers Modul Modbus
    Par mat-tech dans le forum Automation
    Réponses: 31
    Dernier message: 17/04/2009, 17h47

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