古川制御日記

佐賀県武雄市の組み込み開発屋ブログ

Arduino Due Native Portからのデータを受信する方法

System.IO.Ports.SerialPort.DtrEnable = true; // ほんとはインスタンスプロパティ

C#Arduino Due Native Portと通信するプログラムを組んでいて、
ホストPCからの送信データをArduino側で受信するのはすんなりできたが、
Arduinoからの送信データをホストPCで受信するのに難儀した。

ちなみにTeratermではなんなく送受信できておりあきらかに自作C#プログラムに問題がある、ってのはわかった。
C#ではSystem.IO.Ports.SerialPortを使ってて、Arduino Due Native PortじゃないSerial間の送受信は難なくできてる。 System.IO.Ports.SerialPortのプロパティを色々見てるとDtrEnableというものがあり試しにこれをtrueにしてみると受信できた。

DTRはData Terminal Readyの意味でWikipediaとDeepLによると

DTR(Data Terminal Ready)は、RS-232シリアル通信の制御信号で、
コンピュータなどのデータ端末機器(DTE)からモデムなどのデータ通信機器(DCE)に送信され、
端末が通信の準備ができていることを示し、モデムが通信チャネルを開始することができます。

とのことらしい。
この場合は端末側がC#ホストプログラムで、モデム側はArduinoということになる。
C#ホストプログラムが受信出来るよ、というのを伝えるまではArduino/SerialUSBはホストに送るデータが発生したとしても送信するのを待ってくれる(多分デバイスドライバ側でまってるわけじゃないよな)。
SerialUSBにwriteしたときの挙動としてはとくにブロッキングしてる風ではないので、バッファリングくれてるんだろう(多分デバイスドライバ側でまってるわけじゃないよな)。

DTR値をSerialUSBでモニタできればホスト側のプログラムが活性状態かどうか確認できるので便利になるが、
SerialUSBではその情報を取得するすべがある。(ありがてぇ)
SerialUSBの型であるclass Serial_の定義を見るとそのまんまだけど、bool Serial_::dtr()というインスタンスメソッドがありそれでホストプログラムの活性状態を見ることが出来る。
C#ホストプログラムとしては、
System.IO.Ports.SerialPort.DtrEnableをtrueにする必要がある。
C#ホストプログラムが何らかの例外が発生して予期せず死んで正常に終了処理がなされなかったとしてもSerialUSB.dtr()は正常にfalseになってくれる。

ちなみにSerialUSBではないSerialや、Serial[123]は
UARTClass型(もしくはその派生型)でありこれらにはdtr()メソッドはない。
そもそもそのための信号が物理的につながってないのでまぁそれはそう。
DTRで接続相手の死活を監視できるのはSerialUSBならではの利点ということになる。