既存装置をSiLA 2へ接続する|SCPI・シリアル通信・メーカーSDKのラッパー設計

既存装置をSiLA 2へ接続するのアイキャッチ

既存の実験装置をSiLA 2へ接続するとき、装置の通信処理をSiLA Serverへ直接書き込むと、保守しにくい「巨大なドライバー」になりがちです。実務では、SiLA Feature、装置に依存しない共通ドライバー、SCPI・シリアル通信・メーカーSDKを扱うアダプターの3層に分けると、装置交換と試験が容易になります。

この記事では、温度調節装置を例に、既存装置をSiLA 2の共通インターフェースへ変換するラッパー設計を解説します。SCPI、行指向シリアル、メーカーSDKを同じ操作で扱うPythonコードも用意し、実機を使わず正常系と代表的な異常系を検証しました。

この記事で学べること

  • 「SiLA 2対応」と「既存通信をSiLA 2で包むこと」の違い
  • SiLA Feature、共通ドライバー、装置アダプターの責任分担
  • SCPI、シリアル通信、メーカーSDKを選ぶ判断基準
  • タイムアウト、不正応答、装置エラーを共通エラーへ変換する方法
  • 実機導入前に模擬装置で検証すべき項目

仕様・SDKの確認日:2026年10月13日。本文では、SiLA 2の規格上の考え方、各ライブラリ固有の動作、R&D Compass編集部の設計推奨を区別して記載します。

結論:装置固有通信はSiLA Featureから隔離する

SiLA 2は、装置が提供する能力をFeatureとして公開し、ClientがCommandやPropertyを介して利用する仕組みです。Featureは「温度を設定する」「現在温度を読む」といった意味を表し、装置が内部でSCPIを使うか、RS-232の独自文字列を使うか、DLL形式のSDKを使うかまでClientへ見せる必要はありません。SiLA公式も、ServerがFeatureを実装し、ClientはFeatureを通じてServerの能力を利用する構造を説明しています[1]。

推奨する構造は次の4段です。

層 役割 装置交換時の変更
ワークフロー/SiLA Client 実験条件を指定し結果を受け取る 原則なし
SiLA Feature実装 Command・Property・SiLAエラーを提供する 意味が同じなら原則なし
共通ドライバー set_target、read_statusなど装置非依存の契約を定義する 原則なし
装置アダプター SCPI、シリアル、SDKを実際に呼び出す ここを差し替える

この分離はSiLA 2の必須実装方式ではなく、編集部の推奨設計です。しかし、Featureの意味と装置通信を分けることで、同じSiLA Serverを複数メーカーの装置へ展開しやすくなります。

SCPI・シリアル・メーカーSDKは何が違うのか

SCPI:計測器で広く使われる共通のコマンド言語

SCPIは、コンピューターと試験・計測器の間で使う共通コマンド言語です。IEEE 488.2を基礎とするソフトウェア規格で、ASCII文字列としてGPIB、RS-232、LANなど複数の通信経路で利用できます[2]。つまり、SCPIはケーブル規格ではありません。

一般に、値を設定するCommandと、末尾に「?」を付けて値を取得するQueryを使います。例えば、仮想的な温度装置なら、SOUR:TEMP 40で設定し、MEAS:TEMP?で温度を問い合わせます。SCPIのコマンドは木構造を持ち、*IDN?などの共通コマンドと、コロンで階層を表すサブシステムコマンドがあります[3]。

向いている場合:装置マニュアルにリモートコマンド一覧があり、コマンド体系が比較的安定している場合です。PythonではPyVISAを使うと、GPIB、RS-232、USB、Ethernetなどの違いをある程度吸収できます[4]。

行指向シリアル:単純だが、細部を自分で決める必要がある

RS-232やUSB仮想COMポートでは、装置独自の文字列を送受信する場合があります。例えばSET T=40.00\r\nを送り、OK\r\nを受け取る方式です。仕組みは単純ですが、ボーレート、データ長、パリティ、ストップビット、フロー制御、文字コード、終端文字、読取タイムアウトを一致させる必要があります。pySerialのAPIも、これらを個別パラメーターとして扱います[5]。

