プロジェクト

全般

プロフィール

Javaシリアル通信

計算機の通信手段として古くから使われ、現在でも組み込み・制御系でよく使われているシリアル通信をJavaから利用する方法をまとめます。

シリアル通信の構成

RS-232としてPCなどの端末装置(Data Terminal Equipment: DTE)とモデムなどの回線終端装置(Data Circuit Terminating Equipment: DCE)とを結ぶ通信のための電気信号・コネクタ等が規定されました。汎用性が高く、DTEとDCEの間の通信だけではなく、産業機器の機器間通信に広く使われています。RS-232Cの信号は10m程度は通信可能とされていますが、さらにノイズ耐性を高めたRS-485では1000m以上の距離の通信も可能とされています。

Javaからシリアル通信を使う方法

Java SE 標準APIにはシリアル通信は含まれていませんが、Sun Microsystemsが拡張APIとしてシリアル通信のAPIである Java Serial Communication API を定義しました。そして、このAPIの実装が同じくSun Microsystemsから提供されていました。
しかし、バージョン3.0からはWindows版の実装が除外されてしまい、他のOS版もその後アップデートもされなくなりました。

Sun MicrosystemsのJava Serial Communication API実装の代替として、RXTXと呼ぶオープンソースのシリアル通信ライブラリが存在します。配布サイトは維持されていますがバージョンアップは久しく行われていません。RXTXの実装にはいろいろ課題もあるようです。
http://rxtx.qbang.org/wiki/index.php/Main_Page

RXTX以外にもいくつかオープンソースのシリアル通信ライブラリが登場しています。

jSerialComm
http://fazecast.github.io/jSerialComm/
APL2とLGPLv3のデュアルライセンス。RXTXの安定した代替を目指している。
2015年にv1.0.0がリリース、以降2018年にv2.0.0がリリース、こまめにアップデート中で、2022年2月にはv2.9.0がリリース。

PureJavaComm
http://www.sparetimelabs.com/purejavacomm/purejavacomm.php
修正BSDライセンス。JNAを使いネイティブコードを使わない実装をしている。
2016年にv1.0.1がリリース、2017年にv1.0.2、2019年にv1.0.3がリリース。

Java Simple Serial Connector (JSSC)
https://code.google.com/archive/p/java-simple-serial-connector/
LGPLv3ライセンス。2014年にv2.8.0がリリースされ、その後は更新ないようです。

商用製品のライブラリもいくつかあります。

Java Serial Port
https://www.serialio.com/java-developer

Javaシリアル通信の実現

jSerialComm

シリアル通信開発環境

Windowsマシンに仮想シリアルポートを設ける

com0com を用いた仮想シリアルポートの設定

Windows OS上に2つの相互にクロスケーブルで結ばれた設定での仮想COMポートを作成するオープンソースのツール com0com を使います。
http://com0com.sourceforge.net/

同一マシン上で2つのシリアル通信プログラムを実行し、相互にシリアル通信をさせることができるので、シリアルポートがないマシンで開発・テストをするのに有用です。

com0comの使い方

シリアル通信あれこれ

メッセージ定義

キャラクタと開始・終了

シリアル通信では、一般的にはキャラクタ(8bit)単位で通信を行う。データは文字列(ASCII)の範囲とし、先頭と最後に識別用データ(STX、ETX)を付与することが多い。

バイト列 02H 48H 65H 6cH 6cH 6fH 03H
キャラクタ STX 'H' 'e' 'l' 'l' 'o' ETX

ACKとNAK

要求・応答で組み合わせるメッセージでは、正常応答時はACKを、異常応答時はNAKを返すことが多い。

バイト列 06H 6fH 6bH 03H
キャラクタ ACK 'o' 'k' ETX

チェックサム

modulo-2 加算

2進数の1桁同士をXORで演算した結果となります。バイト列のチェックサムをmodulo-2加算で計算する場合は、各バイトをXORします。

バイト    ビット並び
02H       0 0 0 0 0 0 1 0
48H       0 1 0 0 1 0 0 0
65H       0 1 1 0 0 1 0 1
6cH       0 1 1 0 1 1 0 0
6cH       0 1 1 0 1 1 0 0
6fH       0 1 1 0 1 1 1 1
03H       0 0 0 0 0 0 1 1
--------------------------
sum       0 1 0 0 0 0 1 1  ===> 43H
jshell> System.out.printf("%x%n", 0x02 ^ 0x48 ^ 0x65 ^ 0x6c ^ 0x6c ^ 0x6c ^0x6f);
43


約2年前に更新