C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[9]: シリアル通信でバッファオーバーランが発生する


(過去ログ 129 を表示中)

[トピック内 12 記事 (1 - 12 表示)]  << 0 >>

■76552 / inTopicNo.1)  シリアル通信でバッファオーバーランが発生する
  
□投稿者/ jun (6回)-(2015/07/22(Wed) 09:03:45)

分類:[VB.NET/VB2005 以降] 

以前にもご質問させて頂いた者です。

頂いたご意見を元に、コードを書きなおしてみたところ、バッファオーバーランが発生してしまいました。

現在のコードはソフト側に大きめのバッファを用意し、DataReceivedイベントが発生した場合はシリアルポートの受信バッファからソフト側のバッファへ格納、このソフト側のバッファをイベント中にチェックしてCR+LRを見つけたらデータを記録といった処理を行っています。

シリアル機器の監視中はログを取るようにしているのですが、30分毎程度で流れてくるデータを順調に10回程記録していたのですが、それ移行DataReceivedイベントが発生する事も無く2時間程度後にBuffer Overrunが発生し、それ移行もデータの受信は一切無いような状況になりました。
本来であれば30分毎に流れ続けるはずのデータが一切届いてないように見えるのも不思議です。

一度SerialPortをクローズ・オープンし監視を再開したところ、特に問題も無く受信が再開致しました。

この際のバッファオーバーランとは、シリアルポート側のバッファの事を指すと思うのですが、DataReceivedイベントでバッファから読み込みソフト側バッファへ格納しているのに、バッファが一杯になってしまう事はあるのでしょうか。そもそも、イベントが発生していないにも係わらずバッファオーバーランが起きる可能性というのはあるのでしょうか。

なお、「ReceivedBytesThreshold = 1」となっております。

そもそも、DataReceivedイベントではなく、別スレッドでシリアルポートのバッファをループ監視し処理を行った方がよろしいのでしょうか。

引用返信 編集キー/
■76557 / inTopicNo.2)  Re[1]: シリアル通信でバッファオーバーランが発生する
□投稿者/ 774RR (278回)-(2015/07/22(Wed) 10:29:36)
たぶん以下のことが起きているのだと思われる(憶測)

(正常系) 正しくデータ受信する→DataReceived 発生→

(異常系) パリティエラー・フレームエラーなバイトを受信 (ノイズ等)
→このときの挙動を定義していないのだと思われる
ParityReplace を設定して無効データに読み替えるとか
ErrorReceived をハンドルして無効データを捨てるとか

なにもしてないと ParityReplace=63 な様子。
エラーバイトの受信→ ParityReplace で 63 が内部バッファに格納される→
でもこれは正常受信じゃないので DataReceived が発生しない→
エラーバイトが蓄積され、読まなきゃそのうちバッファオーバー
とか?

ErrorReceived もハンドルすればいいんぢゃないかな。
ハンドルした結果どうするのか、 ParityReplace をどうするのか、は案件次第。

引用返信 編集キー/
■76566 / inTopicNo.3)  Re[2]: シリアル通信でバッファオーバーランが発生する
□投稿者/ 通りすがり (16回)-(2015/07/22(Wed) 20:39:43)
"COM1:"等で使うデバイスというか、ファイルですよね。違ったらごめんなさいです。
WindowsのSDKを読むと解るのですが"COM1:"のような通信デバイスは、いわゆる
イベントを発生しないデバイスです。
VB6.0のころから"COM1:"をVBで扱うのは本当に難しいです。他の賢者の方々
はどこまで実際に"COM1:"デバイスを使ったことがあるのかは存じませんが、
モデム等のデバイスをVBで操作するのは自分が扱った物件ではC言語でのDLLに
処理を預けていました。OCX等では1ヶ月とかの長時間連続稼動には耐えたためし
がないからです。
VB.NETでの”イベント発生”がどのように実装されているのかは知りませんが
イベントを発生しないデバイスでイベントを発生させている以上、どこかでデバイ
スを監視するのは確実だと思います。
納得ができない動作をするのであればC言語のスキルがある方を探してAPIを直接
コールするのが問題解決の早道だと思います。
引用返信 編集キー/
■76579 / inTopicNo.4)  Re[2]: シリアル通信でバッファオーバーランが発生する
□投稿者/ jun (7回)-(2015/07/24(Fri) 08:41:43)
ひとまずErrorReceived周りを見なおしてみようと思います。
貴重なご意見ありがとうございました。

No76557 (774RR さん) に返信
> なにもしてないと ParityReplace=63 な様子。
> エラーバイトの受信→ ParityReplace で 63 が内部バッファに格納される→
> でもこれは正常受信じゃないので DataReceived が発生しない→
> エラーバイトが蓄積され、読まなきゃそのうちバッファオーバー
> とか?
>
> ErrorReceived もハンドルすればいいんぢゃないかな。
> ハンドルした結果どうするのか、 ParityReplace をどうするのか、は案件次第。

