Skip to main content

spi-proto:SPI 电机控制库的 Python 包

把 C++ 工程编译出的 libspi_proto.so(aarch64 / Jetson)封装为可直接 pip install 的 Python 库。包内自带共享库,安装后无需再手动管理 .so 路径,所有硬件命令、协议造帧/解析、CRC、浮点转换都有对应的 Python API。

对应 C 接口见 ../c_api.h,协议细节见 ../通讯协议.md

平台要求

  • Linux aarch64(Jetson 等),因为 libspi_proto.so 是 aarch64 ELF;
  • Python 3.8+;
  • 硬件命令需要 /dev/spidev* 节点(纯协议接口 / selftest 不需要硬件)。

在其他架构上安装会正常完成,但导入时会抛出明确的架构错误提示。

安装

方式一:从源码目录直接安装

cd python
pip install .

方式二:从 PyPI 直接安装(已发布)

spi-proto 0.1.1 已发布到公开 PyPI,目标机器联网后直接:

pip install spi-proto

PyPI 项目页:https://pypi.org/project/spi-proto/

方式三:构建 wheel 后安装(分发其他 Jetson / 离线)

cd python
bash build_wheel.sh
pip install dist/spi_proto-0.1.1-py3-none-manylinux_2_24_aarch64.whl

build_wheel.sh 会同时生成 sdist 和 manylinux wheel。PyPI 不接受裸的 linux_aarch64 标签,因此 wheel 使用 manylinux_2_24_aarch64 (auditwheel 依据 .so 实际引用的 glibc / libstdc++ 符号版本算出, 要求目标系统 glibc >= 2.24,即 Ubuntu 18.04+ / 主流 JetPack)。

方式四:直接安装 sdist

pip install python/dist/spi_proto-0.1.1.tar.gz

验证安装

python3 -c "import spi_proto; print(spi_proto.__version__)"
spi-demo selftest        # 无硬件自检,全部 [PASS] 即正常

快速开始

安装后自带 spi-demo 命令行(也可 python -m spi_proto.demo,源码目录 下还可以直接 python3 demo_python.py):

spi-demo selftest                    # 不访问硬件,自检协议
spi-demo init --motor-count 16 --mode 1 --motor-mode 2 2
                                     # 0x05 设置模式并初始化(必须先调用)
spi-demo reconnect --motor-count 16 --mode 1   # 只更新本地记录,不下发
spi-demo enable                      # 0x01 使能(默认全选)
spi-demo enable --motor-id 1 2       # 只使能电机 1、2
spi-demo disable --motor-id 3        # 只失能电机 3
spi-demo zero                        # 0x04 设置零位(默认全选)
spi-demo zero --motor-id 3 --motor-id 7
spi-demo pos --motor 1 0.5 0 0       # 控制电机 1:pos=0.5, vel=0, tor=0
spi-demo pos --motor 1 0.5 0 0 --motor-gain 1 50 1.5   # MIT 模式 Kp/Kd
spi-demo pos --motor 1 0.5 0 0 --motor 9 -0.2 0 0 --loop 10
spi-demo test                        # 0x0F 回环测试(调试)

硬件命令默认打开 /dev/spidev0.0(不存在时自动选择第一个 /dev/spidev*),20 MHz,SPI 模式 0,可用 --device / --speed 覆盖。 只有 init / setmode 会下发 0x05 设置模式帧;其他命令(enable/disable/ stop/zero/pos/test)只做本地记录(reconnect,不下发 SPI),不会在 0x03 读状态时顺带设置模式。需要真正设置模式时请先运行 init 或 setmode。

Python API 示例

硬件控制

from spi_proto import SpiClient

