現在の開発テーマは、多分力センサx多点のひずみゲージセンシングシステムなので、CH数はどんどん増えていきます。1つのCHで扱えるデータ量も限界があるので、複数のUSBポートからVBで受信して、各CH間の同期をとって、整理することが何ポートまで対応できるか実験してみました。
※本実験は、複数ポートでのシリアル受信ログの実験です。
リアルタイム受信ではありませんので、ファイルにログする使い方の場合は
4ポートまでデータログができそうという結果です。リアルタイム受信して画面にTEXTとグラフ表示をしたい場合は、PCの描画性能によりますが、ポート数が増えるほど、受信データ周期はポート数に比例して遅くしないとデータ落ちがでて、受信失敗確率が増えていきます。下記実験例では、2ポートでも古いPC(INTEL HD graphics4000)では50msec周期受信がぎりぎりでした。
■実験条件
USBシリアルポート 番号 <115200bpsで統一> |
マイコンと送信データ 各データの最後にタイムスタンプをつけてあるので欠落が検出できる |
COM6 | mbed NucleoL432KC+AD7194EVAL 7CH 10msec周期送信約37byte |
COM8 | mbed NucleoF446ZE 7CHダミーデータ 4msec周期送信約37byte |
COM10 | M5ATOM lite 7CHダミーデータ 4msec周期送信約37byte |
COM11 | M5ATOM lite 5CHロードセルデータ 10msec周期送信約30byte |
COM12 | M5ATOM lite 7CHダミーデータ 4msec周期送信約37byte |
USBHUB4CHと残り1CHは、PC直差しで5CH
■実験で使ったフォーム
SerialPortコントロールを5個に増やして、
COM番号のTextBoxも5個にしてあります。
SerialPortのPropertyにボーレートとCOM番号をあらかじめ登録しておきます。
■結果
①2ポート受信
COM6が11-12msec周期、COM8が3-4msec周期で交互に受信できてます
何故交互になるかは後で考察します
②3ポート受信
COM6>COM8>COM10の順で周期も合ってます
④4ポート受信
COM6>COM8>COM10>COM11の順で周期も合ってます。
⑤5ポート受信こけた
COM11が重なってしまってCOM12が出てきません。
たぶんタイミングに問題なので、マイコンの送信周期が重ならないようになればもっと多くのCHでもOKだと思います。私の場合は、5~20msec周期が多いのでこの条件で実験した次第です。
■プログラムのTIPS
割り込み処理はコンテック社のままブラックボックスで使わせていただいているのですが、割り込み処理の書き方でデータの順番がかわるので、TIPSがあります。下記に4CHのDataReceive関数ですが、
受信タイミングをHandleするのはSerialPort1で統一してあります。
当初、各CH番号でHandlesを書いたら、出鱈目順になってしまったので
ここをSerialPort1に統一したら、順序正しく出力されました。
●ReceivedData1,2,3,4,5をClass直下のPrivateで宣言しておくこと
=>個々の割り込みメソッドなので外にでると変数が消えてしまうため
※今回は、Deligate,Invokeを各CHで設定してますが1つの割り込みメソッド内で全Chの受信命令を実行してデータを1本にまとめてしまえば、5Chもできるかもしれません
Private Sub SerialPort1_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived Try ReceivedData1 = SerialPort1.ReadLine ‘データを受信しますCatch ex As Exception ReceivedData1 = ex.Message ‘例外処理を行います End Try ‘Invokeメソッドにより実行されるメソッドへのデリゲートの宣言を行い、受信データを表示します Dim adre As New DataDelegate(AddressOf PrintData) Me.Invoke(adre, ReceivedData1) End Sub Private Sub SerialPort2_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles SerialPort1.DataReceivedTry ReceivedData2 = SerialPort2.ReadLine ‘データを受信します Catch ex As Exception ReceivedData2 = ex.Message ‘例外処理を行います End Try ‘Invokeメソッドにより実行されるメソッドへのデリゲートの宣言を行い、受信データを表示します Dim adre As New DataDelegate(AddressOf PrintData) Me.Invoke(adre, ReceivedData2)End Sub Private Sub SerialPort3_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles SerialPort1.DataReceivedTry ReceivedData3 = SerialPort3.ReadLine ‘データを受信します Catch ex As Exception ReceivedData3 = ex.Message ‘例外処理を行います End Try ‘Invokeメソッドにより実行されるメソッドへのデリゲートの宣言を行い、受信データを表示します Dim adre As New DataDelegate(AddressOf PrintData) Me.Invoke(adre, ReceivedData3)End Sub Private Sub SerialPort4_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles SerialPort1.DataReceivedTry ReceivedData4 = SerialPort4.ReadLine ‘データを受信します Catch ex As Exception ReceivedData4 = ex.Message ‘例外処理を行います End Try ‘Invokeメソッドにより実行されるメソッドへのデリゲートの宣言を行い、受信データを表示します Dim adre As New DataDelegate(AddressOf PrintData) Me.Invoke(adre, ReceivedData4)End Sub |
■プログラムソースコードはGISTにアップしてあります。
https://gist.github.com/dj1711572002/f3502968e4e6cd4405412876b1532896
ソリューションはZIPで添付してあります。
Serial_2Ports_Test_rev00
●以後
当面は2ポート受信でシステムを組んでいきます。4ポートまで可能なら
いろいろシステムが融通がきくので助かります。
しかし、システムを組んでいくとスループットがおちるので、複数ポートが苦しくなるかもしれませんので
2ポートを必達でシステムを組んでいきます。
※追伸 9月27日 USBシリアル2ポート受信16CHプログラム完成
本記事は、データ欠落無しの複数ポートで受信する方法の実験ですが、
リアルタイム受信ではありません。リアルタイム受信のためのプログラムを
作りました。
2ポートで、データ間のリアルタイム同期を実現するためには、本記事の方法に追加してシリアル受信バッファを定期的に空にする操作が必須です。読込周期の間にバッファ空にすることで、両CH間の受信タイミングずれは
1周期以内に収まって、リアルタイムグラフで同期がとれた波形をみることができます。