当前USB相机是用sdk访问,日志里显示必须是ttyACM0,我们插了两个会乱,怎么固定USB

cat /home/sunrise/Dev/SoundImg/build/diagnose/summary.txt

=== 运行参数 ===
project_root /home/sunrise/Dev/SoundImg
launcher /home/sunrise/Dev/SoundImg/scripts/run_private_runtime.sh
bin_name DesSoundImg
direct_mode 0
binary /home/sunrise/Dev/SoundImg/build/DesSoundImg
output_dir /home/sunrise/Dev/SoundImg/build/diagnose
run_seconds 120
target_usb 1bcf:28c4

=== 系统环境 ===
uname Linux ubuntu 6.1.83 #4 SMP PREEMPT Fri Dec 19 10:54:38 CST 2025 aarch64 aarch64 aarch64 GNU/Linux
user root
groups root
ulimit_core 0

=== USB与设备节点 ===
usb_detected yes
usb_line Bus 001 Device 006: ID 1bcf:28c4 Sunplus Innovation Technology Inc. Depstech webcam MIC
usb_node /dev/bus/usb/001/006
usb_perm crw-rw---- root:video
tty_nodes /dev/ttyACM0 /dev/ttyACM1
video_nodes /dev/video0 /dev/video1 /dev/video2 /dev/video3
tty_perm crw-rw---- 1 root dialout 166, 0 Mar 26 21:00 /dev/ttyACM0

=== 节点到硬件映射 ===
map_/dev/video0 vid:pid=04b4:f8f8 model=InfraredCamera serial=Infrared_InfraredCamera_0123456789.0123456789.0123456789
sys_/dev/video0 /devices/platform/soc/35000000.hsio_apb/35100000.usb3/35100000.usb/xhci-hcd.2.auto/usb1/1-1/1-1.4/1-1.4:1.0/video4linux/video0
map_/dev/video1 vid:pid=04b4:f8f8 model=InfraredCamera serial=Infrared_InfraredCamera_0123456789.0123456789.0123456789
sys_/dev/video1 /devices/platform/soc/35000000.hsio_apb/35100000.usb3/35100000.usb/xhci-hcd.2.auto/usb1/1-1/1-1.4/1-1.4:1.0/video4linux/video1
map_/dev/video2 vid:pid=1bcf:28c4 model=Depstech_webcam_MIC serial=RH-FAY-250612_Depstech_webcam_MIC_01.00.00
sys_/dev/video2 /devices/platform/soc/35000000.hsio_apb/35100000.usb3/35100000.usb/xhci-hcd.2.auto/usb1/1-1/1-1.2/1-1.2.4/1-1.2.4:1.0/video4linux/video2
map_/dev/video3 vid:pid=1bcf:28c4 model=Depstech_webcam_MIC serial=RH-FAY-250612_Depstech_webcam_MIC_01.00.00
sys_/dev/video3 /devices/platform/soc/35000000.hsio_apb/35100000.usb3/35100000.usb/xhci-hcd.2.auto/usb1/1-1/1-1.2/1-1.2.4/1-1.2.4:1.0/video4linux/video3
map_/dev/ttyACM0 vid:pid=04b4:f8f8 model=InfraredCamera serial_short=0123456789.0123456789.0123456789
sys_/dev/ttyACM0 /devices/platform/soc/35000000.hsio_apb/35100000.usb3/35100000.usb/xhci-hcd.2.auto/usb1/1-1/1-1.4/1-1.4:1.2/tty/ttyACM0
map_/dev/ttyACM1 vid:pid=0483:5740 model=DES_Acoustic_Imaging_Camera serial_short=3274387C3233
sys_/dev/ttyACM1 /devices/platform/soc/35000000.hsio_apb/35100000.usb3/35100000.usb/xhci-hcd.2.auto/usb1/1-1/1-1.2/1-1.2.3/1-1.2.3:1.0/tty/ttyACM1

=== USB拓扑 ===
lsusb_t /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M; |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 5000M;/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M; |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M; |__ Port 2: Dev 3, If 0, Class=Hub, Driver=hub/4p, 480M; |__ Port 3: Dev 5, If 1, Class=CDC Data, Driver=cdc_acm, 480M; |__ Port 3: Dev 5, If 0, Class=Communications, Driver=cdc_acm, 480M; |__ Port 4: Dev 6, If 0, Class=Video, Driver=uvcvideo, 480M; |__ Port 4: Dev 6, If 1, Class=Video, Driver=uvcvideo, 480M; |__ Port 4: Dev 4, If 0, Class=Video, Driver=uvcvideo, 480M; |__ Port 4: Dev 4, If 1, Class=Video, Driver=uvcvideo, 480M; |__ Port 4: Dev 4, If 2, Class=Communications, Driver=cdc_acm, 480M; |__ Port 4: Dev 4, If 3, Class=CDC Data, Driver=cdc_acm, 480M;

=== 驱动冲突检查 ===
lsmod_ftdi_sio
dmesg_ttyusb

=== 设备占用检查 ===
tty_in_use
video_in_use

=== 运行采样 ===
run_cmd timeout 120s /home/sunrise/Dev/SoundImg/scripts/run_private_runtime.sh DesSoundImg
run_log /home/sunrise/Dev/SoundImg/build/diagnose/run.log
dmesg_tail /home/sunrise/Dev/SoundImg/build/diagnose/dmesg_tail.log

=== 关键日志提取 ===
device_found Found 2 device(s). (发现 2 个设备)
start_fail Failed to start: Start failed: Module Response Timeout (-37)
ma_start [260326 210549.319859 5705.515] ma_start err:-37
trace_last none
segfault none
timeout37 Failed to start: Start failed: Module Response Timeout (-37)
close34 [260326 210549.320781 5705.516] micArrCloseTask:0xaaaacfb36740,1 err:-34

=== 诊断结论(初判) ===
diagnose_result MODULE_RESPONSE_TIMEOUT
next_action 排查串口占用/驱动冲突/多设备干扰;先仅保留1台设备复现

问题分析

从诊断日志看,问题很明确:

现状:

  • 系统有2个USB相机,分别映射到 /dev/ttyACM0 和 /dev/ttyACM1
  • SDK要求必须使用 ttyACM0,但设备节点是动态分配的,插拔顺序变化会导致映射错乱
  • 错误 Module Response Timeout (-37) 说明SDK访问了错误的设备

设备映射关系:

设备节点 VID:PID 型号
/dev/ttyACM0 04b4:f8f8 InfraredCamera
/dev/ttyACM1 0483:5740 DES_Acoustic_Imaging_Camera
/dev/video2-3 1bcf:28c4 Depstech webcam (目标设备)

解决方案:使用udev规则固定设备节点

步骤1:确认目标设备的序列号或USB路径

# 查看目标相机的详细信息(替换为你的设备路径)
udevadm info -a -n /dev/ttyACM0 | grep -E "ATTRS{idVendor}|ATTRS{idProduct}|ATTRS{serial}|ATTRS{devpath}"

步骤2:创建udev规则

# 创建规则文件
sudo vim /etc/udev/rules.d/99-usb-camera-fixed.rules

方案A:按序列号固定(推荐,最稳定)

# 假设目标相机序列号是 0123456789.0123456789.0123456789
SUBSYSTEM=="tty", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="f8f8", ATTRS{serial}=="0123456789.0123456789.0123456789", SYMLINK+="ttyCAMERA_FIXED", MODE="0666"

方案B:按USB端口路径固定(如果序列号不可用)

# 从你的日志看,目标设备在 1-1.4 端口
SUBSYSTEM=="tty", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="f8f8", ATTRS{devpath}=="1-1.4", SYMLINK+="ttyCAMERA_FIXED", MODE="0666"

步骤3:应用规则

# 重载udev规则
sudo udevadm control --reload-rules

# 触发规则(或重新插拔设备)
sudo udevadm trigger

# 验证
ls -l /dev/ttyCAMERA_FIXED

步骤4:修改SDK配置

将SDK配置中的设备路径从 /dev/ttyACM0 改为 /dev/ttyCAMERA_FIXED,这样无论插拔顺序如何,都会指向正确的设备。


临时验证方法

在修改配置前,可以先手动测试:

# 拔掉所有相机,只插目标相机
# 查看分配的节点
ls -l /dev/ttyACM*

# 或者临时创建软链接
sudo ln -sf /dev/ttyACM0 /dev/ttyCAMERA_FIXED

注意事项

  1. 权限问题:确保运行用户有访问权限(MODE="0666" 或加入 dialout 组)
  2. 多设备场景:如果两个相机型号相同,必须用序列号区分
  3. 重启生效:某些情况下需要重启才能完全生效

需要我帮你根据具体设备信息生成完整的udev规则吗?请提供:

  • 你要固定的目标相机的 VID:PID
  • 该相机的序列号(如果有)

你好,请教下多USB摄像头是怎么访问,详细的几条指令,我按飞书上的.ko也试了,不成功,也换了多个yuv,jpeg摄像头也没成功

多USB摄像头访问指南(RDK X5)

你好!多USB摄像头访问不成功,通常是设备节点分配混乱或权限/驱动问题。按下面步骤排查:


步骤1:确认摄像头被系统识别

# 查看USB设备列表
lsusb

# 查看视频设备节点
ls -l /dev/video*

# 查看串口设备节点(部分相机需要)
ls -l /dev/ttyACM*

预期输出示例:

/dev/video0
/dev/video1
/dev/video2
/dev/video3

步骤2:查看每个摄像头的详细信息

# 查看每个video节点的硬件信息
udevadm info -a -n /dev/video0 | grep -E "idVendor|idProduct|serial|devpath"
udevadm info -a -n /dev/video1 | grep -E "idVendor|idProduct|serial|devpath"

关键信息:

  • idVendor / idProduct:厂商和产品ID
  • serial:序列号(如果有,最稳定)
  • devpath:USB端口路径(如 1-1.4)

步骤3:创建udev规则固定设备节点(关键!)

多摄像头必须固定设备节点,否则插拔顺序变化会导致映射错乱。

# 创建规则文件
sudo vim /etc/udev/rules.d/99-usb-cameras.rules

示例规则(按序列号固定):

# 摄像头1 -> /dev/video_CAM1
SUBSYSTEM=="video4linux", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="f8f8", ATTRS{serial}=="0123456789", SYMLINK+="video_CAM1", MODE="0666"

# 摄像头2 -> /dev/video_CAM2
SUBSYSTEM=="video4linux", ATTRS{idVendor}=="1bcf", ATTRS{idProduct}=="28c4", ATTRS{serial}=="RH-FAY-250612", SYMLINK+="video_CAM2", MODE="0666"

如果没有序列号,用USB端口路径:

# 摄像头1 插在 1-1.4 端口
SUBSYSTEM=="video4linux", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="f8f8", ATTRS{devpath}=="1-1.4", SYMLINK+="video_CAM1", MODE="0666"

步骤4:应用规则并验证

# 重载udev规则
sudo udevadm control --reload-rules

# 触发规则
sudo udevadm trigger

# 验证软链接是否创建成功
ls -l /dev/video_CAM*

预期输出:

/dev/video_CAM1 -> video0
/dev/video_CAM2 -> video2

步骤5:测试摄像头访问

# 方法1:使用v4l2-ctl测试
v4l2-ctl -d /dev/video_CAM1 --list-formats-ext

# 方法2:使用ffmpeg抓取一帧
ffmpeg -i /dev/video_CAM1 -frames:v 1 /tmp/test1.jpg

# 方法3:使用ROS2测试(如果已安装)
ros2 run image_tools cam2image -i /dev/video_CAM1

步骤6:SDK/代码中使用固定路径

不要用 /dev/video0,要用 /dev/video_CAM1

# Python OpenCV示例
import cv2

cap1 = cv2.VideoCapture('/dev/video_CAM1')  # 固定路径
cap2 = cv2.VideoCapture('/dev/video_CAM2')

# 或者用索引(不推荐,容易乱)
# cap1 = cv2.VideoCapture(0)
# cap2 = cv2.VideoCapture(2)

常见问题排查

问题 排查命令 解决方案
摄像头不识别 dmesg | tail -50 检查USB供电/线材
权限不足 ls -l /dev/video* 加用户到 video 组或 MODE="0666"
节点错乱 udevadm info -a -n /dev/video0 用udev规则固定
格式不支持 v4l2-ctl -d /dev/video0 --list-formats-ext 尝试YUV/MJPEG格式
带宽不足 lsusb -t 分散到不同USB控制器

关于.ko驱动

如果你指的是内核模块,一般UVC摄像头不需要额外驱动。如果是特殊相机:

# 查看已加载的内核模块
lsmod | grep uvc

# 查看内核日志中相机相关信息
dmesg | grep -i "uvc\|camera\|video"

需要你提供的信息

如果以上步骤仍不成功,请提供:

  1. lsusb 输出(摄像头VID:PID)
  2. ls -l /dev/video* 输出
  3. 使用的SDK名称和版本
  4. 具体报错信息

这样我可以帮你更精准定位问题!

正常配置为2个摄像头使用的指令是

