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

通过PySerial读取Arduino串口数据时遭遇COM端口权限拒绝问题

解决PySerial访问COM端口被拒绝的问题

咱们先一步步拆解你遇到的PermissionError(13, 'Access is denied')问题,从最常见的原因到代码里的致命错误逐一解决:

一、最直接的原因:串口被其他进程占用

  • 先彻底关闭Arduino IDE(不仅仅是关闭串口监视器,有时候IDE后台进程还会占用端口)
  • 检查有没有其他串口工具(比如PuTTY、串口调试助手)正在使用COM3,全部关闭后再运行脚本
  • 如果之前脚本崩溃过,打开任务管理器杀掉残留的Python.exe进程——崩溃的进程可能没释放串口资源

二、Python脚本的核心错误:循环内重复打开串口

看你的代码,在while True循环里每次都执行ser_data = serial.Serial("COM3",9600),这会导致每次循环都尝试重新打开串口,但前一次打开的串口没有关闭,系统会判定端口一直被占用,直接触发权限拒绝。

修正后的完整Python代码(关键改动已标注)

import cv2
import sys
import serial
from serial import SerialException

if __name__ == '__main__' :
    # Set up tracker.
    tracker = cv2.TrackerMIL_create()
    # Read video
    video = cv2.VideoCapture(0)
    # Exit if video not opened.
    if not video.isOpened():
        print ("Could not open video")
        sys.exit()
    # Read first frame.
    ok, frame = video.read()
    if not ok:
        print ('Cannot read video file')
        sys.exit()
    # Define ROI
    bbox = cv2.selectROI(frame, False)
    # Initialize tracker with first frame and bounding box
    ok = tracker.init(frame, bbox)

    # --- 关键改动1:串口初始化移到循环外,只打开一次 ---
    ser_data = None
    try:
        ser_data = serial.Serial("COM3", 9600, timeout=1)  # 添加timeout避免阻塞
        ser_data.readline()  # 读取第一行可能的初始化垃圾数据
    except SerialException as e:
        print(f"无法打开串口: {e}")
        sys.exit()

    while True:
        # Read a new frame
        ok, frame = video.read()
        if not ok:
            break
        # Start timer for FPS calculation
        timer = cv2.getTickCount()
        # Update tracker
        ok, bbox = tracker.update(frame)
        # Calculate Frames per second (FPS)
        fps = cv2.getTickFrequency() / (cv2.getTickCount() - timer);
        # Calculate Distance from Raspi
        focallength = 480.20
        knownwidth = 30.480 # Almost the same size as A4 paper
        # --- 改动2:处理bbox宽度为0的情况,避免除以0报错 ---
        RaspiDist = 0
        if bbox[2] != 0:
            RaspiDist = (knownwidth*focallength)/bbox[2]

        # --- 关键改动3:正确读取串口数据,而非直接使用serial对象 ---
        ir_distance = 0
        if ser_data.in_waiting > 0:
            try:
                line = ser_data.readline().decode('utf-8').strip()
                if line.isdigit():
                    ir_distance = int(line)
            except ValueError:
                print(f"读取到无效数据: {line}")

        # Draw bounding box
        if ok:
            # Tracking success
            p1 = (int(bbox[0]), int(bbox[1]))
            p2 = (int(bbox[0] + bbox[2]), int(bbox[1] + bbox[3]))
            cv2.rectangle(frame, p1, p2, (0,255,255), 2, 1)
        else :
            # Tracking failure
            cv2.putText(frame, "Tracking failure detected", (100,80), cv2.FONT_HERSHEY_SIMPLEX, 0.75,(0,0,255),2)
        # Display tracker type on frame
        cv2.putText(frame, "MIL Tracker", (0,20), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0,255,255), 2);
        # Display FPS on frame
        cv2.putText(frame, "FPS : " + str(int(fps)), (0,50), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0,255,255), 2);
        # Display Distance on frame
        cv2.putText(frame, "RaspiDistance : " + str(int(RaspiDist))+" cms", (0,75), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0,255,255), 2);
        cv2.putText(frame, "IRDistance : " + str(ir_distance) + " cms", (0,100), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0,255,255), 2);
        # Display result
        cv2.imshow("Tracking", frame)
        # Exit if ESC pressed
        k = cv2.waitKey(1) & 0xff
        if k == 27:
            break  # 新增ESC退出逻辑,确保程序能正常释放资源

    # --- 关键改动4:程序结束时主动关闭串口和摄像头 ---
    if ser_data is not None and ser_data.is_open:
        ser_data.close()
    video.release()
    # Destroy all windows
    cv2.destroyAllWindows()

三、其他备选解决方案

  • Windows权限问题:右键点击Python IDE或终端,选择「以管理员身份运行」后再执行脚本
  • 串口驱动故障:在设备管理器里找到Arduino的串口设备,右键卸载驱动后重新安装官方驱动
  • 端口编号冲突:如果COM3一直异常,可以在设备管理器里修改Arduino的串口编号(比如改成COM4),再同步修改Python脚本里的端口号

验证步骤

  1. 关闭所有可能占用串口的程序(Arduino IDE、串口工具)
  2. 用管理员身份运行修正后的Python脚本
  3. 若仍报错,检查设备管理器里Arduino的串口编号是否正确,有没有黄色感叹号(驱动问题)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:26:00