引用返信 編集キー/
■76580 / inTopicNo.5)  Re[3]: シリアル通信でバッファオーバーランが発生する
□投稿者/ jun (8回)-(2015/07/24(Fri) 08:53:46)
接続しているのはデバイスです。重量計測用の秤です。

ひとまず、もうちょっと今の開発環境で調べてみようと思います。
ご意見ありがとうございました。

No76566 (通りすがり さん) に返信
> モデム等のデバイスをVBで操作するのは自分が扱った物件ではC言語でのDLLに
> 処理を預けていました。OCX等では1ヶ月とかの長時間連続稼動には耐えたためし
> がないからです。
> VB.NETでの”イベント発生”がどのように実装されているのかは知りませんが
> イベントを発生しないデバイスでイベントを発生させている以上、どこかでデバイ
> スを監視するのは確実だと思います。
> 納得ができない動作をするのであればC言語のスキルがある方を探してAPIを直接
> コールするのが問題解決の早道だと思います。
引用返信 編集キー/
■76633 / inTopicNo.6)  Re[3]: シリアル通信でバッファオーバーランが発生する
□投稿者/ hata (1回)-(2015/07/28(Tue) 15:52:11)
データをバッファから単に読み捨てするだけのコードを書いてみて下さい。
これでも「バッファオーバーラン」が起きるかどうか見るためです。

private void serialPort1_DataReceived(object sender, 
                              System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            //読み取るバイトバッファを設定
            byte[] byteRead = new byte[serialPort1.BytesToRead];
            //データを読み取る
            serialPort1.Read(byteRead,0,serialPort1.BytesToRead);              
        }


c#のserialPortモジュールは安定してますので安心して使ても
良いかと思います。
いわゆる「Event Driven」のイベントと「serialPort1_DataReceived」のような
イベントは別物です。
RS-232Cはガチガチのハードで、ハードウェアーから上がる割り込みを
デバイスドライバーが受けて、モジュールに渡します。

引用返信 編集キー/
■76651 / inTopicNo.7)  Re[4]: シリアル通信でバッファオーバーランが発生する
□投稿者/ 通りすがり (18回)-(2015/07/29(Wed) 13:36:45)
質問の掲示板にオオウソを書くのはどうかと思いますがいかがでしょ?

>いわゆる「Event Driven」のイベントと「serialPort1_DataReceived」のような
>イベントは別物です。
>RS-232Cはガチガチのハードで、ハードウェアーから上がる割り込みを
>デバイスドライバーが受けて、モジュールに渡します。

既にオオウソ。デバドラは割り込みを受け付けますが、今のWindowsのデバドラは
直接ハードウェア割り込みをハンドルはしないでしょう。
「モジュールに渡します」
どーやって???

引用返信 編集キー/
■76652 / inTopicNo.8)  Re[5]: シリアル通信でバッファオーバーランが発生する
□投稿者/ 通りすがり (19回)-(2015/07/29(Wed) 13:53:57)
http://d.hatena.ne.jp/Kazzz/20051109
実に参考になる
引用返信 編集キー/
■76656 / inTopicNo.9)  Re[6]: シリアル通信でバッファオーバーランが発生する
□投稿者/ daive (69回)-(2015/07/29(Wed) 16:36:02)
ラインモニタ例(低価格品)
 通信アナライザー/計測器
 http://www.lineeye.co.jp/html/product.html
 LE-200PS / LE-150PS なども、候補かも:使った事は、ありません。
 BITSの「みえちゃん」シリーズを、修理しながら使っています。
232c 横取り ケーブル
 原理的には、232CドライバICが無くても、
 作成は可能だけど。
 ラインの電圧次第、分岐後の電圧が、マーク、スペースの最低電圧より
 下がる場合は、バッファーが必要。
引用返信 編集キー/
■76658 / inTopicNo.10)  Re[7]: シリアル通信でバッファオーバーランが発生する
□投稿者/ hata (2回)-(2015/07/30(Thu) 10:15:30)
現在のPCにRS-232Cのポートが付属しているものは少ないのですが、
RS-232cのハードウエアとはだいたい下の回路のようになっています。
>>http://amahime.main.jp/sirial/main.php?name=siri
これはピックマイコンの回路とC言語のソースですが、
PCに組み込む場合はPCIバスを使います。
PCIバスにおける「デバイスの割り込み」と「デバイスドライバの記述」
に関しては下を見てください。
>>http://docs.oracle.com/cd/E24845_01/html/E22201/interrupt-11.html
PCIのWindows用のデバイスドライバーは、C++,VC,C#用の関数を公開していて、
それを使ってハードウエアの状態を知ることが出来ます。

