タイトル : Re^2: VB シリアル通信で受けた文字列を配列に格納したい 投稿日 : 2017/09/04(Mon) 11:49 投稿者 : MSAKA
魔界の仮面弁士さん 早々アドバイス有難うございます すっかり遅くなり申し訳ありません > それを言うなら No11868 ですよね。 恐れ入りますそのとおりです 10000円忘れていました > > > SerialPort1.Read(receivedData, 0, receivedData.L使い方ength) > 化けてますね。(^^; ??どうして化けた 私の書き込み時のミスかも知れません > > > 最後に書き込んだBandRegSTR(3,3)は以下のように格納されています > > 各行のインデックスが不明ですが、こういう状態なのでしょうか? > > BandRegSTR(0, 0) = "1" > BandRegSTR(0, 1) = "2" > BandRegSTR(0, 2) = "3" > BandRegSTR(0, 3) = "1" > BandRegSTR(1, 0) = "2" > BandRegSTR(1, 1) = "3" > BandRegSTR(1, 2) = "3 FD23000085080085080000000203000702000(以下略)" いいえ BandRegSTR(n, m) の添え字は2,1〜 3,3(0は使わず)を指定しているので 添字 0,0 や 1,0 の配列は空です 想定とおり ただしその他は BandRegSTR(0, 0) =Nothing BandRegSTR(0, 1) =Nothing BandRegSTR(0, 2) =Nothing BandRegSTR(0, 3) =Nothing BandRegSTR(1, 0) =Nothing BandRegSTR(1, 1) =Nothing BandRegSTR(1, 2) =Nothing BandRegSTR(1, 3) =Nothing BandRegSTR(2, 0) =Nothing BandRegSTR(2, 1) =Nothing BandRegSTR(2, 2) =Nothing BandRegSTR(2, 3) =Nothing BandRegSTR(3, 0) =Nothing BandRegSTR(3, 1) =Nothing BandRegSTR(3, 2) =Nothing BandRegSTR(3, 3) = 3FD23000085080085080000000203000 ・・・略 BandRegSTR(4, 0) =Nothing 以下同じ 受信した文字列を結合されて最後に書き込んだ配列3,3のみ格納されていると言うことです たとえば2,1〜2,3まで送信コマンドを送ったときは最後の配列2,3に3個分結合されて います それ以前の配列は空です (先回 途中の配列には数字だけが格納されて文字はないと言いましたが私の確認ミスで 数字も書き込まれていない つまり 書き込み作業が行われていないと思われます) > おそらくは、 > Dim data As Byte() = {1, 2, 3, 4, 5, 6, 7, 8, 9} > というデータがあった場合に、 > Dim RecStr As String = "090807060504030201" > を得ることが目的なのだと思いますが、それならばループ処理などせずとも、 > Dim RevData As Byte() = data.Reverse().ToArray() > Dim RecStr As String = BitConverter.ToString(RevData).Replace("-", "") > だけで済みますよ。 > > あるいは、data そのものの順番も逆転して良いのであれば、 > Array.Reverse(data) > Dim RecStr As String = BitConverter.ToString(data).Replace("-", "") > と書くこともできます。 Array.Reverse(data) Dim RecStr As String = BitConverter.ToString(data).Replace("-", "") を早々使うことにしました 便利ですね > > > X = RecStr.IndexOf("011A6600FEFE") ' 条件 2 > > この検索方法だと、4bit 分の桁ずれが生じる可能性がありそうですが、大丈夫でしょうか? > > RecStr = "11A6600FEFE000" 'X = -1 が返される(想定どおり) > RecStr = "011A6600FEFE00" 'X = 0 が返される(想定どおり) > RecStr = "0011A6600FEFE0" 'X = 1 が返されるが、本来は X = -1 になるべきでは? > RecStr = "00011A6600FEFE" 'X = 2 が返される(想定どおり) > RecStr = "00011A6600FE00" 'X = -1 が返される(想定どおり) なるほど そこまで考えが及びませんでした 想定外です > > あえてそういう仕様にしているのならば良いのですが、もしもそうではなく、 > 1 バイト単位(16進数表現で 2 文字分)の位置を調べたかったのであれば、 > たとえば BitConverter の "-" をあえて潰さずに、 > Dim RevData As Byte() = data.Reverse().ToArray() > Dim RecStr As String = "-" & BitConverter.ToString(RevData) > X = RecStr.IndexOf("-01-1A-66-00-FE-FE") > Y = RecStr.IndexOf("-FD") > のように探索するという手もあります。これなら桁ズレは発生しません。 > > この方法では、1 バイトが 2 文字ではなく 3 文字で表現されているので、 > 変数 X (と Y) の使いみちによっては、上記の後に追加で > If X >= 0 Then > X = 2 * X \ 3 > End If > のような補正が必要かも知れません。適宜調整してください。 この方法がミスがないのですね Xを使うのに頭が痛くなりますね 課題にします > > > If CC > 40 And X > 10 Then > And 演算子ではなく、AndAlso 演算子を使う癖をつけましょう。 ハイ 分かりました > > > 疑問1 何故 最後の配列変数のみにまとめてを格納されるのでしょうか > > どこで6個の文字列を連結されるのでしょうか ここが原因? > > 『BandRegSTR(n,m) に文字列を格納する処理』が書かれているのは、 > > If CC > 40 And X > 10 Then > > BandRegSTR(BandRegBandNo, BandRegOld) = BandRegOld & RecStr > > End If > の部分だけなのですね。であればこの部分を > > If CC > 40 AndAnslo X > 10 Then > Debug.Write(BandRegBandNo) > Debug.Write(", ") > Debug.Write(BandRegOld) > Debug.Write(" = 文字数:") > Debug.WriteLine((BandRegOld & RecStr).Length) > BandRegSTR(BandRegBandNo, BandRegOld) = BandRegOld & RecStr > End IF > > のように書き換えて、それぞれの変数(特に BandRegBandNo と BandRegOld)の値が > どの時点で期待から外れた値になってしまうのか、出力ウィンドウで確認してみましょう。 出力ウィンドウに何も表示されませんでした 私の知識不足です 開発には不可欠なものなので 勉強します とりあえず今回色々な確認をした結果で問題は解決しそうです 末尾に経過を報告します > 疑問2 ・・・・・ System.Threading.Thread.Sleep(200)の使い方 > この使い方は正しいでしょうか) >正しい使い方ではありません。 ヤッパリ だめなんですね > > コンソール アプリケーションで Sleep を呼ぶような使い方は OK ですが、 > UI スレッド(Form/Button/TextBox などを利用するスレッド)から > Sleep メソッドを呼び出すことは タブー です。 > > 対処方法としては: > (対処案A) メインスレッドから書き込むために、 > Timer を使って Tick イベントから Write する。 Timerで処理することにしました 上手く動いています > > > お願い コマンンドを書き込む方法 下記コード ***1 以降はもっとスマートに > > できないものでしょうか 9×3 で27回分を記述しなければなりませんので > > 下記を見る限り、それぞれの変更箇所は一部分だけなのですよね? そのとおりです > > > 以下 配列のBandRegBandNo BandRegOld と > > RbytOut(6) = &H2 > > RbytOut(7) = &H2 を変更するのみなので内容は省略します > > その場合、それぞれの差異となる部分のみを切り出して、 > それを引数として渡すようにすれば、処理をまとめることができるでしょう。 > > BandRegInfGet( データ1, データ2, … ) > > 引数を使う方法では、渡すデータが多くなりすぎるというのであれば、 > データ受け渡しのためのクラス(または構造体)を設けて、 > Dim arg As New Hoge() > arg.SetOut(6, &H2) > arg.SetOut(7, &H2) > : > BandRegInfGet( arg ) > などという構成にすることもできるかと思います。 > > そして、その引数セットが 27 回あるというのなら、 > Dim args(0 To 26) As Hoge > などで管理しておけば済むでしょう。 > > また、送信するコマンド情報は、現在のコード内に埋め込んでおく方法のほか、 > 外部ファイルなどから読み込ませる方式にするということもできるかと思います。 構造体と聞いただけで頭が痛くなります(扱っている値がどこにあるか迷子になります) 外部ファイルなどから読み込ませる方法が簡単かも 研究課題とします その後の状況 Timerを使うようにした後 何故かしら 条件に合致するものがなくなってしまいました 配列に全く書き込まなくなったのです 変だな?と思い条件なしで受け取ったものをそのときの配列添え字を先頭に付加して 全てをTextBoxに表示して確認しました Private Sub RcvDataToTextBox(data() As Byte) 一部省略 Array.Reverse(data) Dim RecStr As String = BitConverter.ToString(data).Replace("-", "") TextBox2.AppendText(BandRegBandNo & BandRegOld & " " & RecStr & vbCrLf) End Sub 結果は以下です 21 0066FEFE 21 FEFD0102011A 21 21 1A6600FE 21 21 850800000002000003544000010201 21 FD230000850800 22 1A0066FEFE 22 22 FEFD020201 22 1A6600FE 22 22 0800000002030003522150020201 22 FD23000085080085 以下 3,3まで 同じように 同一配列添え字 たとえば(2,1)で7回も受け取って います 空のときもあります (ひとつのコマンドに対して無線機からの文字列は幾つかに分かれて送られているらしい) 念のために受信処理部にカウンターをつけて確認したところPCからの6つのコマンドに 対する受信完了までの間に41回前後を示します また 上記のバラバラの文字列の配列添え字が同じ(例えば 2,2)をつなぎ合わせると FD2300008508008508000000020000035440000202011A6600FEFEFD0202011A0066FEFE となり期待値になります そこで選択条件を無くして同一添え字の配列の間は受信した文字列をその配列に追加書き込みを するようにしてみました Private Sub RcvDataToTextBox(data() As Byte) 一部省略 Array.Reverse(data) Dim RecStr As String = BitConverter.ToString(data).Replace("-", "") BandRegSTR(BandRegBandNo, BandRegOld) = RecStr & BandRegSTR(BandRegBandNo, BandRegOld) ここで追記 TextBox2.AppendText(BandRegBandNo & BandRegOld & " " & RecStr & vbCrLf) ここはTextBoxへの書き込み End Sub 結果配列変数 2,0 は空 (使っていないので正解) 2,1には FD2300008508008508000000010000036020000102011A6600FEFEFD0102011A0066FEFE 2,2には FD2300008508008508000000020000035440000202011A6600FEFEFD0202011A0066FEFE 2,3には FD2300008508008508000000020300035221500302011A6600FEFEFD0302011A0066FEFE 3,0 は 空(使っていないので正解) 3,1には FD2300008508008508000000010000071529900103011A6600FEFEFD0103011A0066FEFE 以下 3,3 まで同じ結果です 受け取った内容は順次変わっていきます たとえば32文字目から6文字が 360200,354400,352215 などと正解と思われる文字列が 格納されるようになりました 無線機から初期値として呼び込み配列に書き込む国的は達成できたことになります たまたま 呼び込みたい初期値は同じコマンド(位置情報のみ変わる)で且つ同じ形式文字列で 返してくること この間は無線機の操作を行わず 余計なイベントが発生しないことなどで 上手く働くだけで未だ課題は多くありそうです 何故文字列が最後の配列に合体してしまうのか?については未確認ですし とりあえず今回ご指導いただいたおかげで一つの壁は乗り越えることができました 大変有難うございました 残されている課題でまたひっかるかも知れません その際はまた お世話になります |