You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派与Arduino串口通信异常:舵机控制失败求助

解决树莓派与Arduino串口通信的设备识别及IO错误问题

问题概述

尝试通过树莓派串口发送指令,让Arduino控制舵机,但频繁出现ttyACM0/ttyACM1设备找不到或写入IO错误的问题,已尝试连接稳定化、换线、重启、更新Python、sudo运行等操作,问题依旧。

现有代码

Arduino 代码

#include <Servo.h>

Servo servodown;

void setup() {
  servodown.attach(8);
  Serial.begin(9600);
}

void loop() {
  if (Serial.available() > 0) {
    String receivedString = Serial.readStringUntil('\n');  
    int nr = receivedString.toInt();

    if (nr >= 0 && nr <= 360) {
      Serial.print("Drehe auf ");
      Serial.println(nr, DEC);
      servodown.write(nr/2);
    } else {
      Serial.println("Digga deine Zahl ist nicht gültig");
    }
  }
}

树莓派 Python 代码

import serial
import time

print("Programm startet...")
degrees = input("Gradzahl bitte!")
if __name__ == "__main__":
        ser = serial.Serial("/dev/ttyACM1", 9600, timeout=1)
        ser.reset_input_buffer()

        while True:
                ser.write(str(degrees).encode("utf-8"))
                line = ser.readline().decode("utf-8").rstrip()
                print(line)
                time.sleep(1)

出现的错误

错误1:IO写入失败

Traceback (most recent call last):
  File "main.py", line 12, in <module>
    ser.write(str(degrees).encode("utf-8"))
  File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 571, in write
    raise SerialException('write failed: {}'.format(e))
serial.serialutil.SerialException: write failed: [Errno 5] Input/output error

错误2:设备不存在

Traceback (most recent call last):
  File "main.py", line 8, in <module>
    ser = serial.Serial("/dev/ttyACM0", 9600, timeout=1)
  File "/usr/lib/python2.7/dist-packages/serial/serialutil.py", line 240, in __init__
    self.open()
  File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 268, in open
    raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg))
serial.serialutil.SerialException: [Errno 2] could not open port /dev/ttyACM0: [Errno 2] No such file or directory: '/dev/ttyACM0'

解决方案步骤

1. 确定正确的串口设备路径

  • 先断开Arduino,执行命令:ls /dev/ttyACM* /dev/ttyUSB*,记录输出(此时应该没有对应设备)
  • 连接Arduino,再次执行上述命令,新增的设备就是目标串口
  • 也可以用dmesg | grep tty查看系统识别到的串口日志,找到类似usb-acm的设备行,确认路径

2. 修复权限问题

  • 将当前用户加入dialout组,避免每次用sudo:
    sudo usermod -a -G dialout $USER
    
  • 注销并重新登录,让权限生效

3. 调整Python代码的串口初始化逻辑

  • 避免硬编码设备路径,添加设备存在性检查;同时确保发送的指令带换行符(匹配Arduino的readStringUntil('\n')读取逻辑):
    import serial
    import time
    import os
    
    def get_serial_port():
        # 自动检测ACM/USB串口
        ports = [f"/dev/{port}" for port in os.listdir("/dev") if port.startswith("ttyACM") or port.startswith("ttyUSB")]
        if ports:
            return ports[0]
        raise Exception("No Arduino serial port found")
    
    print("Programm startet...")
    if __name__ == "__main__":
        try:
            ser = serial.Serial(get_serial_port(), 9600, timeout=1)
            time.sleep(2)  # 给Arduino重启预留时间
            ser.reset_input_buffer()
    
            while True:
                degrees = input("Gradzahl bitte!")
                # 发送带换行符的指令
                ser.write((degrees + "\n").encode("utf-8"))
                line = ser.readline().decode("utf-8").rstrip()
                if line:
                    print(line)
                time.sleep(0.5)
        except Exception as e:
            print(f"Fehler: {e}")
    

4. 检查Arduino的串口冲突

  • 确保Arduino上传代码后,串口监视器已关闭,避免树莓派无法占用串口
  • 部分Arduino(如Uno)在串口连接时会自动重启,Python代码中加入time.sleep(2)等待重启完成

5. 排查硬件与驱动问题

  • 用lsusb检查是否识别到Arduino设备:lsusb | grep Arduino,如果没有,说明硬件或驱动有问题
  • 尝试更换USB端口,优先用树莓派的USB 2.0端口(避免USB 3.0的干扰)

额外提示

  • 原Arduino代码中nr/2的整数除法逻辑没问题,可将输入的0-360转换为舵机支持的0-180度范围
  • 可以用minicom工具测试串口通信是否正常,手动发送指令验证Arduino的响应:
    sudo minicom -b 9600 -D /dev/ttyACM0
    

内容的提问来源于stack exchange,提问作者Mats4411

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 20:00:37