質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
シリアルポート

シリアルポートは一度に一ビットごと移行される物理的なインターフェイスです。一般的には、9ピンのd-subコネクタであるRS-232を指します。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

3回答

14117閲覧

複数のシリアルポートを使用した通信処理にて通信が不可能になる

backfever

総合スコア14

シリアルポート

シリアルポートは一度に一ビットごと移行される物理的なインターフェイスです。一般的には、9ピンのd-subコネクタであるRS-232を指します。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

1クリップ

投稿2019/01/26 01:33

編集2019/01/26 01:47

現状

2つのシリアルポート、2つのスレッドタイマを使用して2つのインジケータから値を取得する処理を行っています。
シリアルポート1はインジケータ1と通信
シリアルポート2はインジケータ2と通信
する仕様になっており、これが変わることはありません。
スレッドタイマで数分毎に通信し値を取得し、タイミングはバラバラでポート1と2がほぼ同時に通信することもありますし
個々に通信をすることもあります。
PCからはUSB変換器を使用してRS232Cと接続をしています。

問題点

通常は正常に通信を行っていて、値も正常に取得できるのですが、あるタイミングで通信タイムアウトが発生し、通信ポートの初期化やプログラム再起動をしても通信が復帰せず、結局PC再起動するまで、タイムアウトが発生し続けます。
PC再起動を行うと正常に通信できるようになります。

実現したいこと

通信タイムアウトが発生しないようにするか、発生した場合、状態をクリアしPC再起動せずに再度通信を再開したい。

ソースコード

vb.net

1''' フォームロード時 2Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load 3 4 'TimerCallbackデリゲート 5 Dim fillTimerDelegate As Threading.TimerCallback = New Threading.TimerCallback(AddressOf FillTimerEvent) 6 'タイマの生成と開始(コールバック処理に時間がかかった場合でも処理を待機し順次処理ように最初は一度しか処理しないように0を設定する) 7 FillTimer = New Threading.Timer(fillTimerDelegate, Nothing, 0, 0) 8 9 'TimerCallbackデリゲート 10 Dim emptyTimerDelegate As Threading.TimerCallback = New Threading.TimerCallback(AddressOf EmptyTimerEvent) 11 12 'タイマの生成と開始(コールバック処理に時間がかかった場合でも処理を待機し順次処理ように最初は一度しか処理しないように0を設定する) 13 EmptyTimer = New Threading.Timer(emptyTimerDelegate, Nothing, 0, 0) 14 15End Sub 16 17'''タイマ1 18Public Sub FillTimerEvent(ByVal obj As Object) 19 '通信処理 20 If Serial_One() = True Then 21 '処理正常終了後、次のコールバックを設定 22 If FillTimer Is Nothing Then 23 Else 24 FillTimer.Change(1000, Timeout.Infinite) 25 End If 26 Else 27 '異常時の処理 28 End If 29End Sub 30 31'''タイマ2 32Public Sub EmptyTimerEvent(ByVal obj As Object) 33 '通信処理 34 If Serial_Two() = True Then 35 '処理正常終了後、次のコールバックを設定 36 If EmptyTimer Is Nothing Then 37 Else 38 EmptyTimer.Change(1000, Timeout.Infinite) 39 End If 40 Else 41 '異常時の処理 42 End If 43End Sub 44 45'ポート1 46Private Function GetWeightInfo_Serial_JYU_Simple() As Boolean 47 48 Dim Result As Boolean = False 49 50 Dim ENQ As Integer = &H5 'ENQ 51 Dim NAK As Integer = &H15 'NAK 52 Dim 安定計量値 As String = "1" 53 Dim 不安定 As String = "0" 54 Dim 計量範囲外 As String = "OV" 55 Dim NAKStr As String = "NAK" 56 57 Dim wkStr As String = "" 58 Dim recvWeight As Double = 0 59 Dim RecvData As String = "" 60 61 Dim IsRecved As Boolean = False 62 63 'シリアルポート1 64 Dim SerialPort_Jyu As New SerialPort() 65 66 Try 67 68 Dim SerialPortIsOpen = False 69 70 For recvTryCount As Integer = 1 To 5 71 72 Try 73 74 'シリアルポート 75 SerialPort_Jyu = New SerialPort() 76 77 '------------------------------------ 78 'シリアルポートの設定 79 '------------------------------------ 80 'ポートを一度閉じる 81 If SerialPort_Jyu.IsOpen = True Then 82 83 'バッファのクリア 84 SerialPort_Jyu.DiscardInBuffer() 85 SerialPort_Jyu.DiscardOutBuffer() 86 87 'ポートが既に開かれている場合は閉じる 88 SerialPort_Jyu.Close() 89 SerialPort_Jyu = Nothing 90 91 'シリアルポート宣言 92 SerialPort_Jyu = New SerialPort() 93 94 End If 95 96 'ポートのオープン処理 97 SerialPort_Jyu.PortName = "COM1" 98 SerialPort_Jyu.BaudRate = 9600 99 SerialPort_Jyu.DataBits = 8 100 SerialPort_Jyu.Parity = IO.Ports.Parity.Even 101 SerialPort_Jyu.StopBits = IO.Ports.StopBits.One 102 103 'タイムアウト値設定 104 SerialPort_Jyu.ReadTimeout = 10000 105 SerialPort_Jyu.WriteTimeout = 10000 106 107 'シリアルポートをオープンする. 108 SerialPort_Jyu.Open() 109 110 'バッファのクリア 111 SerialPort_Jyu.DiscardInBuffer() 112 SerialPort_Jyu.DiscardOutBuffer() 113 114 'ポートフラグ設定 115 SerialPortIsOpen = True 116 117 Dim _requestBytes As Byte() = Encoding.GetEncoding("shift-jis").GetBytes(Chr(ENQ)) 118 119 'シリアルポートから計量依頼を送信する.(ENQ送信) 120 SerialPort_Jyu.Write(_requestBytes, 0, 1) 121 122 '受信するまで待機する 123 RecvData = "" 124 RecvData = SerialPort_Jyu.ReadLine() 125 126 '受信データ表示 127 Console.WriteLine(RecvData) 128 129 Result = True 130 131 Catch ex As Exception 132 133 '例外発生時 134 Result = False 135 136 Finally 137 138 'バッファのクリア 139 If SerialPort_Jyu Is Nothing Then 140 Else 141 SerialPort_Jyu.DiscardInBuffer() 142 SerialPort_Jyu.DiscardOutBuffer() 143 144 'ポートが既に開かれている場合は閉じる 145 If SerialPort_Jyu.IsOpen = True Then 146 SerialPort_Jyu.Close() 147 End If 148 SerialPort_Jyu = Nothing 149 End If 150 151 End Try 152 153 Next 154 155 Catch ex As Exception 156 '例外発生時 157 Result = False 158 End Try 159 160 Return Result 161 162End Function 163 164'ポート2 165Private Function Serial_Two() As Boolean 166 167 Dim Result As Boolean = False 168 169 Dim ENQ As Integer = &H5 'ENQ 170 Dim NAK As Integer = &H15 'NAK 171 Dim 安定計量値 As String = "1" 172 Dim 不安定 As String = "0" 173 Dim 計量範囲外 As String = "OV" 174 Dim NAKStr As String = "NAK" 175 176 Dim wkStr As String = "" 177 Dim recvWeight As Double = 0 178 Dim RecvData As String = "" 179 180 Dim IsRecved As Boolean = False 181 182 'シリアルポート2 183 Dim SerialPort_EMP As New SerialPort() 184 185 Try 186 187 Dim SerialPortIsOpen = False 188 189 For recvTryCount As Integer = 1 To 5 190 191 Try 192 193 'シリアルポート 194 SerialPort_EMP = New SerialPort() 195 196 '------------------------------------ 197 'シリアルポートの設定 198 '------------------------------------ 199 'ポートを一度閉じる 200 If SerialPort_EMP.IsOpen = True Then 201 202 'バッファのクリア 203 SerialPort_EMP.DiscardInBuffer() 204 SerialPort_EMP.DiscardOutBuffer() 205 206 'ポートが既に開かれている場合は閉じる 207 SerialPort_EMP.Close() 208 SerialPort_EMP = Nothing 209 210 'シリアルポート宣言 211 SerialPort_EMP = New SerialPort() 212 213 End If 214 215 'ポートのオープン処理 216 SerialPort_EMP.PortName = "COM2" 217 SerialPort_EMP.BaudRate = 9600 218 SerialPort_EMP.DataBits = 8 219 SerialPort_EMP.Parity = IO.Ports.Parity.Even 220 SerialPort_EMP.StopBits = IO.Ports.StopBits.One 221 SerialPort_EMP.ReadTimeout = 10000 222 SerialPort_EMP.WriteTimeout = 10000 223 SerialPort_EMP.Open() 224 225 'バッファのクリア 226 SerialPort_EMP.DiscardInBuffer() 227 SerialPort_EMP.DiscardOutBuffer() 228 229 'ポートフラグ設定 230 SerialPortIsOpen = True 231 232 Dim _requestBytes As Byte() = Encoding.GetEncoding("shift-jis").GetBytes(Chr(ENQ)) 233 234 'シリアルポートから計量依頼を送信する.(ENQ送信) 235 SerialPort_EMP.Write(_requestBytes, 0, 1) 236 237 '受信するまで待機する 238 RecvData = "" 239 RecvData = SerialPort_EMP.ReadLine() 240 241 '受信データ表示 242 Console.WriteLine(RecvData) 243 244 Result = True 245 246 Catch ex As Exception 247 248 '例外発生時 249 Result = False 250 Finally 251 252 'バッファのクリア 253 If SerialPort_EMP Is Nothing Then 254 Else 255 SerialPort_EMP.DiscardInBuffer() 256 SerialPort_EMP.DiscardOutBuffer() 257 258 'ポートが既に開かれている場合は閉じる 259 If SerialPort_EMP.IsOpen = True Then 260 SerialPort_EMP.Close() 261 End If 262 SerialPort_EMP = Nothing 263 End If 264 265 End Try 266 267 Next 268 269 Catch ex As Exception 270 '例外発生時 271 Result = False 272 End Try 273 274 Return Result 275 276End Function 277