with SpiClient() as client:            # 默认 /dev/spidev0.0, 20MHz, mode 0
    fb = client.init(1, 16)            # 0x05 设置模式并初始化(必须先调用)
    fb = client.enable()               # 整机使能,返回 Feedback
    fb = client.enable_motor(1)        # 只使能电机 1
    fb = client.disable()              # 整机失能
    fb = client.set_zero()             # 全选标零
    fb = client.set_zero_motor(3)      # 只标零电机 3
    fb = client.set_mode([1, 2] + [1] * 30)   # 按电机分别设置(每电机可不同)
    fb = client.position([0.5] * 16, [0.0] * 16, [0.0] * 16)  # 全 16 路
    fb = client.position_ids([1, 9], [0.5, -0.2], [0.0, 0.0], [0.0, 0.0])
    fb = client.position_ids([1], [0.5], [0.0], [0.1], [50.0], [1.5])  # MIT
    fb = client.stop()                 # 0x03 读电机状态

    print(fb.valid, fb.crc_ok, fb.cmd)          # True True 0x82
    for m in fb.motors:
        print(m.id, m.pos, m.vel, m.tor)        # 位置 rad / 速度 rad/s / 力矩 Nm

    client.reconnect(1, 16)            # 只更新本地模式/总数,不下发 SPI

init(modes, motor_count) 必须在其他指令之前调用:SDK 记录每个电机的模式 (0=MIT、1=位置、2=速度,每电机可不同)与总电机数并下发 0x05;运动控制 按每个电机记录的模式打包(位置/速度 float32;MIT 用 kp/kd、tor 作为 t_ff), id 或位图超过总电机数会报错。所有硬件方法成功返回 Feedback,失败抛 SpiError(可 client.last_error() 查看 C 层错误信息)。

纯协议(不访问硬件)

from spi_proto import (
    crc16, frame_enable, frame_position_ids, parse_feedback,
)

frame = frame_enable(0xFFFFFFFF)       # bytes,长度 255
frame = frame_position_ids(1, [1], [0.5], [0.0], [0.0])  # 第 1 个参数是 modes

assert crc16(b"123456789") == 0x4B37

fb = parse_feedback(rx_bytes)          # rx_bytes 必须是 255 字节

API 参考

常量

常量 说明
MOTOR_NUM 16 全 16 路控制时的电机数
MODE_MOTOR_NUM 32 设置模式帧的槽位数
MOTOR_ID_MAX 32 位图类命令的电机 ID 上限
FRAME_LEN 255 帧长度
MASK_ALL 0xFFFFFFFF 使能/失能/标零/读状态全选位图
MODE_MIT / MODE_POSITION / MODE_VELOCITY 0 / 1 / 2 set_mode 取值

SpiClient

构造参数:device=None, speed_hz=20_000_000, mode=0, bits_per_word=8。 支持 with 语句,close() / closed

方法 命令 说明
init(modes, motor_count) 0x05 设置模式并初始化 SDK(必须先调用)
reconnect(modes, motor_count) - 只更新本地模式/总数,不下发 SPI
enable(on=True) 0x01 使能,默认全选
disable() 0x00 失能,默认全选
enable_mask(mask) / disable_mask(mask) 0x01/0x00 按 32 位位图
enable_motor(id) / disable_motor(id) 0x01/0x00 单电机(1..32)
stop() / stop_mask(mask) 0x03 读电机状态
set_zero(mask=0xFFFFFFFF) / set_zero_motor(id) 0x04 标零
set_mode(modes) 0x05 int 或 32 字节序列(改模式,同步本地记录)
loopback(byte=0x5A) 0x0F 回环测试
position(pos, vel, tor, kp, kd) 0x02 槽位 1..总电机数(最多 16),按模式打包
position_ids(ids, pos, vel, tor, kp, kd) 0x02 变长控制,ids 1..总电机数
last_error() - C 层最近错误信息

position / position_ids 的参数按每个电机记录的模式取用:位置模式用 pos+vel(float32)、速度模式仅 vel、MIT 模式用 pos/vel/kp/kd/tor(作为 t_ff) 定点打包,未用到的参数丢弃。

协议函数

