シリアル通信のバイトデータ受信について

MZ Platformとは 掲示板 MZプラットフォームユーザー会掲示板 シリアル通信のバイトデータ受信について

10 件の投稿を閲覧中 - 1 ~ 10 件(全 26 件)
  • 著者
    投稿
  • #6101
    伊予研究会
    一般参加者

     シリアル通信で文字列データを受信していますが、データに欠落があるようで、バイト単位で受信することを考えています。
     もともと送り側のデータは整数(int)のため文字列に変換していましたが、これを上位ビットと下位ビット(2byte)にわけ、送信するようにプログラムを変更しました。Mz側でシリアル通信の受信データをバイト格納変数に入れようとしましたができません(サンプルでは文字格納変数に入れています)。
     したいことは、2バイトのシリアル通信データを受信して変数に格納し、受信したデータが2バイトであるかもチェックしたいので、サンプルなどがございましたら、ご教示ください。

    #6103
    MZPlatformユーザー会
    サイト管理者

    文字列データの受信で欠落があるということでバイト単位の受信にすることは、本質的な解決にはならないように思います。送信側を自由に決められるのであれば、むしろ文字列データ側に工夫をして、エラー検出やエラー補正の仕組みを検討してはいかがでしょうか。

    とは言え、バイトデータ受信についても、回答します。文字列データ受信に比べて複雑なので、あまりおすすめできませんが、バイト列を送信する既存機器からのデータ受信では避けて通れないため、機能としては存在します。性質上、必ず動作するサンプルを作成するのが難しいため、下記長文の説明にてご容赦ください。ご不明な点は再度お問い合わせください。

    まず準備として、シリアル通信コンポーネントの属性情報設定で、下記を変更します。
    ReadMode 3(バイトデータ読み込み)
    ByteReadMode
     0(シングル符号あり)
     1(シングル符号なし)
     2(ダブル符号あり)
     3(ダブル符号なし)
    ご自身で上位バイトと下位バイトに分けて送信する場合は、0か1になります。

    バイトデータ読み込みモードでは、データの区切りを認識するために、ご自身で書式を適切に決めていただく必要があります。例えば、受信したいバイトデータの前に、データの開始を示す特定の1バイトを送ります。シリアル通信コンポーネントのデータ生成イベントの処理で受信したバイトを整数として判定して、そのバイトデータを受信したら、所定の読み込み処理を実行し、それ以外は無視するようにします。

    特定の1バイトの直後に2バイトで整数を送っている場合、所定の読み込み処理として次のような処理を実行します。ここでは符号なし(ByteReadModeが1)としたときの処理について書きます。

    下記はすべてシリアル通信コンポーネントのメソッドで、続けて実行します。
    #0: readByteSingleUnsignedArray(2) // 要素数2の配列としてバイト列を読み込む
    #1: getPacketValueAt(0) // 配列の0番目の要素のバイトデータを取得
    #2: getPacketValueAt(1) // 配列の1番目の要素のバイトデータを取得
    #3: getDoubleByteValue(#1処理結果,#2処理結果) // 2つのバイトデータから整数を取得

    このような処理を実行すると、2バイトデータから1つの整数を取得できます。
    なお、この方法では想定するバイト長に従って読み込んでいき、必要数取得したら進む感じになるため、逆に受信したデータのバイト数チェックはできません。

    以上、お試しください。

    #6104
    伊予研究会
    一般参加者

    ご回答ありがとうございました。

    まず、文字データの欠落の件ですが、3軸振動センサからデータを取得するプログラムを作っております。データの測定は高速で行うため一旦SRAMに保存し、保存したデータを直接USBケーブルで繋いで、Mzのシリアル通信で取り込もうとしています。文字列データでの取込プログラムではシリアル通信で取り込むメモリ番地を出力して、それに対応したデータを受信するようにしました。1コマンド毎に出力して取り込んだ場合には問題なく受信できていますが、何分データ量が多いため連続して取り込もうとすると、一部データの欠落があるようでした。
    その時の、受信フォーマットは
    X12Y-16Z362@
    等の文字列となっており、X,Y,Zの数値は文字列として送信しているため、数値によってデータ量が変わるのが問題では無いかと考えました。Mzプログラムではデータチェックのため、X,Y,Zの順番で最後に@が有ることもプログラムしています。

    そこで、送信する数値は-400~400までの整数であることから、今回送信側をバイト単位にすれば固定長のデータになると思いプログラムの変更をしています。
    バイト単位では、
    X,(数値の符号),(Xの上位ビット),(Xの下位ビット),@
    の5byteで(Xデーのみ)で確認しているところです。チェックは固定位置にX,@が有ることを条件としました。

    ところで、シリアルコンポーネントの属性情報設定でわからないので教えて下さい。
    (1) ReadMode に入れる数値は、取込のバイト数と理解してよろしいでしょうか?
    (2) ByteReadMode のシングルとダブルの違いは数値のサイズのことでしょうか?
    (3) ByteReadMode のシングル符号無しは取込データがプラス、符号有りはマイナスということでしょうか?

    アドバイスしていただいた
    #0: readByteSingleUnsignedArray(2)を入れましたが、入れる場所が悪いのかエラーになってしまいます(添付ファイル serial_ByteRead_1.mzax)。

    また、serial_ByteRead_2.mzaxでチェックを行ったところ、データの順番は正常に取り込みできましたが、数値が127を超えてしまうとバイトデータがマイナスとなり、ByteReadModeで設定を変えても変わりません。この使い方をご教示下さい。
    将来、取込データがマイナスかプラスかで処理を分岐させる予定ですが、プラスの場合はUnSingedで処理してコードを短くしたいと思っております。

    ちなみに、Arduino UNO をシリアルデータ発信としたスケッチも添付しておきます。
    よろしくお願いします。

    添付ファイル:
    #6106
    MZPlatformユーザー会
    サイト管理者

    いただいたサンプルを改変して、動作する状態にしたものを圧縮して添付します。

    注意点として、シリアル通信コンポーネントはバイトデータを受信できますが、データ生成イベントのイベント内包データに入った時点でintに変換されてしまいます。先頭の’X’を受信した時点でデータ生成イベントの内包データが88で出力されるので、それを判定したらメソッドでバイト配列を取得します。その後の処理は添付のサンプルをご覧ください。

    前回書いた内容も含まれますが、ご質問への回答は下記になります。
    (1) ReadMode に入れる数値は、取込のバイト数ではなく、この場合は常に3です。
    (2) ByteReadMode のシングルとダブルの違いは数値のサイズのことではなく、1バイトずつ読むか2バイトずつ読むかということで、この場合は常にシングル符号なしの1です。
    (3) ByteReadMode のシングル符号なしとは、1バイトが示す内容が0-255ということです。

    添付のサンプルアプリの処理であれば、負の値や127より大きな値を受信した時も正常に読み込めると思います。もし何か問題があれば再度お知らせください。

    よろしくお願いします。

    添付ファイル:
    #6108
    伊予研究会
    一般参加者

    サンプルの添付、ありがとうございました。使い方がよく分かりました。
    次の点についてもう少し、詳しくご教示頂けると助かります。

    (1) 通信コンポーネントを追加したデフォルトでは、ReadMode = 0 となっており、今回の場合読込モードが常に3とは、どのような場合に3となるのでしょうか? 3を選択する意味が今一つ理解できません。
    また、1, 2もあるのでしょうか?

    (2) ReadByteSingleUnsignedArrayでは、要素配列4としてバイト配列を呼び出していますが、これは呼出時点(Xの次)のデータから保存と解釈してよろしいでしょうか?

    よろしくお願いいたします。

    #6109
    MZPlatformユーザー会
    サイト管理者

    作成当初のシリアル通信コンポーネントは、文字列データを送受信することを前提に作られています。ReadModeは当初から存在し、intでデータ受信のモードを指定します。指定可能なモードは下記になります。3のバイト読み込みは後から追加されたものです。

    0:初期値。受信が途切れたらそれまでに受信した文字列のまとまりを含むイベント発生。
    1:一文字(シングルバイト)読み込むとイベント発生。
    2:一行(改行文字で判断)読み込むとイベント発生。
    3:バイトデータを読み込むとイベント発生。

    それぞれ数字を覚えなくても、シリアル通信コンポーネントのメソッドで取得することが可能です。
    getReadModeDefault()
    getReadModeSingleChar()
    getReadModeLineText()
    getReadModeByte()

    ReadMode=3のときに、バイト列にもいろいろあるため、ByteReadModeを追加しました。これはReadMode=3のときのみ有効な属性です。指定可能なモードは前述の通り(他にもいくつか存在します)です。こちらも対応するメソッドが存在します。自分でいろいろバイト列を操作するなら1のシングル符号なしで良いと思います。

    前回送っていただいたArduino側のスケッチは、5バイト単位で送っていますね。MZアプリ側のシリアル通信コンポーネントがReadMode=3のByteReadMode=1に設定されていると、1バイト受信した段階でイベント発生します。先頭分はすでに受信が終わっているので、先頭分を入れた配列として受信することはできませんが、後ろにあと4バイト来ることがわかっているので、配列の長さ4としてまとめて受信しています。このとき、メソッドで後続の受信データを処理しているので、処理したデータについては、イベント発生しません。

    なお、こちらで作成したアプリで4バイト目(最後尾)は使っていないので、3バイト分の配列として受信してもよいです。その場合、最後の1バイトについては、イベント発生します。この場合、サンプルではイベント発生して受信データがXでないと判定されて次のイベント発生に進むことになります。

    #6110
    伊予研究会
    一般参加者

    ご丁寧な説明、ありがとうございました。

    ReadMode とByteReadMode の関係が理解できました。また、イベント発生のタイミングを意識していませんでしたので、取込データがどのようになっているかが分かりすっきりしました。

    面倒な質問にご対応いただき、大変ありがとうございました。

    #6125
    伊予研究会
    一般参加者

     前回は符号を別に送信していたのですが、それも省略したいと考えております。符号付きのデータを読み取る場合についてもご教示ください。
     例えば-32768や32767を読み取る場合、符号を含むとそれぞれ 0x8000, 0x7FFFになりますが、上位バイトには符号が含まれているのでreadByteSingleSignedArrayで読み取ると下位バイトはUnsigned情報となっており正常に読み込むことができません。
     readByteModeは0にしましたが、間違っていればそれも含め教えてください。

    #6126
    MZPlatformユーザー会
    サイト管理者

    以前の回答にある通り、バイト読み込みモードでは符号ありと符号なしなどを指定することができますが、それらが混在したバイト列では対応が難しくなります。この読み込みモードは既存の機器から出力されるバイト列をなんとか読み込むために少しずつ機能拡張している状況ですので、あらゆる状況に対応できるわけではありません。

    特に、出力されるバイト列をご自分で決められる状況であれば、MZ側が読みやすい出力をするようにしていただけますでしょうか。

    #6127
    伊予研究会
    一般参加者

     ご回答ありがとうございました。出力側で工夫してみます。
     機能を拡張しているとのこと、IntやLongなどはRAMに2バイト, 4バイトの塊で記録しているので、今後Singed, Unsignedを指定して一括で取り込む関数を追加して頂ければ幸いです。
     今後のご発展をお祈り申し上げます。

10 件の投稿を閲覧中 - 1 ~ 10 件(全 26 件)
  • このトピックに返信するには、ログインしてください。