>>「今のWindowsのデバドラは直接ハードウェア割り込みをハンドルはしないでしょう。」
「今のWindows」とはなんでしょうか?
「今のWindowsのデバドラ」とはなんでしょうか?
Windows用のデバイスドライバーのことですか?
>>https://ja.wikipedia.org/wiki/%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9%E3%83%89%E3%83%A9%E3%82%A4%E3%83%90

>>「直接ハードウェア割り込みをハンドルはしないでしょう」
ハードウエアの割り込み処理なしにどのように「デバドラ」を書くのか
私には理解できません。

>>「モジュールに渡します」
>>どーやって???
デバイスドライバーの開発者が、規格従ってコードを作成します。
I/Oポートのようなものは、言語用の関数が用意されています。

掲示板に書き込むときに誰でもミスはします。
間違いとウソは違うものです。
引用返信 編集キー/
■76659 / inTopicNo.11)  Re[8]: シリアル通信でバッファオーバーランが発生する
□投稿者/ 774RR (288回)-(2015/07/30(Thu) 11:20:07)
元発言者氏のコメントと無関係な方向に話が進んでいるようだ。
シリアル入出力回路とドライバの詳細について議論したいなら別スレッド立てておくれ。

とりあえずウチでは Win32API レベルでのシリアル入出力で問題になったことはない。
数週間連続運用してちゃんと動いている。

.NET 系の SerialPort クラスは、短期間では問題なかった。
長期間の本格運用を試したことはないのでコメントできない。
まあたぶん問題ないと思うぞ。

この手の通信のデバッグには、信頼できる計測器があるととても助かる。
現象再現まで数ヶ月かかるような事象であっても、計測器をつなぐとあっさり間違いが判ることもある。
その再現させるまでの期間=人件費なので計測器を購入する(購入依頼する)のもアリ、かも。
# USB HID のデバッグは USB Protocol analyzer 無しでは無理だったと思う。

んで:この件、1時間に1回しか通信しないから再現まで極端に時間を要しているわけだろう?
パソコンソフトとして秤シミュレータなるものを作ってみて、パソコン同士を直結してみるといい。
そして高頻度で通信してみる加速試験を行おう。

ソフトを作るのがめんどくさけりゃ TeraTerm 等の信頼できる通信ソフトを使って
「バイナリデータの送信」 (TeraTerm なら Send file → Binary) でも事足りることが多い。

引用返信 編集キー/
■76718 / inTopicNo.12)  Re[9]: シリアル通信でバッファオーバーランが発生する
□投稿者/ jun (9回)-(2015/08/05(Wed) 17:40:46)
No76659 (774RR さん) に返信
> この手の通信のデバッグには、信頼できる計測器があるととても助かる。
> 現象再現まで数ヶ月かかるような事象であっても、計測器をつなぐとあっさり間違いが判ることもある。
> その再現させるまでの期間=人件費なので計測器を購入する(購入依頼する)のもアリ、かも。
> # USB HID のデバッグは USB Protocol analyzer 無しでは無理だったと思う。
>
>
> ソフトを作るのがめんどくさけりゃ TeraTerm 等の信頼できる通信ソフトを使って
> 「バイナリデータの送信」 (TeraTerm なら Send file → Binary) でも事足りることが多い。

色々とお知恵を拝借いただき光栄です。

あれから、コードを見直しまして結果的には現在安定(?)して稼動しております。

・DataReceivedイベントを使わないこと
・別スレッドで絶えずループにてシリアルポートのバッファを監視すること
・ParityErrorの場合はデフォのまま63で置き換え

といった事をやっております。
バッファオーバーランは発生しておりませんし、エラーバイトも回避できているみたいです。

この状態で稼動させていて気づいたのは、ケーブル長が長い端末だけParityErrorが頻発している事です。
データを受信するはずのない状況にも係わらず何バイトか不定期に受信している事も見受けられました。
ケーブルの長さの問題・ノイズ対策も視野に入れなければならなそうです。

774RRさんが当初おっしゃっていた

> エラーバイトの受信→ ParityReplace で 63 が内部バッファに格納される→
> でもこれは正常受信じゃないので DataReceived が発生しない→
> エラーバイトが蓄積され、読まなきゃそのうちバッファオーバー

これが問題なのかもしれません。
いまのところ問題が発生していないようなので、このまま稼動させ様子を見てみようと思います。

> んで:この件、1時間に1回しか通信しないから再現まで極端に時間を要しているわけだろう?
> パソコンソフトとして秤シミュレータなるものを作ってみて、パソコン同士を直結してみるといい。
> そして高頻度で通信してみる加速試験を行おう。

開発当初より秤シミュレータといいますか、同様のバイナリデータを作成し、クロスケーブルでのテストをやっておりまして、速度・回数共に想定以上のものを流しておりますが、特に問題は発生していませんでした。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -