Skip to main content

シリアル通信をシンプルにするライブラリ

Project description

kikaiken-pyserial

シリアル通信をシンプルにするライブラリです。pyserial のラッパーとして動作します。

インストール

uv add kikaiken-pyserial

基本的な使い方

SerialPortwith ブロックで開き、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

kikaiken_pyserial-1.0.0.tar.gz (16.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kikaiken_pyserial-1.0.0-py3-none-any.whl (7.2 kB view details)

Uploaded Python 3

File details

Details for the file kikaiken_pyserial-1.0.0.tar.gz.

File metadata

  • Download URL: kikaiken_pyserial-1.0.0.tar.gz
  • Upload date:
  • Size: 16.7 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

Hashes for kikaiken_pyserial-1.0.0.tar.gz
Algorithm Hash digest
SHA256 e7acc087c3a617faae93daf8c93466644bceed018ea46aefc94f766c0c07d5b0
MD5 f1ded3e36797dac7a709686ccd416f2c
BLAKE2b-256 76481955ec18f5a64adc96f8cdc575a260d3c3b938970f268ab78d6784e62dc0

See more details on using hashes here.

File details

Details for the file kikaiken_pyserial-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: kikaiken_pyserial-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 7.2 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

Hashes for kikaiken_pyserial-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 dbf77e56549d900396a8ffb5d84f26d97364d59d573f7a937723544277bec0d8
MD5 625d695ee1b076484456983f1c6acee5
BLAKE2b-256 1ae36a9799994562780db5fb2ddc0e2f47003d73a7b950e4fa6ea1c69725bb20

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page