ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

Visual Basic User's ClubコミュのVB 2008 Express シリアルポート制御について

  • mixiチェック
  • このエントリーをはてなブックマークに追加
はじめまして。
現在、VB2008Expressにてserialportクラスを用いて、
シリアルポートの制御プログラムを書いています。
内容は光学ステージコントローラー(シグマ光機SHOT-602というものです)の制御・・・
といっても基本適には、H:1+等、文字列を送信するだけなのですが、行き詰っています。


━━━━━━━━━━━━━━━━━━━━━
Try

SerialPort1.PortName = cmbPortname.Text

SerialPort1.Open()
SerialPort1.DtrEnable = True
SerialPort1.RtsEnable = True

Catch ex As InvalidOperationException

MsgBox("ポートが開かれている間はポートを変更できません")

Catch ex As Exception

MsgBox("適切なポートを選択してください")
End Try


Dim ch As String
Dim s As String


ch = "OK"

Try

s = tx_comm.Text + Chr(13) + Chr(10)
SerialPort1.WriteLine(s)



Catch ex As Exception

MsgBox("送信できませんでした")
ch = "notsend"

End Try


If (ch = "OK") Then

tx_mcommback.Text = tx_comm.Text + Chr(13) + Chr(10) + tx_mcommback.Text

ElseIf (ch = "notsend") Then

tx_mcommback.Text = "Err-" + tx_comm.Text + Chr(13) + Chr(10) + tx_mcommback.Text

End If

━━━━━━━━━━━━━━━━━━━━━━


という書式で文字列を送信すると

コントローラーの電源を入れた後一度目は動いてくれるのですが、なぜか2度目以降に同様の命令もしくは違う命令を送っても反応しません。(電源を入れなおすとまた動作します)
コンパイルできること、一度目には動作すること、また、2度目以降も送信エラー自体は帰ってこないこと
ターミナル等で操作した場合問題なく動くことなどを考えると、

?接続は完了している
?コントローラーの故障ではない

コントローラ側が最初の命令を溜め込み2つ目以降の命令を受け取らなくなっているのか、もしくは根本的に何か問題があるのか?

というところで行き詰ってしまいました。
経験者、有識者の方、知恵がありましたらよろしくお願いします。

↓SHOT-602のマニュアルです。
http://www.sigma-koki.com/pages/support/motorize/manual_jp/SHOT-602.zip

環境
Visual Basic 2008 Express
Windows XP SP3

コードに関しては、接続送信に関する部分のみ抜き出し貼り付けたため若干違和感があるかもしれません。
実際はフォームを使用しています。

命令文字列の後の改行コードvbCrLfはコントローラーの仕様上必須です。



コメント(26)

はじめまして。

表記されていない部分がないので なんとも申し上げにくいところもありますが、
これが 最小限の再現コードであると 仮定しますと。

・Close メソッドを使用されていない。
→Openメソッドと 同じブロックに Close がないのは ちょっとこわい

と 感じました。

めんどうな気持ちも理解できますが、取説をみたかんじ、15行程度で送信コードは書けると思いますので 最小の再現コードを書いてみては いかがでしょう。
その過程で 気づきがあったりするものですし。
2005しかやったことないですが
ポートを開いた後に、

SerialPort1.NewLine=VBCRLF
を設定して、

s = tx_comm.Text
SerialPort1.WriteLine(s)

とやってみてはどうでしょうか?
WriteLineだと自動で改行コード等を送ってくれるような気がします。



シリアルのクロスケーブルを用意して
もう一台のPCと直結して、
どんな文字列が出てきているか確認してみてはどうでしょう?
そうですね、

ポートを開いて、
コマンドを送信して、
返事を受信して、
ポートを閉じる

と書いたほうがいいんじゃないでしょうか。
繰り返しになって恐縮なのですが、「最小の再現コードを書いてみては いかがでしょう」。

たとえば 全文かかれても btmRun.Click とか 中味はありませんよね?
また Close は btmexit.Click がクリックされるまで 動作してませんよね?

