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

Web & réseau Delphi Discussion :

Protocole MODBUS TCP/IP


Sujet :

Web & réseau Delphi

  1. #1
    Membre à l'essai
    Protocole MODBUS TCP/IP
    Bonjour,
    J'ai une application développée en Delphi 6 qui tourne sous Windows XP à l'intérieur de laquelle je dois ajouter un module qui me permette de communiquer en MODBUS avec un robot 6 axes staubli.
    Quelqu'un peut'il m'indiquer vers ou m'orienter pour ce problème?
    Merci à tous.

  2. #2
    Membre chevronné
    Regardes du côté de Delphi Modbus library

    Je n'avais qu'un besoin basique de lecture, donc je ne sais pas ce qu'elle vaut pour le reste.
    Delphi 7/XE2/XE3
    C#
    Oracle 9i à 12c
    SQL Server 2008 à 2014

  3. #3
    Membre à l'essai
    Problème au chargement des paquets
    Merci pour l'info.
    Par contre je n'arrive pas à installer le package DelphiModbus60.dpk, le système me retourne l'erreur :
    dans IdModbusClient.pas : Declaration of 'Connect' differs from previous declaration.
    ?????
    Merci.

  4. #4
    Membre chevronné
    Quelle version d'Indy as-tu d'installer?
    Delphi 7/XE2/XE3
    C#
    Oracle 9i à 12c
    SQL Server 2008 à 2014

  5. #5
    Membre à l'essai
    Version indy installée
    J'ai installé les packets dclindy60.

  6. #6
    Membre habitué
    essais infructueux de module Modbus TCP
    Bonjour a tous,

    J'ai essayé d'utiliser le module maître dans version source forge 1.6.3.
    Ca fonctionne avec en test avec le simulateur Mod_rssim 8.20 de www.plcsimulator.org
    mais pas en réel sur 2 appareils industriels différents

    J'ai le message "PLC read operation failed!"

    pour avoir essayer de tracer les choses :
    - le Socket est bien alloué
    - la connexion est bien réalisée sur l'appareil cible

    testé avec un superviseur doté de Modbus TCP les 2 appareils cibles fonctionnent.

    je suis sous delphi XE5 et windows 8.1 pro

    Merci a celui qui pourrait m'aider

  7. #7
    Membre chevronné
    Un peu de code serait le bienvenu. Quel Read utilises-tu? Pour ma part je n'utilise que ReadHoldingRegisters.
    Delphi 7/XE2/XE3
    C#
    Oracle 9i à 12c
    SQL Server 2008 à 2014

  8. #8
    Membre habitué
    j'ai utilisé la demo proposée dans le package
    et ce sont des mots (registres) de 16 bits que je veux lire simplement
    j'ai simplement ajouté un memo et géré quelques evenements

    voici le source du module
    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
     
    { $Id: frm_Main.pas,v 1.1 2011/08/25 10:04:33 plpolak Exp $ }
     
    unit frm_Main;
     
    interface
     
    uses
      SysUtils, Types, Classes, Variants, FMX.Types, FMX.Controls, FMX.Forms,
      FMX.Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
      ModbusTypes,
      IdModBusClient, FMX.Edit, UITypes, FMX.StdCtrls, FMX.Layouts, FMX.Memo;
     
    type
      TfrmMain = class(TForm)
        mctPLC: TIdModBusClient;
        Label1: TLabel;
        edtIPAddress: TEdit;
        GroupBox1: TGroupBox;
        GroupBox2: TGroupBox;
        Label2: TLabel;
        Label3: TLabel;
        edtReadReg: TEdit;
        edtReadAmount: TEdit;
        btnRead: TButton;
        Label4: TLabel;
        Label5: TLabel;
        edtWriteReg: TEdit;
        edtValue: TEdit;
        btnWrite: TButton;
        Memo1: TMemo;
        Button1: TButton;
        procedure btnReadClick(Sender: TObject);
        procedure btnWriteClick(Sender: TObject);
        procedure mctPLCConnected(Sender: TObject);
        procedure mctPLCDisconnected(Sender: TObject);
        procedure mctPLCResponseError(const FunctionCode, ErrorCode: Byte;
          const ResponseBuffer: TModBusResponseBuffer);
    (*
        procedure mctPLCResponseMismatch(const RequestFunctionCode,
          ResponseFunctionCode: Byte; const ResponseBuffer: TModBusResponseBuffer);
    *)
        procedure mctPLCSocketAllocated(Sender: TObject);
        procedure Button1Click(Sender: TObject);
        procedure mctPLCStatus(ASender: TObject; const AStatus: TIdStatus;
          const AStatusText: string);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
     
    var
      frmMain: TfrmMain;
     
    implementation
     
    {$R *.fmx}
     
     
    procedure TfrmMain.btnReadClick(Sender: TObject);
    var
      Data: array[0..4096] of Word;
      iAmount: Integer;
      i: Integer;
      sLine: String;
    begin
      iAmount := StrToInt(edtReadAmount.Text);
      if (iAmount > 0) then
      begin
        mctPLC.Host := edtIPAddress.Text;
        if mctPLC.ReadHoldingRegisters(StrToInt(edtReadReg.Text), iAmount, Data) then
        begin
          sLine := 'Register value(s) read:';
          for i := 0 to (iAmount - 1) do
            sLine := sLine +
                     #13#10'     ' +
                     IntToStr(StrToInt(edtReadReg.Text) + i) +
                     ': 0x'  +
                     IntToHex(Data[i], 4);
          ShowMessage(sLine);
        end
        else
          ShowMessage('PLC read operation failed!');
      end;
    end;
     
     
    procedure TfrmMain.btnWriteClick(Sender: TObject);
    begin
      mctPLC.Host := edtIPAddress.Text;
      if mctPLC.WriteRegister(StrToInt(edtWriteReg.Text), StrToInt(edtValue.Text)) then
        ShowMessage('PLC register write successful!')
      else
        ShowMessage('PLC register write failed!');
    end;
     
     
    procedure TfrmMain.Button1Click(Sender: TObject);
    begin
      If not mctPLC.Connected then
      begin
        mctPLC.Connect;
        Button1.Text := 'Deconnecte';
      end else begin
         mctPLC.Disconnect;
        Button1.Text := 'connect';
      end;
    end;
     
    procedure TfrmMain.mctPLCConnected(Sender: TObject);
    begin
      Memo1.Lines.Add('connecté')
    end;
     
    procedure TfrmMain.mctPLCDisconnected(Sender: TObject);
    begin
      Memo1.Lines.Add('déconnecté')
    end;
     
    procedure TfrmMain.mctPLCResponseError(const FunctionCode, ErrorCode: Byte;
      const ResponseBuffer: TModBusResponseBuffer);
    begin
    //  Memo1.Lines.Add('ResponseError>'+ResponseBuffer.Header);
      Memo1.Lines.Add('ResponseError>'+IntToStr(ResponseBuffer.FunctionCode));
    //  Memo1.Lines.Add('ResponseError>'+ResponseBuffer.MBPData);
    end;
     
    (*
    procedure TfrmMain.mctPLCResponseMismatch(const RequestFunctionCode,
      ResponseFunctionCode: Byte; const ResponseBuffer: TModBusResponseBuffer);
    begin
      Memo1.Lines.Add('ResponseMismatch>');
    end;
    *)
     
    procedure TfrmMain.mctPLCSocketAllocated(Sender: TObject);
    begin
      Memo1.Lines.Add('SocketAllocated>');
    end;
     
    procedure TfrmMain.mctPLCStatus(ASender: TObject; const AStatus: TIdStatus;
      const AStatusText: string);
    begin
      Memo1.Lines.Add('CStatus>'+AStatusText);
    end;
     
    end.

  9. #9
    Membre chevronné
    Quelle est l'adresse des registres à lire? Pour mon cas d'utilisation, cela commence à 4097.
    Delphi 7/XE2/XE3
    C#
    Oracle 9i à 12c
    SQL Server 2008 à 2014

  10. #10
    Membre habitué
    plage d'adresse
    C'est, entre autre, Dans la zone $100 .. $110 puis $200..$210

  11. #11
    Membre chevronné
    Je ne vais pas pouvoir t'aider du coup. Ce message d'erreur, je ne l'ai que si j'interroge des registres en dehors de la plage acceptée par le serveur Modbus.

    La seule piste ça serait de faire une boucle sur la lecture de registre, en ignorant les exceptions afin de voir si la plage n'est pas différente.
    Delphi 7/XE2/XE3
    C#
    Oracle 9i à 12c
    SQL Server 2008 à 2014

  12. #12
    Membre habitué
    C'est au moins une bonne information que de savoir d'ou peut provenir ce message.
    Je vais essayer ta proposition de boucle.

    merci

  13. #13
    Membre habitué
    Attention les simulateurs sont dans ce cas tolérants
    mais certains serveurs le sont moins.
    Alors il convient de ne pas laisser a 0 UnitId que l'on peut assimiler a un numéro d'esclave.

    hé oui, même si l'adresse IP semble suffire, dans certains cas, le numéro d'esclave peut être indispensable.