en ja

上位制御層 (xdm1000_ctrl.py)

xdm1000_ctrl.py は、XDM1000 / XDM1241 を測定器として扱う上位制御クラスを提供する。SCPI 低レベル API をそのまま公開する層ではない。

現在の上位制御層は、測定器状態を明示的に設定してから meas() または meas_continue() を呼ぶ構成である。測定モード、レンジ、内部測定速度、連続測定条件は ctrl 層がキャッシュし、worker process 側にも共有 state として反映する。

責務分離

SCPI 層

xdm1000_scpi.py は低レベル SCPI ラッパである。

主な責務は以下である。

serial.Serial を開く
SCPI コマンドを write/query する
*IDN? を問い合わせる
FUNCtion / RANGE / RATE / MEAS1? などを薄く包む

ctrl 層

xdm1000_ctrl.py は利用者向け API を提供する。

主な責務は以下である。

測定モード名を ctrl API 名として整理する
測定モード、レンジ、オートレンジ、内部測定速度を保持する
単発測定と連続測定の入口を分ける
連続測定条件を保持する
process 分離時の worker との RPC を管理する
測定結果を result store に保存する

worker 層

xdm1000_worker.py は use_process=True のとき、子プロセス側で SCPI 実体を保持する。

主な責務は以下である。

親プロセスから command queue で指示を受ける
SCPI オブジェクトを保持する
測定器状態を共有 state に反映する
単発測定結果および連続測定結果を result store に保存する

公開される主な API

現在の Xdm1000Ctrl の主な公開 API は以下である。

close()
disconnect()
get_state()
is_running()
idn()
set_mode(mode)
set_range(value=None, index=None, range_value=None)
set_auto_range(enabled)
set_integration_speed(speed)
set_continue_interval(interval)
set_continue_duration(duration)
set_continue_count(count)
meas(wait=None)
meas_continue(wait=None)
get_result(clear=False)
wait_until_done(poll_interval=0.2)

以下は旧 API であり、現在の Xdm1000Ctrl には存在しない。

stop_job()
get_continuous_result(clear=False)
get_statistics_result(clear=False)
set_meas_mode(kind, range_value="AUTO", rate="F")
meas_one_shot(kind=None, range_value=None, rate=None, settle=0.0)
meas_voltage_dc(range_value=None, rate=None, settle=0.0)
meas_current_dc(range_value=None, rate=None, settle=0.0)
start_continuous_meas(kind=None, duration=0.0, range_value=None, rate=None, interval=0.0, settle=0.0)
start_statistics_mode(kind=None, duration=0.0, range_value=None, rate=None, settle=0.0)

remote()、local()、query()、write() は公開しない。これらは SCPI 層の API である。

use_process=True

use_process=True では、親プロセスが利用者 API を受け、子プロセスである worker が SCPI 通信を担当する。

Xdm1000Ctrl
├── Parent Process
│   ├── command_q
│   ├── response_q
│   ├── Manager().dict() state
│   ├── Manager().dict() result_store
│   ├── Event stop_event
│   └── Lock rpc_lock
└── Worker Process
    └── _Xdm1000Worker
        └── Xdm1000Scpi
            └── serial.Serial

worker process のみがシリアルポートを保持する。親プロセスは SCPI を直接実行しない。

親プロセス側の meas_continue() は worker に開始要求を送り、{"job_id": "..."} を受け取って戻る。測定ループは worker 側で継続する。結果は get_result() で取得する。

use_process=False

use_process=False では、Xdm1000Ctrl 自身が Xdm1000Scpi を生成する。SCPI は同一プロセス内で直接実行される。

meas_continue() は同じ API 名だが、バックグラウンド化されず、呼び出し元でブロッキング実行される。終了後、戻り値として {"job_id": "..."} を返す。

初期化

Xdm1000Ctrl(
    port=None,
    timeout=2.0,
    baudrate=115200,
    logger=None,
    log_level=None,
    config=None,
    use_process=True,
)

config がある場合は PORT、TIMEOUT、BAUDRATE を優先する。最終的に port がない場合は ValueError である。

use_process=True の場合、初期化時に mp.Manager()、command queue、response queue、stop event、RPC lock、worker process を生成する。

use_process=False の場合、初期化時に Xdm1000Scpi を生成し、remote() を実行する。

state

get_state() は現在状態を dict として返す。

use_process=True では共有 dict に process_alive を追加して返す。use_process=False では direct 用状態に process_alive=False を追加して返す。

主なキーは次である。

worker_alive
process_alive
port
baudrate
running
job_id
job_type
started_at
finished_at
error
traceback
message
args
mode
range_value
auto_range
integration_speed
continue_interval
continue_duration
continue_count

mode、range_value、auto_range、integration_speed、continue_interval、continue_duration、continue_count は ctrl 層が保持する設定キャッシュである。

running 中の制約

次の API は running 中に実行できない。

idn()
set_mode()
set_range()
set_auto_range()
set_integration_speed()
set_continue_interval()
set_continue_duration()
set_continue_count()
meas()
meas_continue()

running 中に呼ぶと DeviceBusyError が送出される。

次の API は running 中でも呼べる。

get_state()
is_running()
get_result()
wait_until_done()

現在の実装には stop_job() はない。連続測定は continue_duration または continue_count に到達すると終了する。

測定モード

ctrl API の測定モード名と SCPI FUNCtion パラメータの対応は以下である。

voltage_dc      -> VOLT
voltage_ac      -> VOLT AC
current_dc      -> CURR
current_ac      -> CURR AC
resistance      -> RES
fresistance     -> FRES
frequency       -> FREQ
period          -> PER
capacitance     -> CAP
temperature_rtd -> TEMP
diode           -> DIOD
continuity      -> CONT

未対応の mode を指定すると ValueError である。

手動レンジ

set_range(value=None, index=None, range_value=None) は、現在の測定モードに対する手動レンジを設定する。

value は物理量指定である。数値で指定した場合、単位は現在の測定モードの基本単位である。電圧系は V、電流系は A、抵抗系は Ohm、静電容量は F である。

dmm.set_mode("voltage_dc")
dmm.set_range(value=5.0)
dmm.set_range(value="500 mV")
dmm.set_range(value="500mV")

index は SCPI RANGE 離散番号を直接指定する。

dmm.set_range(index=3)

value、index、range_value は同時に指定しない。range_value は旧 API 互換用であり、value と同じ意味で扱う。

内部測定速度

set_integration_speed(speed) は SCPI RATE を設定する。

指定値は以下である。

F
M
S

小文字を渡した場合も大文字化して扱う。これ以外の値は ValueError である。

integration_speed は測定器内部の測定速度である。連続測定のサンプル間隔ではない。連続測定のサンプル間隔は set_continue_interval() で設定する。

単発測定

meas(wait=None) は現在設定で 1 回 MEAS1? を読む。

meas() の前に set_mode() が必要である。

結果は get_result() で再取得できる。

{
    "type": "single",
    "mode": "voltage_dc",
    "range_value": 10,
    "auto_range": False,
    "integration_speed": "F",
    "value": 1.234,
    "host_time_start": 1710000000.0,
    "host_time_end": 1710000000.02,
    "read_elapsed": 0.02,
}

continuous 測定

meas_continue(wait=None) は現在設定で連続測定を行う。

meas_continue() の前に set_continue_duration() または set_continue_count() の少なくとも一方を設定する必要がある。両方が None の場合は ValueError である。

set_continue_interval(interval) の interval は 0 以上でなければならない。0 の場合は可能な限り連続して読む。

set_continue_duration(duration) の duration は None または正の値である。

set_continue_count(count) の count は None または正の整数である。

use_process=True では開始成功時に {"job_id": ...} を返し、結果は result_store["result"] に保存される。

連続測定結果は以下の形式である。

{
    "type": "continuous",
    "job_id": "...",
    "ok": True,
    "mode": "voltage_dc",
    "range_value": 10,
    "auto_range": False,
    "integration_speed": "F",
    "continue_interval": 0.1,
    "continue_duration": 10.0,
    "continue_count": None,
    "stats": {
        "count": 100,
        "minimum": 1.23,
        "maximum": 1.25,
        "average": 1.24,
        "stdev_population": 0.01
    },
    "started_at": 1710000000.0,
    "finished_at": 1710000010.0,
    "samples": [
        {
            "index": 0,
            "value": 1.234,
            "host_time_start": 1710000000.0,
            "host_time_end": 1710000000.02,
            "read_elapsed": 0.02,
            "t_rel_start": 0.0,
            "t_rel_end": 0.02
        }
    ]
}

use_process=False の direct 実装では、連続測定結果に stats は付与されず、count が付与される。

結果取得

get_result(clear=False) は直近の単発測定または連続測定結果を返す。

clear=True の場合、取得後に保存結果を消す。

get_continuous_result() と get_statistics_result() は現在の API ではない。結果取得は get_result() に統一する。

FastAPI 透過 API

server_fastapi/spec.py で公開される透過 API は以下である。

get_state
is_running
idn
set_mode
set_range
set_auto_range
set_integration_speed
set_continue_interval
set_continue_duration
set_continue_count
meas
meas_continue
get_result
wait_until_done

object_name はすべて xdm1000 であり、HTTP method は post である。