开发板接USB摄像头选型

原创2026-09-17 10:40:51浏览8
8
Star

一、先给结论

如果你正准备给板子接一个 USB 摄像头,下面五条可以先用起来:

结论

一句话解释

只认 UVC 免驱

Linux 内核自带驱动,插上就有节点;不是免驱的别折腾

一颗摄像头会注册两个节点

能出画面的只有一个,判据是 Device Caps

格式优先选 MJPG

同为 720p:MJPG 跑 28.8 fps,YUYV 只有 9.0 fps

记得加 video 组

不加就 Permission denied,而且必须重新登录才生效

供电软件测不到

别指望用命令读母线电压,能看的只有过流告警和满载长稳

下面逐条说怎么验证。

二、第一步:系统认不认这颗摄像头

插上去先看三样东西:

lsusb | grep -i camera
v4l2-ctl --list-devices
ls -l /dev/video*

我这颗摄像头的实测输出:

Bus 001 Device 003: ID 0bda:5846 Realtek Semiconductor Corp. USB Camera

USB Camera: USB Camera (usb-0000:01:00.0-1.1):
        /dev/video4
        /dev/video5
        /dev/media0

能看到这些就说明它免驱。 v4l2-ctl --list-devices 能把节点列出来,意味着内核已经用 uvcvideo 把它接管了,不用装任何驱动。

再看它在 USB 通路上挂在哪:

lsusb -t

图 1:lsusb -t 的真实输出。摄像头挂在 Bus 001(480M,即 USB 2.0)下面的板载 4 口 Hub 上,而 Bus 002 那个 5000M 的 USB 3.0 控制器,当前一个设备都没有。

这里有个很常见的误会值得单独说:"我明明插在 USB 3.0 口上,为什么还是 480M?"

因为速率上限由设备决定,不由接口决定。看一眼设备自己的描述符就明白了:

cat /sys/bus/usb/devices/1-1.1/bcdUSB
cat /sys/bus/usb/devices/1-1.1/bMaxPower
2.00
500mA

bcdUSB = 2.00 的意思就是"我是 USB 2.0 设备"。这类摄像头插到 USB 3.0 口上也不会变成 5000M —— 那多出来的针脚它根本不用。

路径里的 1-1.1 是 USB 拓扑编号(Bus 1 → Hub 的第 1 口 → 设备的第 1 个接口),换 USB 口就会变。对着 lsusb -t 的树看即可,或者到 /sys/bus/usb/devices/ 下找带 idVendor 的那个目录。

把整台机器的视频节点摆开看,格局就清楚了:

图 2:这台机器上的 /dev/video* 全景。8 个节点里,6 个属于板载 MIPI CSI 接口,只有 2 个属于你插的 USB 摄像头。

为什么 USB 摄像头不是 video0? 因为节点号是按注册顺序发的,跟"插了几个设备"没关系。板载 CSI 通路先启动、先占号,USB 摄像头后到,于是拿到 4 和 5。所以永远不要用编号去猜用途 —— 更不要拿 video0 去开 USB 摄像头,那是板子自己的 MIPI 接口。

三、第二步:两个节点,哪个才是"看画面"的

/dev/video4 和 /dev/video5 来自同一颗摄像头。上一篇我写过"编号小的那个用来采集",但那是经验规律,不是判据 —— 遇到注册顺序不同的摄像头就会踩坑。

真正的判据在 Device Caps 里:

v4l2-ctl -d /dev/video4 --info | grep -A3 'Device Caps'
v4l2-ctl -d /dev/video5 --info | grep -A3 'Device Caps'

图 3:同一颗摄像头(序列号都是 202001010001)的两个节点。video4 的 Device Caps 里有 Video Capture*,它才出画面;video5 只剩* Metadata Capture*,连格式列表都是空的。*

再补一条命令交叉验证 —— 去看 video5 支持什么格式:

v4l2-ctl -d /dev/video5 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture

空的。 一个格式都没有,因为它根本不是取画面的节点。按 UVC 规范,摄像头可以额外注册一个 metadata 节点,用来输出每帧的元信息(时间戳、曝光参数等)。它顶着 /dev/videoN 的名字,但不产图像。

所以判断顺序是这样:

  1. v4l2-ctl --list-devices 找出属于这颗摄像头的所有节点

  2. 对每一个跑一遍 --info | grep -A3 'Device Caps'

  3. 有 Video Capture 的那个,才是采集节点