補足

コードは不要部分は削除しております。長いコードですが宜しくお願い致します。
なにか解決につながるヒントでもいいので宜しくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

シリアルポートについてですが、
メッセージを送るときにいちいちOpen/Closeを繰り返すのはまずいです
そのプログラムの起動時に1回だけシリアルポートの初期化&Openを実行するようにしましょう
そして、Closeは、そのプログラムの終了時に実行するようにしてください。

投稿2019/01/26 01:49

y_waiwai

総合スコア87719

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

backfever

2019/01/26 09:12

回答ありがとうございます。 ポートのOpen/Closeを繰り返すのはやはりまずいですかね。 何度も繰り返しているとポート自体が使用不可になってしまうものなんでしょうか?
y_waiwai

2019/01/26 09:18

ポートの初期化周りはおそらくリエントラントの作りにはなってません。 というか、用途的にそういう使い方は想定されてないので、それが原因である可能性は高いと思います
backfever

2019/01/27 05:04

回答ありがとうございました。 ポートの開閉タイミングを調整して様子を見たいと思います。
y_waiwai

2019/01/27 05:38

シリアルポートの場合、ポートのOpen/Closeをメッセージごとに行う意味はありません また、 ポートをCloseしてしまってる間に、他のプログラムで同じポートをOpenしてしまったら、あなたのそのプログラムではエラーとなり異常終了します。 まあ、そこらへんのことを折り込み済みであえてそうするというならいいんですが
backfever

2019/01/27 13:03

返答ありがとうございます。 y_waiwaiさんの言う通り、起動時と終了時にオープン/クローズを移動して試してみたいと思います。 ありがとうございました。
guest

0

Open/Closeをマメにするものではない、というのは確かだけど、それに責任を押し付けるのもちょっと違うような。

通信なので、まずは相手側機器は本当にデータを出しているのか、というのが確認したい項目の一つではあります。オシロか何かで電気的に見るとか、こんなのが使えれば一発なんだけど。USB-232変換をもう一台持ってきて受信側だけつないでteratermとかでモニター、なんて手もあるけど、純粋なソフト屋さんには厳しいかな...

とりあえず、(定常的に)通信できなくて、オマジナイ的に(ハード仕様確認をサボって)DtrEnableとかRtsEnableをtrueにしたら動いた経験はあるので、こいつらはEnableにしておくとか。
Xon/Xoffなんていまどき使わないだろうし、PC側の再起動だけじゃ相手機器の状態は変わらないだろうからこれは関係なさそう。

USB-232変換を他メーカー(わかれば使用チップがちがうもの)に替えてみる、なんてのも一案。疑い出すとキリがないけれど、その変換器のドライバの出来が良くない、とかいう可能性もゼロではないので。

投稿2019/01/26 22:20

thkana

総合スコア7610

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pepperleaf

2019/01/27 02:30

余談ですが、 > 純粋なソフト屋さんには厳しいかな. 手を出すものでは無いと思います。まあ、誰でも最初は初心者なので、勉強しようという気があれば、別ですが。 昔、使ったある機器は、一定時間内に信号線の制御を行わないと、エラー状態になって、リセットが必要なものもありました。(今回は関係無いと思いますが) 相手の仕様確認が大切という事。 > それに責任を押し付けるのもちょっと違うような。 こちらは確かですが。 可能性の大きいところから、確認するものかと。
backfever

2019/01/27 05:03

回答ありがとうございます。 とりあえずシステム側が原因である可能性をつぶしてからハード部分の究明を行いたいと思っています。 確かに畑違いな面は否めないので、いろいろ模索してみます。 ありがとうございました。
guest

0

ポートのオープンクローズを繰り返すと、、、というか、タイミングを失敗すると、バッファにゴミが残って、次のオープンで不正なデータを受信する事になり、辻褄が合わないって事になってませんか?
連続送受信の場合、オープン/クローズは頻繁に行うものではありません。

詳細まで、追ってませんが、、。

投稿2019/01/26 09:35

pepperleaf

総合スコア6383

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

backfever

2019/01/27 05:02

回答ありがとうございます。 とりあえず。ポートの開閉はプログラム起動時に変更したいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問