向いている場合:通信仕様が公開され、応答形式が明確で、メーカーSDKへ依存したくない場合です。ただし「改行を待ち続けて停止する」「途中まで届いた文字列を正常応答と誤認する」といった事故を避ける実装が必要です。

メーカーSDK:高機能だが、配布条件と保守性を確認する

メーカーSDKは、複雑な装置機能を高水準のメソッドとして提供します。バイナリデータ、校正、装置状態、特殊な同期処理を扱いやすい一方、特定OS、特定Python・.NET版、USBドライバー、ライセンス、GUIセッションに依存する場合があります。

向いている場合:公開プロトコルだけでは必要機能へ到達できない場合、SDKが公式に保守されている場合、SDKの戻り値と例外をテストできる場合です。「SDKがあるから最も安全」とは限りません。更新方針、対応OS、再配布条件、ヘッドレス運転可否を調達時に確認します。

ラッパー設計の中心は「共通契約」である

最初にSCPI文字列を書くのではなく、SiLA Featureが必要とする装置能力をPythonのProtocolとして定義します。次の例では、装置種別にかかわらず、識別、目標温度設定、状態取得という3操作だけを公開します。

class TemperatureDevice(Protocol):
    def identify(self) -> str: ...
    def set_target_c(self, value: float) -> None: ...
    def read_status(self) -> DeviceStatus: ...

SiLA側のサービスはこの共通契約だけを参照します。

class TemperatureFeatureService:
    def __init__(self, device: TemperatureDevice) -> None:
        self._device = device

    def set_target_temperature(self, value: float) -> None:
        self._device.set_target_c(value)

    def get_current_temperature(self) -> float:
        return self._device.read_status().temperature_c

公式SDKで生成したFeature Baseクラスでは、Command実装からこのサービスを呼び出します。SDKのメソッド名やデコレーターは実装ごとに異なるため、規格そのものと混同しないことが重要です。SiLA Featureの分け方やデータ型の決め方は、別記事「SiLA 2のFeature設計」で詳しく扱います(公開後に内部リンクを追加予定)。

3種類のアダプターをどう実装するか

SCPIアダプター:writeとqueryを区別し、エラーキューを確認する

設定コマンドは送信に成功しても、装置内部で拒否されることがあります。そのため、通信成功と処理成功を分けて判定します。実装例では設定後にSYST:ERR?を問い合わせ、0,No error以外を装置実行エラーへ変換します。

def set_target_c(self, value: float) -> None:
    validate_target(value)
    self._io.write(f"SOUR:TEMP {value:.2f}")
    error = self._query("SYST:ERR?")
    if not error.startswith("0,"):
        raise DeviceExecutionError(f"SCPI error queue: {error}")

実機では、装置マニュアルが定めるエラー取得方法、コマンド完了待ち、ステータスレジスターを優先してください。全装置がこの仮想コマンドを実装するわけではありません。

シリアルアダプター:終端文字と部分書込みを確認する

シリアル通信では、送信したバイト数、受信終端、文字コードを明示的に確認します。空応答はタイムアウト、終端なしはプロトコル違反として分けます。

payload = command.encode("ascii") + b"\r\n"
if port.write(payload) != len(payload):
    raise DeviceProtocolError("serial partial write")
raw = port.read_until(b"\r\n")
if not raw:
    raise DeviceTimeout("serial timeout")
if not raw.endswith(b"\r\n"):
    raise DeviceProtocolError("terminator was not received")

pySerialではtimeoutとwrite_timeoutを設定できます[5]。無期限待機を本番のServerスレッドに持ち込まないことが重要です。

SDKアダプター:メーカー例外を外へ漏らさない

メーカーSDKの例外クラスや数値エラーコードを、そのままSiLA Clientへ公開すると、装置交換でClientまで変更が必要になります。アダプター内で、入力不正、タイムアウト、応答形式不正、装置実行失敗などの共通分類へ変換します。ただし、保守ログには元の例外、エラーコード、SDK版、装置シリアル番号を残します。

SiLAエラーへどう対応付けるか

共通ドライバーの結果 SiLA側の扱い 再試行の考え方
入力範囲外 Validation Error 同じ入力では再試行しない
装置が条件を拒否 Defined Execution Error 原因を解消後に判断
応答形式不正 DefinedまたはUndefined Execution Error 自動再試行前に状態確認
通信タイムアウト 実行状態に応じてDefined/接続エラー 二重実行を防ぐ
予期しないSDK例外 Undefined Execution Error ログと装置状態を調査

タイムアウトしたからといって、処理が実行されていないとは限りません。応答だけ失われ、装置は設定を変更済みかもしれません。書込み系Commandを無条件に再送すると二重注入、二重測定、二重搬送につながります。再試行前に現在値、装置状態、実行IDを確認できる設計にします。

導入手順:1台を小さく包み、境界を試験する

  1. 操作一覧を作る:設定、読取、開始、停止、校正、結果取得を列挙する。
  2. 危険操作を分ける:衝突、過熱、加圧、薬品移送などは装置内安全機能と責任分界を決める。
  3. 最小Featureを決める:最初は識別、状態取得、安全な1操作に絞る。
  4. 共通契約を定義する:単位、範囲、状態、例外を装置非依存で記述する。
  5. アダプターを実装する:SCPI、シリアル、SDK固有処理を閉じ込める。
  6. 模擬装置で試験する:正常応答だけでなく、無応答、遅延、途中応答、不正値、SDK例外を発生させる。
  7. 実機PoCを行う:電源再投入、ケーブル抜去、装置ローカル操作との競合、長時間運転を確認する。
  8. SiLA Serverへ統合する:Feature Command・Propertyと共通サービスを結び付ける。
  9. 運用情報を固定する:装置ファーム、SDK、ドライバー、VISA、設定ファイルの版を記録する。

実験装置とLIMS・データベースを結ぶ全体像は、実験装置・LIMS・データベースを連携する設計も参考になります。規格の役割分担は、実験自動化の通信・制御・標準を整理するで整理しています。

実行できるPython例と検証結果

サンプルコードは標準ライブラリだけで動きます。SCPI、シリアル、SDKの模擬バックエンドを同じTemperatureDevice契約へ接続し、Featureサービスから40℃を設定して状態を読みます。実機へ置き換える際は、FakeScpiTransportをPyVISA Resource、FakeSerialPortをserial.Serial、FakeVendorSdkをメーカーSDKオブジェクトへ差し替えます。

python3 device_adapter_demo.py
python3 -m unittest -v test_device_adapter_demo.py

検証環境では9件の自動試験がすべて成功しました。

試験 期待結果 結果
SCPI・シリアル・SDKの共通操作 40℃設定とREADY取得 成功
設定範囲外 装置へ送る前に拒否 成功
SCPIタイムアウト DeviceTimeoutへ変換 成功
SCPIエラーキュー DeviceExecutionErrorへ変換 成功
SCPI数値不正 DeviceProtocolErrorへ変換 成功
シリアル無応答・終端欠落・形式不正 異常を区別して検出 成功
メーカーSDK例外 共通実行エラーへ変換 成功

この試験は設計例のロジックを検証したもので、特定メーカー装置との相互接続試験ではありません。PyVISAの利用にはVISAバックエンド、シリアル実機には正しい電気仕様とポート設定が別途必要です。

よくある失敗

失敗1:Feature実装へSCPI文字列を直接散らす

コマンド変更が複数箇所へ波及し、模擬試験もしにくくなります。アダプターへ集約し、SiLA側は共通契約だけを見るようにします。

失敗2:応答が返れば成功と判断する

装置がエラー文字列を返している、値が適用範囲へ丸められた、処理がまだ完了していない可能性があります。エラーキュー、状態、実際の設定値を確認します。

失敗3:タイムアウト後に同じCommandを即時再送する

装置側で処理済みなら二重実行になります。読取可能な現在状態と、処理を一意に識別する情報を設計します。

失敗4:SDKの型と例外をFeatureへ漏らす

Clientがメーカー固有実装へ依存します。アダプターで共通データ型とエラーへ変換し、詳細はログへ残します。

失敗5:SiLA Serverを安全制御装置として扱う

ネットワーク越しのServerは、非常停止、インターロック、過温・過圧保護の代替ではありません。安全機能は装置、PLC、安全リレーなど適切な層で実装し、SiLAは上位の操作と状態取得を担います。

限界・不確かさ・責任範囲

ラッパーは異なる通信方式を同じ意味へそろえますが、装置能力そのものを同一にするわけではありません。温度精度、設定分解能、更新周期、校正状態、処理完了条件が異なるなら、共通インターフェースでもその差を明示する必要があります。

また、SiLA 2接続が成立しても、危険な操作が安全になるわけではありません。装置メーカーは装置内部の安全仕様、システム統合者はインターフェースとワークフロー、利用組織はリスク評価・権限・手順・教育に責任を持ちます。自動運転へ進む前に、実験自動化の導入手順と、自律実験の仕組みと導入手順も確認してください。

導入前チェックリスト

  • 通信方式、コマンド仕様、SDK版、対応OSが文書化されている
  • 読取タイムアウトと書込タイムアウトを設定した
  • 終端文字、文字コード、単位、小数点、ロケールを固定した
  • 装置エラーと通信エラーを区別できる
  • タイムアウト後に処理済みか確認できる
  • 同じ操作の二重実行を防止できる
  • 装置交換時にアダプターだけを差し替えられる
  • 模擬装置で無応答、不正応答、SDK例外を試験した
  • 実機で電源断、再接続、ローカル操作との競合を試験した
  • 非常停止とインターロックがネットワークから独立している

FAQ

Q1. SCPI対応なら、そのままSiLA 2対応ですか?

いいえ。SCPIは装置コマンド言語、SiLA 2はFeatureを公開するClient/Server標準です。SCPIコマンドを呼ぶSiLA Serverを作ることで両者を接続できます。

Q2. PyVISAとpySerialはどちらを使うべきですか?

装置がVISA Resourceとして扱え、SCPIなどのコマンド仕様があるならPyVISAが便利です。独自の行プロトコルを仮想COMポートで扱うならpySerialが直接的です。装置マニュアルとサポート範囲を優先してください。

Q3. メーカーSDKがある場合も共通ドライバーは必要ですか?

長期運用や装置交換を考えるなら有効です。SDKのメソッド、型、例外をアダプター内に閉じ込めることで、SiLA Featureを安定させられます。

Q4. 1台の装置を複数Clientから操作できますか?

技術的に接続できても、同時操作が安全とは限りません。排他制御、所有権、予約、状態遷移、タイムアウト後の解放を設計してください。

Q5. 既存装置を包めば、メーカー保証は維持されますか?

保証条件は製品ごとに異なります。公開API・SDKの使用条件、サポート対象のドライバー、遠隔操作の制限をメーカーへ確認してください。

まとめ

既存装置をSiLA 2へ接続する要点は、装置通信をSiLA Featureへ直書きせず、共通ドライバーと装置アダプターへ分離することです。SCPIは共通コマンド言語、シリアル通信は低レベルの送受信、メーカーSDKは製品固有APIであり、それぞれのエラーや戻り値を共通の意味へ変換します。

最初のPoCでは、1台・1Feature・1つの安全な操作から始め、正常系より先に無応答、不正応答、装置拒否、二重実行の危険を試験してください。そうすることで、装置を交換しても上位ワークフローを変えにくいSiLA 2接続へ近づけます。

参考文献

  1. SiLA Association, “Standards – High Level Overview,” SiLA 2 Core, Mapping and Features. https://sila-standard.com/standards/(2026年10月13日確認)
  2. IVI Foundation, “The SCPI Standard.” https://www.ivifoundation.org/About-IVI/scpi.html(2026年10月13日確認)
  3. Keysight Technologies, “SCPI Basics,” instrument help documentation. https://helpfiles.keysight.com/csg/n5106a/scpi_basics.htm(2026年10月13日確認)
  4. PyVISA Project, “PyVISA 1.16.1 documentation.” https://pyvisa.readthedocs.io/en/1.16.1/(2026年10月13日確認)
  5. Chris Liechti et al., “pySerial API,” pySerial 3.5 documentation. https://pyserial.readthedocs.io/en/latest/pyserial_api.html(2026年10月13日確認)

コメントする

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です

CAPTCHA


上部へスクロール