双USB摄像头配置完整指令清单(RDK X5)

按顺序执行以下命令即可完成双摄像头固定配置:


:one: 查看当前设备状态

# 查看USB设备
lsusb

# 查看视频节点
ls -l /dev/video*

# 查看串口节点(部分相机需要)
ls -l /dev/ttyACM*

:two: 获取每个摄像头的唯一标识

# 摄像头1信息
udevadm info -a -n /dev/video0 | grep -E "idVendor|idProduct|serial|devpath"

# 摄像头2信息
udevadm info -a -n /dev/video1 | grep -E "idVendor|idProduct|serial|devpath"

记录以下关键信息:

  • ATTRS{idVendor}:如 "04b4"
  • ATTRS{idProduct}:如 "f8f8"
  • ATTRS{serial}:如 "0123456789"(如果有)
  • ATTRS{devpath}:如 "1-1.4"(如果没有序列号就用这个)

:three: 创建udev规则文件

# 创建规则文件
sudo vim /etc/udev/rules.d/99-usb-cameras.rules

写入以下内容(根据你的实际信息修改):

# 方案A:有序列号(推荐)
SUBSYSTEM=="video4linux", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="f8f8", ATTRS{serial}=="序列号1", SYMLINK+="video_CAM1", MODE="0666"
SUBSYSTEM=="video4linux", ATTRS{idVendor}=="1bcf", ATTRS{idProduct}=="28c4", ATTRS{serial}=="序列号2", SYMLINK+="video_CAM2", MODE="0666"

# 方案B:无序列号,用USB端口路径
SUBSYSTEM=="video4linux", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="f8f8", ATTRS{devpath}=="1-1.4", SYMLINK+="video_CAM1", MODE="0666"
SUBSYSTEM=="video4linux", ATTRS{idVendor}=="1bcf", ATTRS{idProduct}=="28c4", ATTRS{devpath}=="1-1.2", SYMLINK+="video_CAM2", MODE="0666"

:warning: 注意:如果两个摄像头型号相同(VID:PID一样),必须用序列号或USB端口路径区分


:four: 应用规则

# 重载udev规则
sudo udevadm control --reload-rules

# 触发规则
sudo udevadm trigger

# 验证软链接
ls -l /dev/video_CAM*

预期输出:

/dev/video_CAM1 -> video0
/dev/video_CAM2 -> video2

:five: 测试摄像头

# 测试摄像头1
v4l2-ctl -d /dev/video_CAM1 --list-formats-ext

# 测试摄像头2
v4l2-ctl -d /dev/video_CAM2 --list-formats-ext

# 或抓取一帧测试
ffmpeg -i /dev/video_CAM1 -frames:v 1 /tmp/cam1.jpg
ffmpeg -i /dev/video_CAM2 -frames:v 1 /tmp/cam2.jpg

:six: 代码中使用固定路径

import cv2

# 使用固定路径(推荐)
cap1 = cv2.VideoCapture('/dev/video_CAM1')
cap2 = cv2.VideoCapture('/dev/video_CAM2')

# 检查是否打开成功
if not cap1.isOpened() or not cap2.isOpened():
    print("摄像头打开失败")

:clipboard: 完整命令速查表

步骤 命令 说明
查看设备 lsusb 确认摄像头被识别
查看节点 ls -l /dev/video* 查看分配的节点
查信息 udevadm info -a -n /dev/video0 获取VID/PID/序列号
创规则 sudo vim /etc/udev/rules.d/99-usb-cameras.rules 创建固定规则
重载 sudo udevadm control --reload-rules 重载规则
触发 sudo udevadm trigger 立即生效
验证 ls -l /dev/video_CAM* 确认软链接创建
测试 v4l2-ctl -d /dev/video_CAM1 --list-formats-ext 测试摄像头

:red_question_mark: 如果还不成功

请提供以下信息,我帮你进一步排查:

# 1. lsusb输出
lsusb

# 2. 视频节点列表
ls -l /dev/video*

# 3. 摄像头1详细信息
udevadm info -a -n /dev/video0 | head -50

# 4. 摄像头2详细信息
udevadm info -a -n /dev/video1 | head -50

# 5. 具体报错信息

把你执行到哪一步、遇到什么报错发出来,我帮你定位!

想请教的是如何配置多个摄像头,会提示VIDIOC_STREAMON failed: No space left on device,而不是区分是哪个

