none
RS232の通にて相手側機器へ送信 RRS feed

  • 質問

  • 下記に示すコマンド要求を参考にコードを作成しデータを機器から抽出するつもりですが

    送信する場合この下記に示すコードではデータが返ってきません 通信設定は間違いなくあっていますのでデータ要求コマンドのこのコードが間違っています。正しいコードを教えて下さい

     Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
            ComSerialPort.Write(Chr(&H16) & Chr(&H16) & Chr(&H1) & Chr(&H30) & Chr(&H31) & Chr(&H2) & Chr(&H52) & Chr(&H56) & Chr(&H3) & Chr(&H5))


        End Sub


    2013年8月14日 1:08

回答

  • こんにちは、


    発生するのであれば、ReadLine とか使っても本当に問題ないのですか? 
    ReadLine は相手が文字列を返さなければ使えません が、返答は文字列が帰ってくるのですか?

    送信文字列の形式から、同じような文字列が帰ってくるのでないでしょうか。
    その場合、 ReadLineは全く使えないと思いますが、違いますか? 自分だったら、ReadByte あたりを使いそうです。あるいは、BytesToReadで、バイト数を取得して、Readで読取り? (こちらの方がパフォーマンスが良い?)
    まずは、相手から送られてくるデータの形式を見てどうすべきか考えましょう。

    可能でしたら、ラインモニタを入手してデバックが適切ではないかと思います。 うまく動いている時は、良いですが、つまらないミスでも通信が失敗し、原因を調べるのは、相手があるので、結構大変です。 余計な1バイトを送ったがために、相手が、エラー状態になって特定コマンドまで、全て無視なんてのも過去にありました。

    参考までに。



    2013年8月15日 1:50

