原文链接:
摘要
MicroPython串口舵机库,支持幻尔科技全系列舵机,支持mpremote工具一键导入,28条指令全测试。
往期推荐:
全网最适合入门的面向对象编程教程:00 面向对象设计方法导论
全网最适合入门的面向对象编程教程:01 面向对象编程的基本概念
全网最适合入门的面向对象编程教程:02 类和对象的 Python 实现-使用 Python 创建类
全网最适合入门的面向对象编程教程:03 类和对象的 Python 实现-为自定义类添加属性
全网最适合入门的面向对象编程教程:04 类和对象的Python实现-为自定义类添加方法
全网最适合入门的面向对象编程教程:05 类和对象的Python实现-PyCharm代码标签
全网最适合入门的面向对象编程教程:06 类和对象的Python实现-自定义类的数据封装
全网最适合入门的面向对象编程教程:07 类和对象的Python实现-类型注解
全网最适合入门的面向对象编程教程:08 类和对象的Python实现-@property装饰器
全网最适合入门的面向对象编程教程:09 类和对象的Python实现-类之间的关系
全网最适合入门的面向对象编程教程:10 类和对象的Python实现-类的继承和里氏替换原则
全网最适合入门的面向对象编程教程:11 类和对象的Python实现-子类调用父类方法
全网最适合入门的面向对象编程教程:12 类和对象的Python实现-Python使用logging模块输出程序运行日志
全网最适合入门的面向对象编程教程:13 类和对象的Python实现-可视化阅读代码神器Sourcetrail的安装使用
全网最适合入门的面向对象编程教程:全网最适合入门的面向对象编程教程:14 类和对象的Python实现-类的静态方法和类方法
全网最适合入门的面向对象编程教程:15 类和对象的 Python 实现-__slots__魔法方法
全网最适合入门的面向对象编程教程:16 类和对象的Python实现-多态、方法重写与开闭原则
全网最适合入门的面向对象编程教程:17 类和对象的Python实现-鸭子类型与"file-like object"
全网最适合入门的面向对象编程教程:18 类和对象的Python实现-多重继承与PyQtGraph串口数据绘制曲线图
全网最适合入门的面向对象编程教程:19 类和对象的 Python 实现-使用 PyCharm 自动生成文件注释和函数注释
全网最适合入门的面向对象编程教程:20 类和对象的Python实现-组合关系的实现与CSV文件保存
全网最适合入门的面向对象编程教程:21 类和对象的Python实现-多文件的组织:模块module和包package
全网最适合入门的面向对象编程教程:22 类和对象的Python实现-异常和语法错误
全网最适合入门的面向对象编程教程:23 类和对象的Python实现-抛出异常
全网最适合入门的面向对象编程教程:24 类和对象的Python实现-异常的捕获与处理
全网最适合入门的面向对象编程教程:25 类和对象的Python实现-Python判断输入数据类型
全网最适合入门的面向对象编程教程:26 类和对象的Python实现-上下文管理器和with语句
全网最适合入门的面向对象编程教程:27 类和对象的Python实现-Python中异常层级与自定义异常类的实现
全网最适合入门的面向对象编程教程:28 类和对象的Python实现-Python编程原则、哲学和规范大汇总
全网最适合入门的面向对象编程教程:29 类和对象的Python实现-断言与防御性编程和help函数的使用
全网最适合入门的面向对象编程教程:30 Python的内置数据类型-object根类
全网最适合入门的面向对象编程教程:31 Python的内置数据类型-对象Object和类型Type
全网最适合入门的面向对象编程教程:32 Python的内置数据类型-类Class和实例Instance
全网最适合入门的面向对象编程教程:33 Python的内置数据类型-对象Object和类型Type的关系
全网最适合入门的面向对象编程教程:34 Python的内置数据类型-Python常用复合数据类型:元组和命名元组
全网最适合入门的面向对象编程教程:35 Python的内置数据类型-文档字符串和__doc__属性
全网最适合入门的面向对象编程教程:36 Python的内置数据类型-字典
全网最适合入门的面向对象编程教程:37 Python常用复合数据类型-列表和列表推导式
全网最适合入门的面向对象编程教程:38 Python常用复合数据类型-使用列表实现堆栈、队列和双端队列
全网最适合入门的面向对象编程教程:39 Python常用复合数据类型-集合
全网最适合入门的面向对象编程教程:40 Python常用复合数据类型-枚举和enum模块的使用
全网最适合入门的面向对象编程教程:41 Python常用复合数据类型-队列(FIFO、LIFO、优先级队列、双端队列和环形队列)
全网最适合入门的面向对象编程教程:42 Python常用复合数据类型-collections容器数据类型
全网最适合入门的面向对象编程教程:43 Python常用复合数据类型-扩展内置数据类型
全网最适合入门的面向对象编程教程:44 Python内置函数与魔法方法-重写内置类型的魔法方法
全网最适合入门的面向对象编程教程:45 Python实现常见数据结构-链表、树、哈希表、图和堆
全网最适合入门的面向对象编程教程:46 Python函数方法与接口-函数与事件驱动框架
全网最适合入门的面向对象编程教程:47 Python函数方法与接口-回调函数Callback
全网最适合入门的面向对象编程教程:48 Python函数方法与接口-位置参数、默认参数、可变参数和关键字参数
全网最适合入门的面向对象编程教程:49 Python函数方法与接口-函数与方法的区别和lamda匿名函数
全网最适合入门的面向对象编程教程:50 Python函数方法与接口-接口和抽象基类
全网最适合入门的面向对象编程教程:51 Python函数方法与接口-使用Zope实现接口
全网最适合入门的面向对象编程教程:52 Python函数方法与接口-Protocol协议与接口
全网最适合入门的面向对象编程教程:53 Python字符串与序列化-字符串与字符编码
全网最适合入门的面向对象编程教程:54 Python字符串与序列化-字符串格式化与format方法
全网最适合入门的面向对象编程教程:55 Python字符串与序列化-字节序列类型和可变字节字符串
全网最适合入门的面向对象编程教程:56 Python字符串与序列化-正则表达式和re模块应用
全网最适合入门的面向对象编程教程:57 Python字符串与序列化-序列化与反序列化
全网最适合入门的面向对象编程教程:58 Python字符串与序列化-序列化Web对象的定义与实现
全网最适合入门的面向对象编程教程:59 Python并行与并发-并行与并发和线程与进程
更多精彩内容可看:
给你的 Python 加加速:一文速通 Python 并行计算
一个MicroPython的开源项目集锦:awesome-micropython,包含各个方面的Micropython工具库
Avnet ZUBoard 1CG开发板---深度学习新选择
1.原先库存在的问题