crc16(data)float_to_uint(x, min, max, bits)uint_to_float(x, min, max, bits)parse_feedback(frame),以及返回 bytes(255 字节)的帧构造:frame_enable / frame_disable / frame_stop / frame_set_zero / frame_set_mode / frame_test / frame_position / frame_position_ids

数据结构

  • Feedbackvalidcrc_okcmdraw(bytes)、motors
  • MotorFeedbackidstateposveltormos_tempcoil_temp

协议要点

  • 使能/失能/读状态/标零:32 位位图写入 frame[4..7](小端), bit(id-1)=1 对应电机 id(1..32);
  • 设置模式(0x05):32 字节,每电机一字节(0=MIT、1=位置、2=速度);
  • 运动控制(0x02 / 回传 0x82)为变长帧,长度字节 = 数据长度(9×N); 每个电机的块按其记录的模式打包(位置/速度 float32;MIT 定点 kp/kd/t_ff);
  • CRC-16/MODBUS 覆盖“长度+命令+数据”,紧随数据存放。

注意事项

  • SPI 设备节点可能需要 root 或 dialout 组权限,报 open 失败 时先检查 ls -l /dev/spidev* 与权限;
  • libspi_proto.so 是 aarch64 的,wheel 只能装在 Linux aarch64 且 glibc >= 2.24 的系统上(Ubuntu 18.04+ / 主流 JetPack);
  • 公开 PyPI 上的包是公开的,任何人均可下载查看;
  • MCU 0x0F 回环存在固件特性:回传帧携带上一拍状态、回环字节写在 CRC 计算之后。spi-demo test 已兼容(连发两拍 + 按 raw[5]=0 复核 CRC), 普通命令(stop 等)回传帧 CRC 正常;
  • 纯协议接口和 selftest 不需要硬件,可在任意 aarch64 机器上跑。

打包与分发

bash build_wheel.sh

产物在 dist/

  • spi_proto-0.1.1-py3-none-manylinux_2_24_aarch64.whl:把 .so 打进 wheel,可直接上传 PyPI 或拷贝到 Jetson 上 pip install
  • spi_proto-0.1.1.tar.gz:sdist,pip install <tar.gz> 或上传 PyPI。

发布到 PyPI(需要 API token):

TWINE_USERNAME=__token__ TWINE_PASSWORD=<你的token> \
  python3 -m twine upload dist/*

包内模块:spi_proto(API 入口)、spi_proto.client(SpiClient)、 spi_proto.protocol(造帧/解析/CRC)、spi_proto.selftestspi_proto.demo(CLI demo)。

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

spi_proto-0.1.1.tar.gz (47.2 kB view details)

Uploaded Source

Built Distribution

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

spi_proto-0.1.1-py3-none-manylinux_2_24_aarch64.whl (45.3 kB view details)

Uploaded Python 3manylinux: glibc 2.24+ ARM64

File details

Details for the file spi_proto-0.1.1.tar.gz.

File metadata

  • Download URL: spi_proto-0.1.1.tar.gz
  • Upload date:
  • Size: 47.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.10

File hashes

Hashes for spi_proto-0.1.1.tar.gz
Algorithm Hash digest
SHA256 a6c4da788661ccbedd1cb4e3fdfdedc2f709cd50ee880b38a517ba147ec83bde
MD5 0155e72867b57fcd12d03fcd2dfa518d
BLAKE2b-256 c38c918c647ad1bb54aebfc78f7bea557af20ddf070ee795d57b245376bddb21

See more details on using hashes here.

File details

Details for the file spi_proto-0.1.1-py3-none-manylinux_2_24_aarch64.whl.

File metadata

File hashes

Hashes for spi_proto-0.1.1-py3-none-manylinux_2_24_aarch64.whl
Algorithm Hash digest
SHA256 a0d38107fa4be1ca5e60ae761680eecec573d617080910d5438b82a6883b57fa
MD5 75e1b3ede7e8999f99bff3613482bbe8
BLAKE2b-256 122053242bbd831607655ae64709278b3de5601addb1c5d37a1bd84d654e15fb

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page