有的摄像头会注册 4 个节点,有的只注册 1 个。别看编号,看能力。

四、第三步:格式选错,帧率直接掉到三分之一

这是本篇最值得看的一张表:

v4l2-ctl -d /dev/video4 --list-formats-ext

图 4:摄像头的完整格式能力表(原样输出,未做整理)。MJPG 的六种分辨率全部 30fps;YUYV 只有 640×480 能到 25fps,其余都是 10fps。

同一颗摄像头,同样标着 720p,两种像素格式的帧率上限差了 3 倍:

  • MJPG 1280×720 → 30 fps

  • YUYV 1280×720 → 10 fps

原因在于这两种格式根本不是一回事:

  • MJPG:每帧就是一张 JPEG,相机内部先压缩再传 —— 数据量小,但主机要解码

  • YUYV:未压缩的裸像素,一帧固定 宽 × 高 × 2 字节 —— 数据量大,主机不用解码

720p 的 YUYV 一帧是 1280×720×2 = 1,800 KB,是 MJPG(约 70 KB)的 25 倍。USB 2.0 的可用带宽就那么多,于是帧率被硬压到 10 fps。

但"标称上限"不等于"你实际跑的"。 我把四种配置各跑了一遍固定帧数:

bash e-cam-bench.sh /dev/video4

图 5:四种格式的实测(脚本见文末)。用 date 取采集前后的时间戳,帧数 ÷ 耗时得到帧率。先后跑了两轮,同一配置的偏差都在 1% 以内。

把四个数字放一起:

格式

分辨率

实测帧率

单帧大小

等效带宽

MJPG

1280×720

28.8 fps

~70 KB

16.4 Mbps

MJPG

640×480

28.8 fps

~25 KB

5.9 Mbps

YUYV

1280×720

9.0 fps

1800 KB

132.8 Mbps

YUYV

640×480

22.5 fps

600 KB

110.4 Mbps

(MJPG 的带宽按实测文件字节数换算;YUYV 是未压缩流,按 宽×高×2 的理论值换算,两者是同一个量级的口径。)

三个结论:

  1. 同分辨率下,MJPG 比 YUYV 快 3 倍多,带宽只要它的 1/8。 除非摄像头不支持 MJPG,否则没有任何理由用 YUYV。

  2. MJPG 把分辨率降到 640×480,帧率一点不掉(还是 28.8),带宽再降到 1/2.8。 这就是多路扩展的第一招 —— 先降分辨率,而不是先怀疑摄像头或 USB 口。

  3. MJPG 720p 只吃掉 16.4 Mbps。 USB 2.0 理论 480 Mbps、实测可用大约 280 到 320 Mbps(协议开销),这颗摄像头只用了 5% 出头,带宽上其实很宽裕。

然后是我自己踩的一个坑,很值得说。 我第一轮测 MJPG 720p,数字很怪:帧率 22.5 fps、单帧 600 KB —— 那明明不是 720p 的数据量。查了半天才反应过来:v4l2-ctl 不指定格式时,沿用设备"上次生效"的格式,而那颗摄像头当时停在 YUYV 640×480 上,我测的其实是它。

所以采集之前,一定要显式设一遍、再确认一遍:

v4l2-ctl -d /dev/video4 --set-fmt-video=width=1280,height=720,pixelformat=MJPG
v4l2-ctl -d /dev/video4 --get-fmt-video
Format Video Capture:
        Width/Height      : 1280/720
        Pixel Format      : 'MJPG' (Motion-JPEG)

--get-fmt-video 输出里的 Pixel Format 那行,才是它真正会用的格式。

GStreamer 里同理。v4l2src 后面的 caps 协商不上时会静默换一个能用的格式,所以要么把 caps 写死,要么事后确认一遍 —— 不然你会在错误的帧率上优化半天。

五、一个小权限,不加就起不来

如果访问 /dev/video* 报 Permission denied:

sudo usermod -aG video $USER

要重新登录(或重启)才生效,因为用户的组关系在登录那一刻就定下来了。验证:

id
uid=1000(user) gid=1000(user) groups=1000(user),27(sudo),44(video)

看到 44(video) 就对了。这条看着琐碎,但不做的话后面整条 GStreamer 流水线都起不来,而且报错位置往往指向别处,容易查偏。

顺手还能看看镜头有哪些可调项:

v4l2-ctl -d /dev/video4 --list-ctrls

亮度、对比度、饱和、曝光、白平衡都能调。比如画面偏暗:

v4l2-ctl -d /dev/video4 --set-ctrl=brightness=160

六、供电:先说清楚"软件测不到什么"

这类文章一般会写"拿万用表量一下电压"。但我想先把软件能测到什么、测不到什么划清楚,免得你在错误的路上花时间。

cat /sys/class/hwmon/hwmon0/name
ls /sys/class/hwmon/hwmon*/in*_input /sys/class/hwmon/hwmon*/curr*_input
sfctemp
(无 in*_input / curr*_input —— 即读不到母线电压与电流)

图 6:这台机器上唯一的 hwmon 是温度传感器;regulator 下 26 路读到的全是 PMIC 的目标设定值;唯一一条供电硬信号,是开机 5.6 秒时的 over-current。

三个事实:

  1. hwmon 下只有一个温度传感器(sfctemp),没有任何电压 / 电流采样节点。想知道 5V 母线此刻是多少伏,软件层问不出来。

  2. /sys/class/regulator/*/microvolts 读到的不是实测值,而是 PMIC 的目标设定值。比如 vcc_3v3 报 3300000,意思是"这里配了 3.3V",不是"此刻真的是 3.3V"。而且那 26 路里根本没有 5V 母线 —— 5V 是直接进稳压器的,不在 PMIC 的可读范围内。

  3. 唯一能拿到的供电硬信号是过流告警 over-current:

dmesg | grep -i 'over-current'
[    5.594076] usb usb2-port2: over-current condition

开机 5.6 秒时,USB 3.0 控制器的 port2 报过一次过流。

这条告警说明什么? 说明整板的 5V 余量并不宽裕 —— USB 3.0 口在开机瞬间就触发过一次过流保护。之后连续运行 18 小时(含满载测试)没有再出现。

那摄像头这一路到底够不够? 有几个证据:

  • 摄像头自己申报的需求:bMaxPower = 500mA,也就是 ≤ 2.5 W

  • 满载实测:1280×720 @ 28.8 fps 连续采集 760 帧,零丢帧、零报错

  • 它挂在 USB 2.0 那一条通路上,而 USB 3.0 那一路空着,互不争抢

结论:这颗摄像头的供电是够的。

但整板要算总账。 与其拍脑袋说"够 / 不够",不如算一算:

部件

峰值功耗

数值来源

开发板本体

约 5 W(峰值更高)

板厂手册

USB 摄像头

≤ 2.5 W(500mA × 5V)

设备描述

M.2 NPU 卡

6.6 W

卡厂手册

加起来峰值接近 15 W,除以 5V 就是 3 A。所以板厂标的"5V/3A"是底线而不是"推荐配置" —— 建议按 5V/4A 备电源,把余量留出来。供电不足的典型症状是:设备枚举随机失败、lspci 时有时无、跑一会儿就掉。

还有一条实用建议:以后要接多路摄像头时,别把供电压力全压在板上。用带独立供电的 USB Hub(有源 Hub),让摄像头吃自己的电源,开发板只管数据。这比换一个更大的电源更便宜,也更稳。

七、一张清单

挑摄像头时看这 5 条:

  1. 确认是 UVC 免驱 —— 免驱就意味着 Linux 插上就能用

  2. 看 --list-formats-ext 里有没有 MJPG —— 没有 MJPG 的 720p 摄像头,大概率只能跑 10 帧

  3. 别只看"支持 1080P",要看那个分辨率下的帧率是挂在哪种格式下面的

  4. 优先选带序列号的(我这颗有 202001010001),多摄像头时能区分谁是谁

  5. 线别贪长,超过 3 米考虑带供电的延长方案,长线掉速是常见现象

出问题时按这个顺序查:

  1. lsusb 都看不到 → 供电或接触问题,换口换线

  2. 能看到 USB 但 --list-devices 没有 → 不是 UVC 设备,或驱动没加载(dmesg | grep -i uvcvideo)

  3. 有节点但打不开 → 先看是不是 metadata 节点(Device Caps),再看 video 组权限

  4. 帧率远低于标称 → 先确认实际生效的格式(--get-fmt-video),多半是被协商成 YUYV 了

  5. 跑一会儿掉线 → 查 dmesg 有无 over-current,怀疑供电