机器人串口连接 函数

99ANYc3cd6 机器人 2

串口通信的核心是 pyserial 库,这是 Python 中最常用、最强大的串口操作库。

机器人串口连接 函数-第1张图片-广州国自机器人
(图片来源网络,侵删)

核心函数详解 (基于 pyserial)

pyserial 库中,所有操作都围绕 serial.Serial 这个类对象展开。

初始化与打开串口 (serial.Serial)

这是第一步,用于创建一个串口对象,并设置好所有必要的参数。

import serial
# --- 构造函数 ---
# ser = serial.Serial(port, baudrate, bytesize, parity, stopbits, timeout, xonxoff, rtscts, dsrdtr)
# 参数说明:
# port:         串口设备名,例如在 Windows 上是 'COM3',在 Linux 上是 '/dev/ttyUSB0' 或 '/dev/ttyACM0'
# baudrate:     波特率,必须与机器人端设置的波特率一致,9600, 115200
# bytesize:     数据位,通常是 8 (serial.EIGHTBITS)
# parity:       校验位,通常是 'N' (无校验 serial.PARITY_NONE)
# stopbits:     停止位,通常是 1 (serial.STOPBITS_ONE)
# timeout:      超时时间(秒),非常重要!
#               - None: 阻塞模式,read() 会一直等待直到读到数据
#               - 0:    非阻塞模式,read() 立即返回,读到多少是多少
#               - x.x:  超时模式,read() 最多等待 x.x 秒
# xonxoff:      是否启用软件流控 (默认 False)
# rtscts:       是否启用硬件流控 (默认 False)
# dsrdtr:       是否启用硬件流控 (默认 False)
# --- 常用简化写法 ---
ser = serial.Serial(
    port='/dev/ttyUSB0',
    baudrate=115200,
    timeout=1  # 设置超时为1秒,防止程序卡死
)
# --- 其他常用方法 ---
ser.baudrate = 9600  # 动态修改波特率
ser.port = 'COM4'    # 动态修改串口
ser.open()           # 手动打开串口(如果构造函数中 auto_open=False)
ser.is_open         # 检查串口是否已打开,返回 True 或 False

写数据 (write)

向机器人发送指令。

# ser.write(data)
# 参数说明:
# data: 必须是 bytes 类型,不能是字符串
# --- 示例 ---
# 发送字符串 "START",需要先编码成 bytes
command = "START\n"  # 很多机器人协议以换行符作为命令结束
ser.write(command.encode('utf-8')) # 或者 command.encode('ascii')
# 发送一个字节数据
ser.write(b'\x01') # 发送十六进制 0x01

读数据 (read, readline, readlines)

从机器人读取返回的数据或状态。

机器人串口连接 函数-第2张图片-广州国自机器人
(图片来源网络,侵删)
# --- read(size=1) ---
# 读取指定大小的字节,如果超时时间内没读到足够字节,则返回已读到的部分。
# size: 要读取的字节数
data = ser.read(10)  # 读取10个字节,如果1秒内没读到10个,则返回已读到的
# --- readline() ---
# 读取一行,以换行符 '\n' 或 '\r' 为结束标志,非常适用于读取文本协议。
# 如果超时时间内没读到换行符,则返回已读到的内容。
response = ser.readline() # 读取一行,返回 bytes 类型
print(response.decode('utf-8').strip()) # 解码并去除首尾空白字符
# --- readlines() ---
# 读取多行,直到超时,返回一个包含多行 bytes 的列表。
# 注意:如果数据流很慢,这个函数可能会阻塞很长时间,一般不推荐使用。
# lines = ser.readlines()

关闭串口 (close)

在程序结束或不再需要通信时,必须关闭串口以释放资源。

ser.close()

完整示例:控制一个假设的机器人

假设我们的机器人通过串口接收指令,格式为 命令+参数\nMOVE 100\n 表示向前移动100cm,机器人返回 OK\n 表示成功。

import serial
import time
def connect_to_robot(port, baudrate=115200, timeout=1):
    """
    连接到机器人串口
    :param port: 串口号
    :param baudrate: 波特率
    :param timeout: 超时时间
    :return: serial.Serial 对象 或 None
    """
    try:
        ser = serial.Serial(
            port=port,
            baudrate=baudrate,
            timeout=timeout
        )
        print(f"成功连接到串口 {port}")
        return ser
    except serial.SerialException as e:
        print(f"连接串口 {port} 失败: {e}")
        return None
def send_command(ser, command):
    """
    发送命令并等待响应
    :param ser: 串口对象
    :param command: 要发送的命令字符串
    """
    if not ser or not ser.is_open:
        print("串口未打开,无法发送命令。")
        return
    # 发送命令
    ser.write(command.encode('utf-8'))
    print(f"已发送命令: {command.strip()}")
    # 等待并读取响应
    response = ser.readline()
    if response:
        print(f"机器人响应: {response.decode('utf-8').strip()}")
    else:
        print("超时,未收到机器人响应。")
def main():
    # --- 配置参数 ---
    # !!! 请根据你的实际情况修改这些参数 !!!
    ROBOT_PORT = '/dev/ttyUSB0'  # Linux 或 macOS
    # ROBOT_PORT = 'COM3'         # Windows
    ROBOT_BAUDRATE = 115200
    # 1. 连接机器人
    robot_serial = connect_to_robot(ROBOT_PORT, ROBOT_BAUDRATE)
    if robot_serial:
        try:
            # 给机器人一点时间启动和准备
            time.sleep(2)
            # 2. 发送一系列命令
            send_command(robot_serial, "START\n") # 启动机器人
            time.sleep(0.5)
            send_command(robot_serial, "MOVE 100\n") # 移动100cm
            time.sleep(0.5)
            send_command(robot_serial, "TURN 90\n") # 转向90度
            time.sleep(0.5)
            send_command(robot_serial, "STOP\n")    # 停止
        except KeyboardInterrupt:
            print("\n用户中断程序,正在关闭串口...")
        finally:
            # 3. 关闭串口 (非常重要!)
            robot_serial.close()
            print("串口已关闭。")
if __name__ == '__main__':
    main()

进阶主题与最佳实践

使用 with 语句 (推荐)

with 语句可以确保串口在使用完毕后被自动关闭,即使发生错误也不会忘记关闭,是更安全、更 Pythonic 的写法。

import serial
# with 语句会自动处理 ser.close()
with serial.Serial('/dev/ttyUSB0', 115200, timeout=1) as ser:
    ser.write(b'HELLO\n')
    response = ser.readline()
    print(f"Response: {response.decode('utf-8').strip()}")
# ser 已经被自动关闭了

多线程/异步串口通信

机器人的数据接收往往是持续不断的(不断上报传感器数据),而发送命令是事件驱动的,如果使用单线程,在 readline() 等待数据时,程序就无法发送新的命令。

解决方法是使用多线程:

  • 主线程:负责发送命令和用户交互。
  • 数据读取线程:在一个循环中持续读取串口数据,并放入队列或进行其他处理。
import threading
import queue
import serial
# 创建一个队列用于线程间通信
data_queue = queue.Queue()
def read_from_port(ser):
    """一个持续从串口读取数据的线程函数"""
    while True:
        if ser.in_waiting > 0:
            line = ser.readline()
            data_queue.put(line) # 将读到的数据放入队列
            print(f"收到数据: {line.decode('utf-8').strip()}")
        time.sleep(0.01) # 短暂休眠,避免CPU占用过高
# --- 主程序 ---
ser = serial.Serial('/dev/ttyUSB0', 115200, timeout=1)
# 启动数据读取线程
read_thread = threading.Thread(target=read_from_port, args=(ser,), daemon=True)
read_thread.start()
# 主线程可以继续执行其他任务,比如发送命令
ser.write(b'START\n')
time.sleep(2)
ser.write(b'READ_SENSOR\n')
# 让主线程保持运行,以便观察子线程的输出
try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    print("程序退出")
    ser.close()

跨平台串口名

不同操作系统的串口命名规则不同:

  • Windows: COM1, COM2, ...
  • Linux: /dev/ttyS0, /dev/ttyUSB0, /dev/ttyACM0, ...
  • macOS: /dev/tty.serialname

在编写跨平台程序时,需要根据操作系统选择正确的串口名,可以使用 platform 模块来判断。

import platform
import serial
def find_robot_port():
    system = platform.system()
    if system == 'Windows':
        # 可以尝试常见的 COM 端口
        for i in range(1, 10):
            port = f'COM{i}'
            try:
                ser = serial.Serial(port, 115200, timeout=0.1)
                ser.close()
                return port
            except:
                continue
    elif system == 'Linux':
        # 可以尝试常见的 USB 串口设备
        for port in ['/dev/ttyUSB0', '/dev/ttyACM0']:
            try:
                ser = serial.Serial(port, 115200, timeout=0.1)
                ser.close()
                return port
            except:
                continue
    # ... 其他系统处理
    return None
robot_port = find_robot_port()
if robot_port:
    print(f"找到机器人串口: {robot_port}")
else:
    print("未找到可用的机器人串口。")

希望这份详细的指南能帮助你实现机器人的串口连接!

标签: 机器人串口通信函数 Python机器人串口连接函数 STM32机器人串口控制函数

抱歉,评论功能暂时关闭!