ところで ちょっと気になったのですが、書き方に 若干クセがあるように見受けました。
本来の 得意な 言語は 別にありますか?
参考までに 書いていただけると助かります。
あー 名前付けから そんな感じのように思いました>C

>命令を送信するたびにオープン→送信→クローズとしたほうがいいのでしょうか?

この場合は おっしゃるとおりです。
VBやC#はRADツールのため、非常に短く記述できますしね。

といいますのは、ご存知のとおり 掲示板・トピックスは 「作ってくれ」の場所ではなく「教えてくれ」の場所なので、実際に実装している状態を書いてしまうのは、他の人にとっては 認知心理学上 答えてくれる人の数を 減らしてしまう要素にしかならないことが多いと思います。

逆に 最小の 再現専用のコードで論じると、集客力(?)が上がることがありますし。
なるほど
いまのところ「これかなぁ?」と 思うのが、本文側であれば

s = tx_comm.Text + Chr(13) + Chr(10)
SerialPort1.WriteLine(s)

SerialPort1.WriteLine("H:1-" + vbCrLf)

という記載です。


これを VB.NET な書き方をしますと

s = tx_comm.Text & VbCrLf
SerialPort1.WriteLine(s)

になるのですが、
WriteLineは 改行を送るので
SerialPort1.WriteLine("H:1-" + vbCrLf)

Cでいうところの
H:1- 0x0d 0x0a 0x0d 0x0a
と送られているんじゃないかと思います。

このデバイスって これでいいんですかね?
(質問1)
H: コマンドは 原点復帰ですが、2回連続しても 原点復帰特有の動作を見た目にするのですか?
(質問2)
SerialPort1.Write(s + vbCrLf)
では 動作せず
SerialPort1.Write(s + vbCrLf + vbCrLf)
では 動作すると考えてよろしいですか?
くわえて、一応 取説どおりに書いてみましたが、プロパティと一致しますか?

SerialPort1.PortName = 1
SerialPort1.BaudRate = 9600 'DIPスイッチで設定した通信レート
SerialPort1.DataBits = 8
SerialPort1.Parity = Parity.None
SerialPort1.StopBits = StopBits.One
SerialPort1.Handshake = Handshake.RequestToSend

SerialPort1.WriteTimeout = 500
SerialPort1.ReadTimeout = 500

SerialPort1.Open()
あ、なおったみたいですね。
よかったです。

でも 念のため 明示部分のチェックはしてくださいね。(特にハンドシェイク)
というわけで、
2:ひじかた さん
が 最も正解だったということになりました。(拍手)
問題は解決したようなのでデバッグについて

デバッグするときに回線チェッカーという機器を使ったり
動かす機器に接続する前にパソコンを接続して
受け取り側で伝送内容をチェックするといいと思います。

送信タイミングが早いと相手の機器がうまく反応しないときも
あったりするので待ち時間なんかも必要なときがあります。
> 21:るりるり さん
プロトコルモニターあると 便利ですよねー
私も手離せません。

あと MS 半純正の PortMon
http://www.microsoft.com/technet/sysinternals/ProcessesAndThreads/Portmon.mspx


>二重にcloseを実行してもエラーが帰ってこない原因
命令が 最終的に行き着く先は、Win32 Communications API だと思うのですが、そっちでも 何度でも Close できたはずなので、SerialPortクラスでClose できて いいんじゃないでしょうか。
(原理上、へたしたら Dispose したあとでも Close できるかもですよ)

ポートが開いているかチェックしてから
閉じればいいのではないでしょうか
If SerialPort1.IsOpen = True Then SerialPort1.Close()

同じ参照を繰り返すときはWithを使ったほうが
見やすくなりますよ

ログインすると、残り13件のコメントが見れるよ

mixiユーザー
ログインしてコメントしよう!

Visual Basic User's Club 更新情報

Visual Basic User's Clubのメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング