上位制御層 (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 である。