質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

Q&A

2回答

12345閲覧

C#のプログラムでModbusのRTUの通信を行いたい

a_s_

総合スコア1

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

0グッド

0クリップ

投稿2020/07/27 06:01

編集2022/01/12 10:55

現在、modbusのRTUプロトコルでPCと温度調節器(CHINO製)で通信を試みています。
プログラムを使って無人で自動調整させるためにC#を使っています。
しかし実際にプログラムを書いても通信できませんでした。
そこで、プログラムにミスがあると考え、Modbusの通信用ソフト(HUMANDATA製 Modbus通信確認用アプリケーション)を使用したところ、問題なく通信が行えました(PCから調節器の設定ができた)。

以下に作製したプログラムを書き出します。有識者の方、どうかお願いします。

c#

1 2using System; 3using System.Collections; 4using System.Collections.Generic; 5using System.ComponentModel; 6using System.Data; 7using System.Drawing; 8using System.Linq; 9using System.Text; 10using System.Threading.Tasks; 11using System.Windows.Forms; 12 13namespace WindowsFormsApp2 14{ 15 public partial class Form1 : Form 16 { 17 public Form1() 18 { 19 InitializeComponent(); 20 } 21 22 private void Form1_Load(object sender, EventArgs e) 23 { 24 //プロパティ設定 25 comSerialPort.PortName = "COM3"; 26 comSerialPort.BaudRate = 9600; 27 comSerialPort.DataBits = 8; 28 comSerialPort.Parity = System.IO.Ports.Parity.None; 29 comSerialPort.StopBits = System.IO.Ports.StopBits.One; 30 } 31 32 private void connectButton_Click(object sender, EventArgs e) 33 { 34 //通信開始ボタン 35 try 36 { 37 if(comSerialPort.IsOpen==false) 38 { 39 comSerialPort.Open(); 40 connectButton.Text = "通信停止"; 41 } 42 else 43 { 44 comSerialPort.Close(); 45 connectButton.Text = "通信開始"; 46 } 47 } 48 catch(Exception ex) 49 { 50 MessageBox.Show(ex.Message, "通信エラー", 51 MessageBoxButtons.OK, MessageBoxIcon.Error); 52 } 53 } 54 55 private void sendButton_Click(object sender, EventArgs e) 56 { 57 //送信ボタン 58 if (comSerialPort.IsOpen) 59 { 60 try 61 { 62 string strSend = sendDataTextBox.Text; 63 Byte[] byteArry =System.Text.Encoding.UTF8.GetBytes(strSend);  64 comSerialPort.Write(byteArry, 0, byteArry.Length); 65 //文字列をutf-8でByte配列にして送信 66 67 } 68 catch (Exception ex) 69 { 70 //送信エラー時の処理 71 MessageBox.Show(ex.Message, "送信エラー", 72 MessageBoxButtons.OK, MessageBoxIcon.Error); 73 } 74 } 75 else 76 { 77 MessageBox.Show("通信が未開始", "送信エラー", 78 MessageBoxButtons.OK, MessageBoxIcon.Error); 79 } 80 } 81 } 82}

ちなみに送信しているメッセージの内容ですが、「01 06 00 c8 01 2c 08 79」のように、
アドレスからCRCまでを纏めて送信しています。またsendButtonをクリックしても特にエラーコードは出ません。

追記:
例に示しました「01 06 00 c8 01 2c 08 79」は実際にテキストボックスに入力した文字列で、これをbyte配列(byteArry)に変換して送信しています(できていませんが、、)。またこの「01 06 00 c8 01 2c 08 79」は通信確認用アプリケーションから送信した場合実際に動作する文字列です。

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

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

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

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

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

YAmaGNZ

2020/07/27 06:14

「01 06 00 c8 01 2c 08 79」とは実際に送信しようとしているbyteArryの内容なのですか? また、「01 06 00 c8 01 2c 08 79」とは正常に通信できているModbusの通信用ソフトの通信内容と同じなのでしょうか?
a_s_

2020/07/27 06:26

お二方、コメントありがとうございます。 本文を追記、修正いたしました。 よろしくお願いします。
guest

回答2

0

ソースの通りですと、byteArryの中身は
「30-31-20-30-36-20-30-30-20-63-38-20-30-31-20-32-63-20-30-38-20-37-39」
となります。デバッガで確認できるかと思います。

テキストボックスに入力されたものをそのままバイナリに変換していますので送信すべきバイナリデータと異なっています。
ですので、入力された文字列を正確にバイト配列に変換しないといけません。
各バイトはスペースで区切られていますから、Splitにて文字列の配列に分解し、それぞれをConvert.ToByteにてByte型に変換してはどうでしょうか。

投稿2020/07/27 06:49

YAmaGNZ

総合スコア10222

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

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

a_s_

2020/07/27 10:01

ご回答ありがとうございます。 分かりやすい解説ありがとうございます。 今まで纏めて変換していたものを、一つずつにする、というイメージでよろしいでしょうか? またsplitで配列にし、Convert.ToByteで変換を試みました。 ``` string[] input = strSend.Split(' '); byte byteinput = Convert.ToByte(input); ``` 変換自体はできていると思うのですが。シリアルポートから送信する際のコードがうまくいきません。comSerialPort.Writeを使っていますがなにか別にいいものがあれば教えていただきたいです。
YAmaGNZ

2020/07/27 10:46

自分の書いたコードがどのように動くかデバッガで確認してください。 また、最終的に送信しなくてはならないデータがどのようなものなのか把握してください。 私は回答で「それぞれをConvert.ToByteにてByte型に変換して」と書きました。 これは分割した物をそれぞれ処理する意味で書きました。 また、Convert.ToByteについてはこちらを参照してください。 https://docs.microsoft.com/ja-jp/dotnet/api/system.convert.tobyte?view=netframework-4.8#System_Convert_ToByte_System_String_System_Int32_ 送信に必要なものはByte型の配列で、Convert.ToByteはByte型を返します。 ようは分割した1バイト分の文字列を順番にConvert.ToByteでByte型に変換し、配列に格納するということです。
guest

0

アドレスからCRCまでを纏めて送信しています。

提示のコードではCRCを計算してるところはみあたらないですね

投稿2020/07/27 06:09

y_waiwai

総合スコア87719

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

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

a_s_

2020/07/27 06:16

ご返答、ありがとうございます! CRCはまだプログラムがかけていない状態です。。 HUMANDATA製 Modbus通信確認用アプリケーションに、メッセージを入力すると自動で算出する機能がついているので、それで求めてメッセージに追加する形で送信しています。 例の「08 79」がそれにあたります。
y_waiwai

2020/07/27 06:20

こういう機器に対する通信では、コマンドを送信すると返信(レスポンス)が帰ってくるもんだと思いますが、そのテのメッセージは帰ってきてるんでしょうか
a_s_

2020/07/27 06:31

はい!帰ってきます。 アプリケーション側では、「01 06 00 c8 01 2c 08 79」と送信されると、設定の変更と同時に機器から同様のメッセージが返ってきて、「01 06 00 c8 01 2c 08 79」と表示されます。 また他に、数値を読み取る文字列を送信するとちゃんとその数値(上のような文字列に組み込まれてです)が送られてきます。
y_waiwai

2020/07/27 06:52

そういうレスポンスメッセージにはエラーコードなどが含まれてるもんですが、コマンド正常のコードが返信されてるんでしょうか
a_s_

2020/07/27 10:05

はい、返信のメッセージにもエラーチェック用のコードが入っています。 メッセージが帰ってくる場合は毎回正常のメッセージです。 逆に、異常なコマンドを送った際はメッセージが返ってこず、確認用のアプリケーションではtime out という表示になります。なおvisual studioでメッセージが返ってきたことはありません。
y_waiwai

2020/07/27 10:13

ん?提示のコードではメッセージは帰らないってこと? ならコードが間違ってるってことですな
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問