这里,我们看厂家提供的MicroPython库中代码:
实际上,并没有很好的实现功能解耦和充分利用Python面向对象的特性。
可以看到,多个方法中间存在重复的收发逻辑:
同时,UART 波特率(115200)、超时时间(50ms)等硬编码在代码中,而非可配置:
并且,无 API 文档和示例代码,不利于用户快速上手,也缺乏必要的入口参数校验机制,如判断舵机ID、角度范围、速度范围是否合理:
因此,我决定自己写一个MicroPython版本的幻尔科技串口舵机库。
仓库地址为:
Freak嵌入式-MicroPython串口舵机库
我也将其发布到了PyPi上(虽然不适合发布到上面,只是方便后期讲解Python发布第三方库):
Freak嵌入式-MicroPython串口舵机库-PyPi
2.serial_servo库介绍
2.1 简介与主要特性
通过串口舵机库,用户可以控制多个舵机的角度、速度等参数,实现高效、灵活的舵机控制,程序中使用了串口通讯与舵机进行数据交互,提供了完整的控制命令和反馈解析功能。
推荐大家使用我们的串口舵机扩展板,感谢支持:
Freak嵌入式-多米诺系列-串口舵机驱动板
主要特性包括:
- 使用UART串口与舵机通信,支持多舵机控制。
- 支持舵机的角度、速度、工作模式等多种设置。
- 支持舵机温度、电压、角度等实时读取。
- 校验和机制确保数据传输的完整性,幻尔科技串口舵机28条指令全部实现,并且封装为类。
- 完整的异常捕获机制,对入口参数进行详细检查。
- 注释完善,所有方法和类均提供了类型注解。
该类封装了舵机控制相关的所有功能,包括生成和发送控制指令、接收舵机反馈、读取舵机状态等。
__init__(self, uart: UART) -> None
:初始化串口舵机控制类。calculate_checksum(data: list[int]) -> int
:计算校验和,确保数据的完整性和正确性。build_packet(servo_id: int, cmd: int, params: list[int]) -> bytearray
:构建舵机控制指令包。send_command(servo_id: int, cmd: int, params: list[int] = []) -> None
:发送控制指令到指定舵机。receive_command(expected_cmd: int, expected_data_len: int) -> list
:接收并解析舵机返回的指令数据包。move_servo_immediate(servo_id: int, angle: float, time_ms: int) -> None
:立即控制舵机转动到指定角度。get_servo_move_immediate(servo_id: int) -> tuple
:获取舵机的预设角度和时间。move_servo_with_time_delay(servo_id: int, angle: float, time_ms: int) -> None
:控制舵机延迟转动到指定角度。get_servo_move_with_time_delay(servo_id: int) -> tuple
:获取舵机的延迟转动角度和时间。start_servo(servo_id: int) -> None
:启动舵机的转动。stop_servo(servo_id: int) -> None
:立即停止舵机转动并停在当前角度位置。set_servo_id(servo_id: int, new_id: int) -> None
:设置舵机的新 ID 值。get_servo_id(servo_id: int) -> int
:获取舵机的 ID。set_servo_angle_offset(servo_id: int, angle: float, save_to_memory: bool = False) -> None
:根据角度值调整舵机的偏差。get_servo_angle_offset(servo_id: int) -> float
:获取舵机的偏差角度。set_servo_angle_range(servo_id: int, min_angle: float, max_angle: float) -> None
:设置舵机的最小和最大角度限制。get_servo_angle_range(servo_id: int) -> tuple
:获取舵机的角度限位。set_servo_vin_range(servo_id: int, min_vin: float, max_vin: float) -> None
:设置舵机的最小和最大输入电压限制。get_servo_vin_range(servo_id: int) -> tuple
:获取舵机的电压限制值。set_servo_temp_range(servo_id: int, max_temp: int) -> None
:设置舵机的最高温度限制。get_servo_temp_range(servo_id: int) -> int
:获取舵机的内部最高温度限制值。read_servo_temp(servo_id: int) -> int
:获取舵机的实时温度。read_servo_voltage(servo_id: int) -> float
:获取舵机的实时输入电压。read_servo_pos(servo_id: int) -> float
:获取舵机的实时角度位置。set_servo_mode_and_speed(servo_id: int, mode: int, speed: int) -> None
:设置舵机的工作模式和电机转速。get_servo_mode_and_speed(servo_id: int) -> tuple
:获取舵机的工作模式和转动速度。set_servo_motor_load(servo_id: int, unload: bool) -> None
:设置舵机的电机是否卸载掉电。get_servo_motor_load_status(servo_id: int) -> bool
:获取舵机电机是否装载或卸载。set_servo_led(servo_id: int, led_on: bool) -> None
:设置舵机的 LED 灯的亮灭状态。get_servo_led(servo_id: int) -> bool
:获取舵机 LED 的亮灭状态。set_servo_led_alarm(servo_id: int, alarm_code: int) -> None
:设置舵机 LED 闪烁报警对应的故障值。get_servo_led_alarm(servo_id: int) -> int
:获取舵机 LED 故障报警状态。
2.2 核心方法介绍
该类的核心是通过 UART(串口通信)与舵机通信。类中的常量定义包括了多种控制命令和舵机相关的设置。这些常量包括了指令的编号、参数长度和返回数据长度。例如:
SERVO_MOVE_TIME_WRITE
和SERVO_MOVE_TIME_READ
是与舵机位置控制相关的指令及其参数格式。SERVO_ID_WRITE
和SERVO_ID_READ
是与舵机ID相关的读写指令。
这些常量帮助类在进行通信时,能确保发送正确的指令和正确解析返回的数据。
READ_COMMANDS
集合定义了所有读取命令的编号,这些命令对应舵机的数据读取请求,例如,读取舵机的实时电压、角度、温度等信息。
这个集合便于在 receive_command()
方法中判断接收到的数据是否为期望的读取命令。
串口舵机类的核心方法为:
- 构建数据包方法
build_packet
:该方法用于构建舵机控制的指令包,指令包由以下部分组成:- 帧头:固定为 0x55, 0x55
- 舵机ID:唯一标识每个舵机
- 数据长度:包括指令和参数
- 指令编号:具体的控制指令
- 参数:控制指令的参数
- 校验和:用于校验数据包的完整性

