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

Python连接Arduino初始化串口/dev/ttyACM0报设备占用错误求助

Python连接Arduino串口报[Errno 16]设备忙故障排查

故障现象

无法实现Python与Arduino的串口通信,每次尝试初始化连接时返回如下错误信息:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 322, in open
    self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
OSError: [Errno 16] Device or resource busy: '/dev/ttyACM0'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    ser1 = serial.Serial('/dev/ttyACM0', 9600)
  File "/usr/lib/python3/dist-packages/serial/serialutil.py", line 244, in __init__
    self.open()
  File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 325, in open
    raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg))
serial.serialutil.SerialException: [Errno 16] could not open port /dev/ttyACM0: [Errno 16] Device or resource busy: '/dev/ttyACM0'

报错指向代码行:

ser1 = serial.Serial('/dev/ttyACM0', 9600)

异常发生在串口初始化阶段,两端原始代码如下:

Python端原始代码

import serial
import time

s = serial.Serial('/dev/ttyACM0', 9600)
s.close()
s.open()
time.sleep(5)

s.write("test")
try:
    while True:
        response = s.readline()
        print (response)

except KeyboardInterrupt:
    s.close()

Arduino端原始代码

void setup() {
Serial.begin(9600);
Serial.println("running");
}

void loop() {

  if(Serial.available()){
    byte recieved = Serial.read();
    Serial.print("recieved:");
    Serial.println(recieved, DEC);
  }
}

故障原因

  1. 核心报错[Errno 16] Device or resource busy代表/dev/ttyACM0串口已经被其他进程占用,常见占用源包括:Arduino IDE自带的串口监视器、系统串口调试工具(minicom/gtkterm等)、Linux发行版默认预装的brltty盲文支持服务(该服务会自动抢占所有ttyACM类设备,是此类问题最高发诱因)。
  2. Python代码存在逻辑错误:serial.Serial()实例化时会默认自动打开串口,后续手动调用close()再open()属于冗余操作,若初始化阶段就因端口占用抛错,这两行代码根本不会执行。
  3. Python3下串口写入要求传入字节类型数据,原始代码直接传入字符串"test"会触发类型错误,哪怕端口占用问题解决也会运行失败。

解决步骤

  • 释放被占用的串口
    终端执行sudo fuser /dev/ttyACM0查询占用该端口的进程ID,执行kill <查询到的进程ID>终止占用进程即可。如果占用进程是brltty,直接执行sudo apt remove brltty卸载该服务即可永久解决抢占问题;如果是Arduino IDE开了串口监视器,直接关闭监视器窗口再运行脚本。
  • 修正Python端代码
    移除冗余的关开串口操作,给串口加超时参数避免读阻塞,写入数据时转成字节类型,修正后代码如下:
import serial
import time

# 实例化时自动建立串口连接,加timeout参数避免readline永久阻塞
s = serial.Serial('/dev/ttyACM0', 9600, timeout=1)
# Arduino每次串口连接会自动重启,等待2秒让设备完成初始化
time.sleep(2)

# 写入内容前加b转成字节类型
s.write(b"test")
try:
    while True:
        response = s.readline()
        if response:
            # 字节转字符串输出,去掉首尾空白符
            print(response.decode('utf-8').strip())
except KeyboardInterrupt:
    s.close()
  • 确认串口操作权限
    若释放端口后仍报错,执行sudo usermod -aG dialout <当前系统用户名>将当前用户加入串口操作权限组,执行完成后注销用户重新登录即可生效。

注:Arduino端代码不存在功能性问题,仅变量名recieved为拼写笔误,不影响正常通信。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 21:12:19