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,           # ポート名 ("COM3", "/dev/ttyUSB0" など)
    baudrate: int = 115200,
    *,
    timeout: float = 1.0,   # 受信タイムアウト(秒)
    encoding: str = "utf-8",
)

with ブロックで接続・切断を管理します。with の外で使うと RuntimeError になります。

# ポートの情報を確認
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, baudrate=115200, *, timeout=1.0, encoding="utf-8") インスタンス生成
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-0.1.0.tar.gz (12.8 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-0.1.0-py3-none-any.whl (6.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: kikaiken_pyserial-0.1.0.tar.gz
  • Upload date:
  • Size: 12.8 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-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ffba97130f8a7c37921c5c91db446654f8e1b4f7dbd0ba9819c4ace6a3270a53
MD5 f8972e228be7e1f17b019d70f057a036
BLAKE2b-256 5b57945e9d065afedf821393c65410112a851c6674abf8f58d8367de7fc9c17b

See more details on using hashes here.

File details

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

File metadata

  • Download URL: kikaiken_pyserial-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 6.9 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-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6d3c4f9ed3f5cf15d30c16b250c32468100f1723ab651e6e4b13ab5f02780e48
MD5 e7f8eca5f8438c731182be66c548bd5f
BLAKE2b-256 c93983598cd87b54ebb6c71ce6994df72e253de9eca8c99e992810850c540358

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