すべての返信

  • 注記(2013/8/18)
    SerialPort クラスの既定の Encoding が ASCII であることを後のコメントで指摘をいただいています。
    太文字で追記しています。
    -----

    VB.NET における Chr 関数は Char 型を返しますが、この型は 2 バイトです。
    一方、添付画像の説明書によると、1 バイトずつの符号に見えるのであなたが送るべきデータを間違えていると思われます。
    (今は 16h 00h 16h 00h 01h 00h といったように無駄なバイトを送っていると予想される) ← 間違いです。(2013/08/18)

    バイト単位のデータを扱う場合、Byte 型を使ってください。今回の場合、SerialPort クラスには Byte 型配列を受け取る Write メソッド もあるので、そちらを使うべきでしょう。

    テストしてませんがイメージ:

    Dim command As Byte() = {&H16, &H16, &H1, &H30, &H31, &H2, &H53, &H56, &H3, &H5}
    serialport.Write(command, 0, command.Length)


    2013年8月14日 3:00
    モデレータ
  • やはり上記のコードでもできませんでした。

    全てのコードは以下の通りです。

    違う機器では受信できるのですがこの機器だけできません。

    Public Class RS232CForm

        '*****************************************************************
        '
        '   シリアルインタフェースを利用した通信用フォーム
        '
        '*****************************************************************

        ' フォームのLoadイベントハンドラ


        ' 通信開始ButtonのClickイベントハンドラ
        Private Sub ConnectButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ConnectButton.Click

            Try
                ' 通信ポートが開いているかどうかの判定
                If ComSerialPort.IsOpen = False Then
                    ' 通信ポートを開く場合の処理
                    ComSerialPort.Open()            ' 通信ポートを開く
                    ConnectButton.Text = "通信停止"
                Else
                    '   通信ポートを切断する場合の処理
                    ComSerialPort.Close()           ' 通信ポートを切断
                    ConnectButton.Text = "通信開始"
                End If
            Catch ex As Exception
                ' 通信ポートの接続・切断時のエラー処理
                MessageBox.Show(ex.Message, "接続エラー", _
                    MessageBoxButtons.OK, MessageBoxIcon.Error)
            End Try

        End Sub

        ' 送信ButtonのClickイベントハンドラ
        Private Sub SendButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SendButton.Click

            ' 通信ポートが開いているかどうかの判定
            If ComSerialPort.IsOpen Then
                Try
                    ' データの送信

                    Dim command As Byte() = {&H16, &H16, &H1, &H30, &H31, &H2, &H53, &H56, &H3, &H5}
                    ComSerialPort.Write(command, 0, command.Length)
                Catch ex As Exception
                    ' 送信エラー時の処理
                    MessageBox.Show(ex.Message, "送信エラー", _
                        MessageBoxButtons.OK, MessageBoxIcon.Error)
                End Try
            Else
                MessageBox.Show("通信が開始されていません", "送信エラー", _
                    MessageBoxButtons.OK, MessageBoxIcon.Error)
            End If

        End Sub

        ' デリゲート型の宣言
        Delegate Sub RecieveDataDelegate(ByVal RecieveData As String)


        ' デリゲート型のプロシージャを宣言
        Private Sub SetRecieveData(ByVal DataString As String)

            RecieveDataTextBox.Text &= DataString

        End Sub

        ' SerialPortコントロールのDataReceivedイベントハンドラ
        Private Sub ComSerialPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles ComSerialPort.DataReceived

            Dim RecieveData As String
            ' デリゲート型の変数の宣言と生成
            Dim recieve As New RecieveDataDelegate(AddressOf SetRecieveData)

            Try
                ' データの受信
                RecieveData = ComSerialPort.ReadLine
            Catch ex As Exception
                ' 受信エラー時の処理
                RecieveData = ex.Message
            End Try

            'デリゲート型のプロシージャを呼び出す
            Invoke(recieve, RecieveData)

        End Sub

    End Class

    2013年8月14日 3:57
  • 送信する場合この下記に示すコードではデータが返ってきません 通信設定は間違いなくあっていますのでデータ要求コマンドのこのコードが間違っています。正しいコードを教えて下さい

    そもそもの話を引っ張り出してきて申し訳ないですが、この一文を読む限り、「コードだけが間違っている」、「コードを直せば問題は解決する」と信じられる根拠をお持ちのようですが、それは何でしょうか?
    どんなに優れた人・経験を持った人でも、コードと現象だけを見て、「コードを直せばよい」と断定できません。
    なお、「他の通信機器とは問題なく通信できたから、ほかに問題はない」は論理的に成り立ちません。なぜならば、別の通信機器に切り換えるにあたり、「ケーブルを一度外し、接続し直す」(接続不完全・接触不良)、機器による特性の違い(通信設定が異なる)、機器の電源不良など、別の機器に差し替えるに当たって問題が生じる可能性はいくらでもあるためです。

    そういえば、「データが帰ってきません」とかんたんに書いてしまっていますが、DataReceived イベントは発生するのですか?
    発生するのであれば、ReadLine とか使っても本当に問題ないのですか? ReadLine は相手が文字列を返さなければ使えません が、返答は文字列が帰ってくるのですか?
    私は、コマンド送信例の記述内容から察するに、機器からの返答もバイナリであり、ReadLine は使えない と見ていますが、きちんとコマンドの仕様書を確認されていますか?

    2013年8月14日 8:43
    モデレータ
  • こんにちは、


    発生するのであれば、ReadLine とか使っても本当に問題ないのですか? 
    ReadLine は相手が文字列を返さなければ使えません が、返答は文字列が帰ってくるのですか?

    送信文字列の形式から、同じような文字列が帰ってくるのでないでしょうか。
    その場合、 ReadLineは全く使えないと思いますが、違いますか? 自分だったら、ReadByte あたりを使いそうです。あるいは、BytesToReadで、バイト数を取得して、Readで読取り? (こちらの方がパフォーマンスが良い?)
    まずは、相手から送られてくるデータの形式を見てどうすべきか考えましょう。

    可能でしたら、ラインモニタを入手してデバックが適切ではないかと思います。 うまく動いている時は、良いですが、つまらないミスでも通信が失敗し、原因を調べるのは、相手があるので、結構大変です。 余計な1バイトを送ったがために、相手が、エラー状態になって特定コマンドまで、全て無視なんてのも過去にありました。

    参考までに。



    2013年8月15日 1:50
  • やはり上記のコードでもできませんでした。

     「やはり」というのは、何らかの予測があって、その予測通りであった場合に使う言葉です。ここで、「できない」と予測した要因はなんでしょうか。その要因を取り除くこと、説明することが、解決への一歩ではないでしょうか。


    Jitta@わんくま同盟

    2013年8月15日 1:56
  • 私の投稿に対して引用返信されていますが、質問者への問いかけと考えて差し支えないでしょうか。
    私は「コマンド送信例の記述内容から察するに、機器からの返答もバイナリであり、ReadLine は使えない と見ています」と以前に書いていますので。

    -----

    参考までですが、なぜ、ReadLine を使ったコードになったかという背景を探る上では、質問者のスレッドを参照すると見えてきます。
    こちらのスレッドで扱った機器 は、どうも文字列で送受信するタイプだったので ReadLine で問題なかったのでしょう。
    今回の機器は文字列ではなく、バイト列で処理する必要がありそうですが、送信側しかまだ変更が及んでいないので、受信側も見直しが必要に思います。

    2013年8月15日 2:50
    モデレータ
  • Azuleanさん、投稿の仕方がまずかったでしょうか?
    レイアウトが変わって、いま一つ馴染めないでいます。

    質問者の以前のスレッドも見ましたが、基本的なところで苦労しているように感じました。
    元々、この手の通信は、バイナリが基本と思っているので、逆にReadLineで読む事の方が少ないです。
    送信例も以前、どっかでサポートした記憶があります。(同じかどうかは不明)

    どういうデータが流れているかを把握するのが、基本だと思うのですが、動いたら、OKでは道のりが長いと思うのは余計なお世話でしょうか?

    2013年8月15日 9:47
  • Azuleanさん、投稿の仕方がまずかったでしょうか?

    私に対する指摘のような文章構成に見えた割に、そのように見た時に主張したいことが読み取れなかったことから、念のためにお聞きした次第です。
    (文章構成を気にしています。私の文章を引用して疑問形の文面を提示している、私のコメントに対して返信をつける形である、引用する必然性がない場所で引用されているなどから)

    その他、今のところ、質問者への助言に対して私から何か言いたかったことはありませんので、本スレッドのこの流れは私の読み違いと言うことで一旦区切らせてください。
    質問者の方とこのスレッドの参加者・閲覧者の方にはお手数をおかけしました。

    2013年8月15日 11:34
    モデレータ
  • ありがとうございました。ReadLine→ReadByteからあとはそのデータをテキストデータに返るだけです。

    基本的な質問をしてすみません。

    ホントに感謝です。

    あとは返ってきたこのコードを文字列に変換するだけです。

    222214849284775053564930495148564954495249493082663077306952483083495153323232483077494853323232483068325657323232483080325452323073495430763232

    2013年8月16日 5:14
  • VB.NET における Chr 関数は Char 型を返しますが、この型は 2 バイトです。
    一方、添付画像の説明書によると、1 バイトずつの符号に見えるのであなたが送るべきデータを間違えていると思われます。
    (今は 16h 00h 16h 00h 01h 00h といったように無駄なバイトを送っていると予想される)

    解決済みですがこの説明は一部、間違っているため指摘しておきます。

    確かにChr関数やChar型は2バイトのUnicodeですが、SerialPortクラスの既定のEncodingはASCIIEncodingなので特に指定していなければ1バイトのASCIIに変換されてから送信されます。

    2013年8月18日 3:48
  • ご指摘ありがとうございます。
    該当のコメントに対して追記しました。

    あとは、&H00 ~ &H7F(0x00 ~ 0x7F)の範囲での送受信であるという前提がとれれば、バイトで扱う必要はないですね。
    (ASCII 制御文字の表現がなされていることから、それを期待できそう)

    2013年8月18日 9:19
    モデレータ
  • 余計ついでですが、

    この送受信は、7bitの範囲ではないかと。 表示では、漢字表示を行ってもシリアル通信まで漢字というのは出会った事は記憶に無いです。正確には、対象の機器の仕様の確認が必要ですが。

    それより問題は、ストップ/パリティ等。 間違えてもある状況下では、通信が成立してしまうのが面倒だったりします。 (一部の文字が文字化け... パリティビットが、データビットに扱われていたとか....)

    参考までに。

    2013年8月18日 10:55