问题定位:USB 带宽不足导致 VIDIOC_STREAMON failed: No space left on device

这个错误不是设备节点分配问题,而是USB 带宽不足。RDK X5/X3 的 USB 口通过一个 USB 3.0 Hub 分出,默认情况下第一个摄像头会占满带宽,导致第二个摄像头无法启动。


:white_check_mark: 解决方案:限制 uvcvideo 带宽

步骤1:加载 uvcvideo 模块并限制带宽

# 卸载现有模块
sudo rmmod uvcvideo

# 重新加载并设置 quirks=128(限制带宽)
sudo modprobe uvcvideo quirks=128

参数说明:quirks=128 会限制每个 UVC 设备的带宽占用,允许多设备共享 USB 总线


步骤2:验证模块加载

# 查看模块是否加载成功
lsmod | grep uvcvideo

# 查看模块参数
cat /sys/module/uvcvideo/parameters/quirks

预期输出:128


步骤3:设置开机自动生效(可选)

# 创建模块配置文件
sudo vim /etc/modprobe.d/uvcvideo.conf

写入内容:

options uvcvideo quirks=128

步骤4:降低摄像头分辨率/格式(关键!)

即使设置了 quirks=128,如果两路摄像头总带宽超过 USB 3.0 上限,仍会报错。推荐配置:

分辨率 格式 帧率 单路带宽估算 双路是否可行
640x480 MJPEG 30fps ~15MB/s :white_check_mark: 可行
1280x720 MJPEG 30fps ~30MB/s :white_check_mark: 可行
1920x1080 MJPEG 30fps ~60MB/s :cross_mark: 超限
640x480 YUYV 30fps ~30MB/s :warning: 紧张

测试命令:

# 查看摄像头支持的格式
v4l2-ctl -d /dev/video0 --list-formats-ext

# 设置摄像头为 MJPEG 格式 720p
v4l2-ctl -d /dev/video0 --set-fmt-video=width=1280,height=720,pixelformat=MJPG

步骤5:代码中指定格式和分辨率

import cv2

cap1 = cv2.VideoCapture('/dev/video_CAM1')
cap2 = cv2.VideoCapture('/dev/video_CAM2')

# 强制设置格式和分辨率(关键!)
cap1.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))
cap1.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap1.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
cap1.set(cv2.CAP_PROP_FPS, 30)

cap2.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))
cap2.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap2.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
cap2.set(cv2.CAP_PROP_FPS, 30)

# 测试读取
ret1, frame1 = cap1.read()
ret2, frame2 = cap2.read()
print(f"Cam1: {ret1}, Cam2: {ret2}")

步骤6:验证带宽使用情况

# 查看 USB 拓扑和带宽分配
lsusb -t

# 查看内核日志中是否有带宽相关报错
dmesg | grep -i "uvc\|bandwidth\|usb"

:clipboard: 完整操作速查表

步骤 命令 说明
限制带宽 sudo rmmod uvcvideo && sudo modprobe uvcvideo quirks=128 必须执行
验证参数 cat /sys/module/uvcvideo/parameters/quirks 确认值为 128
开机生效 echo "options uvcvideo quirks=128" | sudo tee /etc/modprobe.d/uvcvideo.conf 可选
查看格式 v4l2-ctl -d /dev/video0 --list-formats-ext 确认为 MJPEG
设置格式 v4l2-ctl -d /dev/video0 --set-fmt-video=width=1280,height=720,pixelformat=MJPG 推荐 720p MJPEG
测试读取 Python OpenCV 代码 同时读取两路

:red_exclamation_mark: 注意事项

  1. 必须使用 MJPEG 格式:YUYV/NV12 等未压缩格式带宽占用太大
  2. 分辨率不要超过 720p:双路 1080p 必超限
  3. USB 口尽量分开:如果有多个 USB 控制器,分散连接
  4. MIPI + USB 组合:如果一个用 MIPI 接口,一个用 USB,不会有带宽冲突

:magnifying_glass_tilted_left: 如果仍然失败

请提供以下信息:

# 1. 当前 uvcvideo 参数
cat /sys/module/uvcvideo/parameters/quirks

# 2. 摄像头支持的格式
v4l2-ctl -d /dev/video0 --list-formats-ext
v4l2-ctl -d /dev/video1 --list-formats-ext

# 3. USB 拓扑
lsusb -t

# 4. 内核日志
dmesg | tail -100

把报错信息和以上输出发出来,我帮你进一步分析!


相关帖子参考: