• 締切済み

シリアル通信でコマンドを送信し、戻ってきたら実行する

VB初心者です。ぜひ、お分かりになる方がいらっしゃいましたら教えて下さい。 質問1:輝度計をシリアルポートに接続し、測定実行のコマンドを送信し、測定後にOKが戻ってきたら測定結果を受信するコマンドを送って結果を受信するというプログラムをVBで作成しています。MScommを使用し、測定実行コマンドを送信後、OKが戻ってくるところまでは出来たのですが引き続き、測定結果を受信するコマンドを送っても反応がありません。やけになって2行続けて書いたらなぜか、2行目が先に実行されてしまいました! 質問2:シリアルポートが開いたらForm2を開き、フォームの色をRGB関数で0に設定、測定コマンドを送信後に結果を受信したらフォームの色を1にするということを 繰り返し、255色まで行いたいのですがFor Nextで設定しても色が変わってくれず、なぜか255の白になってしまいます。色々、調べたのですがよく分からなくて。 とてもこまっています。宜しくお願いします。 Max = 255 For i = 0 To Max r = i: g = i: b = i FrmColor.BackColor = RGB(r, g, b) Next End Sub

みんなの回答

  • Pesuko
  • ベストアンサー率30% (2017/6702)
回答No.8

あんまり詳しくないですが、 全体の流れがおかしいような感じがします。 ”GM”送出後”OK”を受信するまで次の処理をしてはいけないです。 大まかな流れとして。 1)GM送出 2)”OK”ポーリング&タイムアウト処理 3)”OK”正常受信時 4)”OR”送出 5)データ受信ポーリング&タイムアウト 6) 2)のタイムアウト処理 7) 6)のタイムアウト処理 Hayashi_Trekさんがおっしゃるように、よく勘違いするのが対象機の処理に非常に時間がかかる事を忘れて一気に処理をしてしまうと結果がバラバラに受信してしまう場合があります。 このような事象も前述のプロトコルアナライザーを使って通信内容を見るとコマンドの順番がおかしいことがすぐに解るんです。

回答No.7

このソースでは正常動作は難しいと思います。 なぜなら >' GMコマンド送信後OKが戻ってきたら の処理部分が無いため、GMコマンドとORコマンドが立て続けに送られます。 輝度計が測定開始するには時間が掛かると思います。 それに対して結果を返すのはすぐ出来ます。 だから測定開始がOKになる前に、前回の測定結果が返されているのでしょう。 私が良く使う方法は、状態モードで処理分けする方法です。 大雑把な例を書いておきます。受信データの取り込み部分はまだまだ改善が必要です。 Private m_Mode as Integer ' 状態モード ' m_Mode = 0 : 初期状態 ' = 1 : GM送信 ' = 2 : GM応答待ち ' = 3 : OR送信 ' = 4 : OR応答待ち ' = 5 : 終了 ' 送信のClickイベント Private Sub cmdSend_Click() ' 処理のLOOP  m_Mode = 0  Do Until m_Mode=5 ' 終了状態になるまでループする   Switch Case m_Mode   Case 0    ' 通信ポート開く     mscPort.PortOpen = True     m_Mode = 1   Case 1    ' GMコマンド送信     mscPort.Output = "GM" & Chr(&HA)     m_Mode = 2   Case 2   Case 3    ' ORコマンド送信     mscPort.Output = "OR" & Chr(&HA)     m_Mode = 4   Case 4   Case 5   End Select   DoEvents  Loop  ' 通信ポート閉じる   mscPort.PortOpen = False   m_Mode = 0 End Sub ' MSCommコントロールのOnCommイベントプロシージャ Private Static Sub mscPort_OnComm() ' 変数宣言 Dim varBuffer As Variant '受信バッファ  ' CommEventプロパティに対する各処理  Select Case mscPort.CommEvent  ' イベントメッセージ  Case comEvCD ' CD ラインの状態が変化しました。  Case comEvCTS ' CTS ラインの状態が変化しました。  Case comEvDSR ' DSR ラインの状態が変化しました。  Case comEvRing ' リング インジケータの状態が変化しました。  Case comEvReceive ' RThreshold プロパティで指定された数のバイトを受信しました。   ' 受信データの取得   Select Case m_Mode   Case 0   Case 1   Case 2    ' OK待ち    varBuffer = mscPort.Input    If varBuffer="OK" Then     m_Mode = 3    End If   Case 3   Case 4    ' 測定値待ち    varBuffer = mscPort.Input    m_Mode = 5   Case 5   End Select  End Select End Sub

wanta_k
質問者

お礼

別の仕事が入ってしまい、しばらくVBから離れていたため、試せずお礼が遅くなってしまって申し訳ありませんでした。 細かいリソースまで作って頂いてとても感謝しています。 その後、作って頂いたリソースを元にプログラムを変更して実行した結果、正常に 動くことを確認出来ました。順番に実行するためにはどう書いて良いのかが分からず、続けて書いてしまっていたためとご指摘のとおり、コマンドの戻り時間を考慮していなかったために逆に実行されているように思い込んでしまいました。 プログラムとしては他にもまだまだ改善が必要ですがとても勉強になりました。 また、何かありましたら宜しくお願い致します。 本当に有り難うございました。

  • k-family
  • ベストアンサー率34% (180/523)
回答No.6

説明が矛盾していますよ。 > ' GMコマンド送信後OKが戻ってきたら ですからGMコマンドは実行されているのではないですか。 やはり状況が良く把握できません。 できる限りシンプルなプログラムを作って見せて頂けますか。 (でもやはり解決できる自信がないですけど・・・。#2,#3,#4の方いかがですか?)

  • k-family
  • ベストアンサー率34% (180/523)
回答No.5

良く把握できないのでお役に立てそうもないのですが、 >' GMコマンド送信後OKが戻ってきたら というのはこの書かれたリストでは省略されているのですよね? 「逆に実行される」とはどういうことなんでしょうか。GMコマンドは測定開始なんですよね。OKが帰ってきたと言うことは無事実行されたのではないんですか? ------ #2の方がかかれた、DoEventsは制御をOSに戻すための物です。時々OSに戻してやらないとマウスやKBやシリアルの入力を受け付けませんから。

wanta_k
質問者

補足

>' GMコマンド送信後OKが戻ってきたら >というのはこの書かれたリストでは省略されているのですよね? はい、どのように記載してよいのか分からなかったので。 試しにifで書いてみたのですが・・・だめでした。 >「逆に実行される」とはどういうことなんでしょうか。GMコマンドは測定開始な>んですよね。OKが帰ってきたと言うことは無事実行されたのではないんです ? ハイパーターミナルのように戻り値をテキストに表示するような設定を行っているのですがORコマンド戻り値が先に表示されてしまいます。 OR,0.8 GM,OK   というような感じです。 宜しくお願い致します。

  • Pesuko
  • ベストアンサー率30% (2017/6702)
回答No.4

お問い合わせの回答ではないですが、シリアル通信は電文が正確に出ているかどうかがわかりにくいので、ぜひプロトコルアナライザーを使用しましょう。 ビッツ社のみえちゃん・旧積水電子(現ラインアイ社)のラインアイ等。 弊社では「嘘発見器」と呼んで必需品です。 殆どの不具合がアナライザーを通すと解ります。 良くあるのがデリミタ(.や:)やエンド(CRやLF)の付加忘れです、プログラム上絶対出ているはずが、数十回に一回だけ付加されないとか。 買うことが出来なくても知り合いが持っていれば1日だけでも借りればすぐに解決しますよ。 おおむね定価20万円前後です。 ビッツ http://www.bits.co.jp/hm/hm2g.htm ラインアイのうちLE1100 http://www.lineeye.co.jp/le1100.htm

  • fantasis
  • ベストアンサー率26% (14/52)
回答No.3

一応2のほうの解凍を記しときます。 この際はタイマーコントロールによるタイマーイベントで行ったほうが良いと思います。 まず、タイマーコントロールをフォールに張りつけダブルクリックします。そのつぎには次の文を試してみてください。 (この際、Timer1.Interval=1とします) Option Explicit Dim r as Byte, g as Byte, b as Byte Private Sub Timer1_Timer() If r >254 Then Timer1.Interval = 0 Else r = r + 1 g = g + 1 b = b + 1 End If FrmColor.BackColor = RGB(r,g,b) End Sub で出来ると思います。ちなみにお勧めは増分値を5にしたら結構良い具合になります。

wanta_k
質問者

お礼

お礼が遅くなってしまい、申し訳ありませんでした。 有難うございます。教えて頂いたとおりに記載してみたところ、 色の変更は順番とおりに出来ているようです! ただ・・・早すぎるみたいでビデオの早送りのようになって しまいます。Timer1.Intervalの数字をいくつか変えてみたのですが (1000とか5000等etc・・・)だめでした。(うっ) 例えば5秒たったら次のフォームの色に変えるというように(255色まで) するのは難しいのでしょうか??? 宜しくお願い致します。

  • ykkw_2001
  • ベストアンサー率26% (267/1014)
回答No.2

現在のプログラムとか、計測器の通信仕様とか、もうちょい、具体的であればいいんですが・・・ 1: >なぜか、2行目が先に実行されてしまいました 1行目の分は、実行されないわけでしょうか? もしそうなら、「輝度計」側の受信ソフトが遅くて、1行目は、「測定実行->OK」の処理中になってしまい、無視された。 あるいは、電文の区切りが違っていた。 あるいは、MSCommの設定ミス。 2: 多分、色変更が早すぎるからです。 For ループ内に DoEvents を書き加えるか、 タイマーを使ってゆっくリ色を変えるようにして、試してください。

wanta_k
質問者

お礼

ご連絡が遅くなってしまい、申し訳ありません。 ご回答有難うございました。 2:についてご指摘頂いたことについて試していました。やはり、早く実行されて いるために白しか表示されていないように見えているようです。 その後、タイマーなどを使って5秒で設定し、行ってみたのですが・・・ なぜか、状況は変わりません。具体的にはfrmColorにタイマを1つ設定して 上記質問のfor文を記載して見たのですが。DoEventsについては色々インターネットでも調べてみたのですが記載の仕方が良く、分かず試せませんでした。 もし、よろしければどのように記載したらよいのかを教えて頂けると嬉しいです。 尚、1:についてもご指摘のとおりに思いますが測定器が会社ですのでまた、 調べてみます。

  • k-family
  • ベストアンサー率34% (180/523)
回答No.1

お困りのようですが、情報が少なくて答えられる人は少ないと思います(特に1番)。もう少し具体的に書いてみてはいかがでしょうか。だからといって私が答えられるとは限りません。でも他の方から回答を得られやすくなります。 2番の方ですが、これは一部分を取り出したんですよね。このままだとしたら、一瞬で0~255まで行ってしまうので白になるような気がします。 それから1番と2番は直接関係なさそうですから別々に聞かれた方が回答を得られやすいと思います。

wanta_k
質問者

補足

状況の説明が悪くて申し訳ありません。。。 手順としては送信コマンドをクリックしたらCOMポートをを開く→測定開始コマンドを送信する(GM)→輝度計が測定を開始→OKが戻ってきたら輝度計の測定結果を戻すコマンドを送信(OR)→データを受信という形になります。以下に、作成中のプログラムを記載します。 (初心者ですのでプログラムの乱雑さはお許し下さい! ' 送信のClickイベント Private Sub cmdSend_Click() ' 通信ポートか開いているか確認 If mscPort.PortOpen = True Then   ' Colorフォームを開く   FrmColor.Show   ' 受信データの一時取得用変数の初期化   strData = ""   ' MDT測定を要求するコマンドを送信   strSendData = "GM"   mscPort.Output = strSendData & Chr(&HA)   TxtSendData.Text = strSendData   ' GMコマンド送信後OKが戻ってきたら   If strSendData = "GM" Then ←この行をコメントするとGMとORが    strSendData = ""     逆に実行されてしまいます。     ' 測定結果を要求するコマンドを送信     strSendData = "OR"    mscPort.Output = strSendData & Chr(&HA)    TxtSendData.Text = strSendData     FrmColor.BackColor = RGB(r, g, b)   End If End If End Sub ' MSCommコントロールのOnCommイベントプロシージャ Private Static Sub mscPort_OnComm() ' 変数宣言 Dim varBuffer As Variant '受信バッファ ' CommEventプロパティに対する各処理 Select Case mscPort.CommEvent ' イベントメッセージ Case comEvCD ' CD ラインの状態が変化しました。 Case comEvCTS ' CTS ラインの状態が変化しました。 Case comEvDSR ' DSR ラインの状態が変化しました。 Case comEvRing ' リング インジケータの状態が変化しました。 Case comEvReceive ' RThreshold プロパティで指定された数のバイトを受信しました。 ' 受信データの取得 varBuffer = mscPort.Input TxtRecieveData.Text = TxtRecieveData.Text & varBuffer 送信コマンドはtxtSendDataに表示され、コマンドの送信結果はtxtrecivedataに表示されるように作成しています。ぜひ、宜しくお願いします。

関連するQ&A