- 发送指令方法
send_command
:该方法构建指令包并通过UART
发送给舵机,它调用了build_packet()
来构造数据包,
并通过self.uart.write()
发送数据。

- 接收指令方法
receive_command
:receive_command()
方法用于接收来自舵机的反馈数据,此方法的工作过程如下:- 命令验证:确认接收到的是读取命令,而不是其他类型的命令。
- 数据检查:检查数据的帧头是否正确,命令编号是否匹配,数据长度是否符合预期。
- 校验和验证:验证接收到的数据包的校验和是否正确,确保数据未被篡改。
- 数据解析:根据返回的数据长度,解析并返回舵机的状态或数据(例如电压、角度等)。
- 如果数据包无效(如校验和错误、数据长度不符等),该方法将返回空列表。

SerialServo 类的设计通过封装舵机控制指令和数据包的构建逻辑,简化了舵机通信过程,核心思路是通过统一的数据包格式和校验机制确保指令的正确传输,
结合 UART 通信接口实现与舵机的高效交互。类内指令常量和参数处理使得操作更加清晰易懂,
同时通过校验和和数据长度的验证确保数据的完整性和可靠性。
3.如何使用
3.1 安装依赖
在运行示例程序之前,确保你的环境中安装了machine
和time
等模块。你可以通过MicroPython的包管理器安装依赖。
您可以使用如下语句和 mpremote
工具安装该库:
bash
mpremote mip install https://github.com/leezisheng/freakstudio-micropython-libraries/tree/main/serial_servo
或者(推荐):
bash
mpremote mip install github:leezisheng/freakstudio-micropython-libraries/serial_servo
安装进行中会显示:
bash
(base) PS D:\lee\windows terminal\terminal-1.17.11461.0> mpremote mip install github:leezisheng/freakstudio-micropython-libraries/serial_servo
Install github:leezisheng/freakstudio-micropython-libraries/serial_servo
Installing github:leezisheng/freakstudio-micropython-libraries/serial_servo/package.json to /lib
Installing: /lib/serial_servo/__init__.py
Installing: /lib/serial_servo/serial_servo.py
Installing micropython-machine (latest) from https://micropython.org/pi/v2 to /lib
Package may be partially installed
mpremote: Package not found: https://micropython.org/pi/v2/package/6/micropython-machine/latest.json
安装完成后,通过mpremote工具,连接你的开发板,如果成功安装,会显示如下信息:
bash
(base) PS D:\lee\windows terminal\terminal-1.17.11461.0> mpremote connect COM8
Connected to MicroPython at COM8
Use Ctrl-] or Ctrl-x to exit this shell
>>> import os
>>> os.listdir()
['lib']
>>> from serial_servo import SerialServo
>>>
如果通过 mpremote
安装失败,您可以选择手动安装库,即选择 Download ZIP,然后解压文件。
- 将该程序文件保存为
serial_servo.py
。 - 确保使用的主控板通过舵机驱动扩展板已连接好舵机和串口,接线供电无异常。
- 在MicroPython环境中,通过
import serial_servo
导入该模块。
3.2 使用示例
在使用前,我们需要注意:
- 硬件连接:确保舵机的电源和控制线正确连接
- 串口通信参数设置:串口通信的波特率必须与舵机的波特率匹配,为115200,数据位为8,无校验位,停止位为1。
- 响应等待:每次发送指令后,最好等待舵机响应,避免指令丢失。
你可以像下面这样,去调用串口舵机控制类中方法控制舵机或者读取其状态:
python
from machine import Pin, UART
from serial_servo import SerialServo
# 配置UART串口
uart = UART(1, baudrate=115200, tx=Pin(4), rx=Pin(5))
# 初始化串口舵机控制类
servo = SerialServo(uart)
# 控制舵机转到指定角度
servo.move_servo_immediate(servo_id=1, angle=90.0, time_ms=1000)
# 获取舵机的角度和时间设置
angle, time = servo.get_servo_move_immediate(servo_id=1)
print(f"Servo ID: 1, Angle: {angle}, Time: {time}")
下面是实测的相关图片:
如有任何问题或需要帮助,请通过 10696531183@qq.com 联系开发者。
