手把手教你用 MicroPython 玩转幻尔串口舵机,代码+教程全公开

原文链接:

FreakStudio的博客

摘要

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 并行计算

一文搞懂 CM3 单片机调试原理

肝了半个月,嵌入式技术栈大汇总出炉

电子计算机类比赛的"武林秘籍"

一个MicroPython的开源项目集锦:awesome-micropython,包含各个方面的Micropython工具库

Avnet ZUBoard 1CG开发板---深度学习新选择

工程师不要迷信开源代码,还要注重基本功

什么?配色个性化的电机驱动模块?!!

什么?XIAO主控新出三款扩展板!

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_WRITESERVO_MOVE_TIME_READ 是与舵机位置控制相关的指令及其参数格式。
  • SERVO_ID_WRITESERVO_ID_READ 是与舵机ID相关的读写指令。

这些常量帮助类在进行通信时,能确保发送正确的指令和正确解析返回的数据。

READ_COMMANDS 集合定义了所有读取命令的编号,这些命令对应舵机的数据读取请求,例如,读取舵机的实时电压、角度、温度等信息。

这个集合便于在 receive_command() 方法中判断接收到的数据是否为期望的读取命令。

串口舵机类的核心方法为:

  • 构建数据包方法 build_packet :该方法用于构建舵机控制的指令包,指令包由以下部分组成:
    • 帧头:固定为 0x55, 0x55
    • 舵机ID:唯一标识每个舵机
    • 数据长度:包括指令和参数
    • 指令编号:具体的控制指令
    • 参数:控制指令的参数
    • 校验和:用于校验数据包的完整性
  • 发送指令方法 send_command :该方法构建指令包并通过 UART 发送给舵机,它调用了build_packet()来构造数据包,
    并通过self.uart.write()发送数据。
  • 接收指令方法 receive_commandreceive_command() 方法用于接收来自舵机的反馈数据,此方法的工作过程如下:
    1. 命令验证:确认接收到的是读取命令,而不是其他类型的命令。
    2. 数据检查:检查数据的帧头是否正确,命令编号是否匹配,数据长度是否符合预期。
    3. 校验和验证:验证接收到的数据包的校验和是否正确,确保数据未被篡改。
    4. 数据解析:根据返回的数据长度,解析并返回舵机的状态或数据(例如电压、角度等)。
    5. 如果数据包无效(如校验和错误、数据长度不符等),该方法将返回空列表。

SerialServo 类的设计通过封装舵机控制指令和数据包的构建逻辑,简化了舵机通信过程,核心思路是通过统一的数据包格式和校验机制确保指令的正确传输,

结合 UART 通信接口实现与舵机的高效交互。类内指令常量和参数处理使得操作更加清晰易懂,

同时通过校验和和数据长度的验证确保数据的完整性和可靠性。

3.如何使用

3.1 安装依赖

在运行示例程序之前,确保你的环境中安装了machinetime等模块。你可以通过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,然后解压文件。

  1. 将该程序文件保存为 serial_servo.py
  2. 确保使用的主控板通过舵机驱动扩展板已连接好舵机和串口,接线供电无异常。
  3. 在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 联系开发者。

相关推荐
go54631584653 小时前
本地部署 GitHub 上的 Python 人脸识别项目
开发语言·python·github
tekin4 小时前
基于 Python 开发在线多人游戏服务器案例解析
服务器·python·游戏·在线多人游戏服务器
让学习成为一种生活方式5 小时前
libGL.so.1: cannot open shared object file: No such file or directory-linux022
linux·开发语言·python
楼台的春风6 小时前
【图像的读写与基本操作】
图像处理·人工智能·深度学习·opencv·算法·计算机视觉·嵌入式
java1234_小锋6 小时前
一周学会Flask3 Python Web开发-Jinja2模板继承和include标签使用
python·flask·flask3
图书馆钉子户6 小时前
from flask_session import Session 为什么是Session(app)这么用?
python·flask·mybatis
一只蜗牛儿6 小时前
Sherpa-ONNX:说话人识别与语音识别自动开启(VAD)+ Python API 完整指南
人工智能·python·语音识别
结衣结衣.6 小时前
【OpenCV】入门教学
图像处理·人工智能·python·opencv
辰阳星宇6 小时前
203、【数组】NLP分词实现(Python)
开发语言·python