シリアル通信をシンプルにするライブラリ
Project description
kikaiken-pyserial
シリアル通信をシンプルにするライブラリです。pyserial のラッパーとして動作します。
インストール
uv add kikaiken-pyserial
基本的な使い方
SerialPort を with ブロックで開き、send() / read_line() を呼ぶだけです。
from kikaiken_pyserial import SerialPort
with SerialPort("COM3", baudrate=115200) as ser:
ser.send("Hello\r\n")
response = ser.read_line()
print(response)
ポートの確認
接続中のシリアルポートを一覧表示します。どのポート名を指定すればいいかわからないときに使います。
import kikaiken_pyserial
ports = kikaiken_pyserial.list_ports()
print(ports)
# => ["COM3", "COM8"] (Windows)
# => ["/dev/ttyUSB0", "/dev/ttyACM0"] (Linux)
SerialPort
接続
SerialPort(
port: str | None = None, # ポート名 ("COM3", "/dev/ttyUSB0" など)。省略すると STM32 を自動検出
baudrate: int = 115200,
*,
timeout: float = 1.0, # 受信タイムアウト(秒)
encoding: str = "utf-8",
)
with ブロックで接続・切断を管理します。with の外で使うと RuntimeError になります。
port を省略すると、接続中の STM32 デバイスを USB VID (0x0483) で自動検出します。見つからない場合や複数見つかった場合は RuntimeError になります。
# STM32 を自動検出して接続
with SerialPort() as ser:
print(ser.port) # => "COM3" など(自動検出されたポート名)
# ポートを明示して接続
with SerialPort("COM3", baudrate=9600) as ser:
print(ser.port) # => "COM3"
print(ser.baudrate) # => 9600
テキスト送信 — send(data: str)
文字列をそのまま送信します。改行コードはユーザーが明示します。
with SerialPort("COM3") as ser:
ser.send("ping\r\n") # \r\n を明示
ser.send("speed:100\n") # \n だけでもOK
ser.send("raw message") # 改行なしも送れる
テキスト受信 — read_line() -> str
\n が来るまで待ち、末尾の \r\n / \n を取り除いた文字列を返します。
with SerialPort("COM3") as ser:
line = ser.read_line()
print(line) # => "OK" (デバイスが "OK\r\n" を返した場合)
タイムアウト内に改行が届かない場合は TimeoutError を送出します。
with SerialPort("COM3", timeout=0.5) as ser:
try:
line = ser.read_line()
except TimeoutError:
print("応答がありませんでした")
バイナリ受信 — read_bytes(n: int) -> bytes
ちょうど n バイト受信して返します。タイムアウトまでに届かない場合は TimeoutError です。
with SerialPort("COM3") as ser:
header = ser.read_bytes(4) # 4バイトのヘッダを読む
print(header.hex()) # => "deadbeef"
BinaryProtocol — バイナリプロトコルの定義
マイコンとバイナリ形式で通信する場合は BinaryProtocol を使います。クラス変数にフィールドを定義すると、send_bytes() でそのままシリアルに送れます。
フィールドの型
| 型 | 説明 | 値の範囲 |
|---|---|---|
UInt(n) |
n ビット符号なし整数 | 0 〜 2ⁿ − 1 |
Int(n) |
n ビット符号あり整数 | −2ⁿ⁻¹ 〜 2ⁿ⁻¹ − 1 |
Bool() |
1 ビットのフラグ | True / False |
基本的な定義
from kikaiken_pyserial import BinaryProtocol, UInt, Int, Bool
class MotorCmd(BinaryProtocol):
speed = UInt(7) # 0〜127
direction = Bool() # True=正転 / False=逆転
# 合計 8 ビット = 1 バイト
フィールドの値はインスタンス化時にキーワード引数で渡します。 省略すると TypeError になります。
cmd = MotorCmd(speed=100, direction=True)
print(cmd) # => MotorCmd(speed=100, direction=True)
print(cmd.speed) # => 100
print(cmd.to_bytes().hex()) # => "c9"
# speed=100 → 0b1100100
# direction=1 → 0b1
# 結合(MSBファースト) → 0b11001001 = 0xc9
インスタンス化後にフィールドを書き換えようとすると AttributeError になります。
cmd.speed = 50 # AttributeError: 'MotorCmd.speed' はインスタンス化後に変更できません
send_bytes() で送信
with SerialPort("COM3") as ser:
ser.send_bytes(MotorCmd(speed=80, direction=False))
複数バイトのプロトコル
フィールドの合計が 8 ビットを超えると自動的に複数バイトになります。
class ServoCmd(BinaryProtocol):
servo_id = UInt(4) # 0〜15
angle = UInt(12) # 0〜4095
# 合計 16 ビット = 2 バイト
cmd = ServoCmd(servo_id=3, angle=2048)
print(cmd) # => ServoCmd(servo_id=3, angle=2048)
print(cmd.to_bytes().hex()) # => "3800"
# servo_id=3 → 0b0011
# angle=2048 → 0b100000000000
# 結合 → 0b0011_100000000000 = 0x3800
符号あり整数(Int)
class PositionCmd(BinaryProtocol):
x = Int(8) # -128〜127
y = Int(8) # -128〜127
# 合計 16 ビット = 2 バイト
cmd = PositionCmd(x=-30, y=50)
print(cmd.to_bytes().hex()) # => "e232"
パディング
合計ビット数が 8 の倍数でない場合、末尾(LSB 側)を自動的に 0 で埋めます。
class SensorCmd(BinaryProtocol):
mode = UInt(3) # 0〜7
enable = Bool() # True/False
# 合計 4 ビット → 4 ビットパディング → 1 バイト
cmd = SensorCmd(mode=5, enable=True)
print(cmd.to_bytes().hex()) # => "b0"
# mode=5 → 0b101、enable=1 → 0b1
# 結合(MSBファースト) + 4ビットパディング → 0b1011_0000 = 0xb0
kikaiken-pycontroller と組み合わせる
コントローラの入力をシリアルでマイコンに送る典型的な使い方です。
from pycontroller import Controller
from kikaiken_pyserial import BinaryProtocol, Int, SerialPort, UInt
class DriveCmd(BinaryProtocol):
left = Int(8) # 左モータ速度: -128〜127
right = Int(8) # 右モータ速度: -128〜127
# 合計 16 ビット = 2 バイト
with Controller(0) as ctrl, SerialPort("COM3") as ser:
while True:
state = ctrl.read()
# 左スティックの Y 軸(前後)と X 軸(左右)で差動駆動
forward = state.axes.axis1 # -1.0〜1.0
turn = state.axes.axis0 # -1.0〜1.0
ser.send_bytes(DriveCmd(
left=int((forward - turn) * 127),
right=int((forward + turn) * 127),
))
テキストで送りたい場合はこうなります。
from pycontroller import Controller
from kikaiken_pyserial import SerialPort
with Controller(0) as ctrl, SerialPort("COM3") as ser:
while True:
state = ctrl.read()
x = state.axes.axis0
y = state.axes.axis1
ser.send(f"X:{x:.3f},Y:{y:.3f}\r\n")
try:
ack = ser.read_line()
print("ACK:", ack)
except TimeoutError:
pass # 応答がない場合は無視して続行
API リファレンス
list_ports() -> list[str]
接続中のシリアルポートの名前一覧を返します。
SerialPort
| メソッド / プロパティ | 説明 |
|---|---|
SerialPort(port=None, baudrate=115200, *, timeout=1.0, encoding="utf-8") |
インスタンス生成。port 省略時は STM32 を自動検出 |
with SerialPort(...) as ser: |
接続・切断の管理 |
ser.send(data: str) |
テキスト送信 |
ser.send_bytes(data: BinaryProtocol) |
バイナリ送信 |
ser.read_line() -> str |
1 行受信(タイムアウトで TimeoutError) |
ser.read_bytes(n: int) -> bytes |
n バイト受信(タイムアウトで TimeoutError) |
ser.port |
ポート名 |
ser.baudrate |
ボーレート |
BinaryProtocol
| 要素 | 説明 |
|---|---|
UInt(n) |
n ビット符号なし整数フィールド |
Int(n) |
n ビット符号あり整数フィールド |
Bool() |
1 ビットフラグフィールド |
MyProtocol(field=value, ...) |
インスタンス生成。全フィールドの指定が必須 |
to_bytes() -> bytes |
フィールドの値をバイト列に変換(MSB ファースト) |
repr(cmd) |
MyProtocol(field=value, ...) 形式で内容を表示 |
フィールドは定義した順に MSB から詰められます。合計が 8 の倍数でない場合は末尾を 0 でパディングします。値が範囲外のとき ValueError、インスタンス化後に書き換えようとすると AttributeError を送出します。
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kikaiken_pyserial-1.0.1.tar.gz.
File metadata
- Download URL: kikaiken_pyserial-1.0.1.tar.gz
- Upload date:
- Size: 19.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.11 {"installer":{"name":"uv","version":"0.11.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52f18383611f40a6bfb4ba9585b10d0180f6396f179212a5539147af8d8efc54
|
|
| MD5 |
7c38c943816952cb621b40acc0cc8cd7
|
|
| BLAKE2b-256 |
04434ccf44f1cb862c1f737dd850ef5c2c22e503992dd8361123d90604a51e00
|
File details
Details for the file kikaiken_pyserial-1.0.1-py3-none-any.whl.
File metadata
- Download URL: kikaiken_pyserial-1.0.1-py3-none-any.whl
- Upload date:
- Size: 10.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.11 {"installer":{"name":"uv","version":"0.11.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d54dc70b39e3ef7194d056837aaf38cfe99f4f01835c6880e9d71da010996b11
|
|
| MD5 |
eb5e59b874f50c9fbf80a2f8655e752b
|
|
| BLAKE2b-256 |
01412e8f3efb7b2cffef11581aa4ef87b98d0b02619563e2d1c80789ca5cf8d1
|