質問するログイン新規登録
TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

ネットワーク

ネットワークとは、複数のコンピューター間を接続する技術です。インターネットが最も主流なネットワークの形態で、TCP/IP・HTTP・DNSなどの様々なプロトコルや、ルータやサーバーなどの様々な機器の上に成り立っています。

Q&A

解決済

1回答

989閲覧

Modbus TCP サーバの実装について

ma-yu

総合スコア57

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

ネットワーク

ネットワークとは、複数のコンピューター間を接続する技術です。インターネットが最も主流なネットワークの形態で、TCP/IP・HTTP・DNSなどの様々なプロトコルや、ルータやサーバーなどの様々な機器の上に成り立っています。

0グッド

0クリップ

投稿2023/10/03 08:53

0

0

実現したいこと

Modbus TCPというものを知り、試してみたく試行錯誤しています。
以下の環境おいてModbus TCP を実現したいのですがうまくいきません。

  • Modbusサーバ
    ラズパイ
    libmodbus使用

  • Modbusクライアント
    Modbus TCP機能付きPLC(製品名は伏せます)

前提

  • Modbusクライアント、Modbusサーバ、PCをHUBで接続

  • Modbusクライアント側の設定
    ・本体IPアドレス 192.168.1.5
    ・機能 コイルの状態読み出し
    ・マスターデバイスアドレス M0001
    ・データサイズ 1
    ・リモートホスト番号 192.168.1.100 502
    ・スレーブ番号 220
    ・Modbusスレーブアドレス 001002

  • Modbusサーバ
    libmodbusを用いて構築(ソースは後述)

発生している問題・エラーメッセージ

  • クライアント側で以下の通信ログが確認できている
    送信:OK
    受信:エラー

  • サーバー側での最終ログは以下の通り
    Modbusサーバが起動しました
    かつ、いつまで経ってもquery_len が>0にならないことを確認
    →TCP接続ができていないと判断

該当のソースコード

C++

1int ModbusServer() 2{ 3 modbus_t *ctx = nullptr; 4 ctx = modbus_new_tcp("192.168.1.100", 502); 5 modbus_set_slave(ctx,220); 6 7 if(modbus_tcp_listen(ctx, 1) == -1){ 8 std::cerr << "Modbusサーバのリスニングに失敗" << std::endl; 9 modbus_free(ctx); 10 return -1; 11 } 12 13 std::cout << "Modbusサーバが起動しました" << std::endl; 14 15 // coilsのマッピング 16 modbus_mapping_t *mapping = nullptr; 17 mapping = modbus_mapping_new(0,0,16,0); // 16個のコイルを設定 18 19 if(mapping == nullptr) { 20 std::cerr << "Modbusマッピングに失敗" << std::endl; 21 modbus_free(ctx); 22 return -1; 23 } 24 25 while(true){ 26 uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH]; 27 int query_len = modbus_receive(ctx, query); 28 29 if(query_len > 0){ 30 int response_len = modbus_reply(ctx, query, query_len, mapping); 31 32 if (response_len == -1){ 33 std::cerr << "レスポンス生成失敗" << std::endl; 34 } 35 } 36 } 37 38 modbus_mapping_free(mapping); 39 modbus_free(ctx); 40 std::cout << "Modbusサーバが正常終了しました" << std::endl; 41 42 return 0; 43}

試したこと

以下は確認済

  • PCからModbusサーバ機器に対してnetcatをしてTCP/502に接続できること
  • ModbusサーバからModbusクライアントにPingが通ること

とりあえずどんな内容でも良いのでハンドシェイクが取りたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

modbus_tcp_accept()を実行していないためかと思われます。
またmodbus_set_slave()は自分がマスター(クラインアント)の時に実行するものであり、間違っているのではないでしょうか。
下記の作成者のサンプルコード通りやれば上手く行きませんか?

https://github.com/stephane/libmodbus/blob/master/tests/random-test-server.c

投稿2023/10/03 12:25

編集2023/10/03 12:26
naitou

総合スコア141

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ma-yu

2023/10/04 03:09

ありがとうございます。 modbus_tcp_accept()を実行し、modbus_set_slave()を除外することでハンドシェイクが取れました。 ただし、ハンドシェイクが取れているものの通信エラーが発生しています。 クライアント側からは「Modbusスレーブアドレス」を001002(0x03E9)としています。 サーバー側のmodbus_mapping_new()の設定が間違っているのだろうと推測していますが、引数に何を指定すべきかわかりませんでした。 modbus_set_debug エラー内容  Illegal data address 0x3EA in read_bits もし詳細がおわかりになるようでしたら、ご教授よろしくお願いします。
naitou

2023/10/04 03:43

https://libmodbus.org/reference/modbus_mapping_new/ を読んだところからの助言レベルですが、 コイルの状態読み出しなので、 modbus_mapping_new(0,0,16,0) ではなく、 第一引数で modbus_mapping_new(16,0,0,0) かと思われます。
ma-yu

2023/10/04 05:55

本当にありがとうございます。 おかげさまで解決が出来ました。 行ったことを以下に示します。 Modbusスレーブアドレスを001002(0x03E9)としているので、 Modbusの0x03E8から8bitをマッピングすることで解決しました。 ソースでいうと、  mb_mapping = modbus_mapping_new(0x03E8+8, 0, 0, 0); とすることで、通信エラーがなくなり正常にやりとりできました。 ただしこの状態だと読み出しの0x03E9は"0"でしたので、  mb_mapping->tab_bits[0x03E9] = 1; とすることで1を設定でき、無事"1"として読み出しができました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問