OV5647与树莓派bullseye 64bit的兼容性问题

1. 源由

最近一直在倒腾摄像头,OpenIPC/FPV、CompanionComputer、IPC等,都离不开这个摄像头。可惜树莓派上的这个摄像头尤其奇怪,明明之前是好的,但是系统升级以后出现了一些兼容性问题。

为此,特地总结归纳下。有知道的朋友也请告知下如何解决,谢谢!

问题出处主要是Rover上CompanionComputer一直摄像头问题不断,导致不断地换货、测试、分析、定位。

最后OV5647的买家来了一句“OV5647树莓派只是支持32位”。我晕,我可以发誓“前面几个月,我用的这个树莓派伴机电脑,一直用64位系统,同一张tf卡,没见什么问题啊!!!”

2. 问题

貌似问题越来越指向兼容性、参数优化等问题。
而目前最为重要的问题,就是采用python的gst库获取设备的时候,会出现Segmentation fault,这个可不是什么好事情。

3. 分析

在树莓派上编程以获取摄像头设备列表,可以使用多种方法,包括 pyudevv4l2-ctl、以及直接读取 /dev 目录。

以下是几种有效的方法,按理应该能够在树莓派上成功获取摄像头设备列表并验证其工作状态。如果依然遇到问题,请检查硬件连接、摄像头模块的兼容性以及驱动是否正确安装。

方法一:使用 pyudev 库

pyudev 是一个与设备直接交互的库,适用于树莓派。

  1. 安装 pyudev
$ pip install pyudev
  1. 使用以下代码获取摄像头设备列表:
import pyudev

context = pyudev.Context()
cameras = []
for device in context.list_devices(subsystem='video4linux'):
    cameras.append(device.device_node)

print("Available cameras:", cameras)

方法二:使用 v4l2-ctl 工具

v4l2-ctl 是一个命令行工具,可以列出视频设备。

  1. 安装 v4l-utils
$ sudo apt-get install v4l-utils
  1. 使用以下代码获取摄像头设备列表:
import subprocess

def list_cameras():
    try:
        output = subprocess.check_output("v4l2-ctl --list-devices", shell=True).decode('utf-8')
        devices = []
        lines = output.split('\n')
        for i in range(len(lines)):
            if "video" in lines[i]:
                devices.append(lines[i].strip())
        return devices
    except Exception as e:
        print(f"Error: {e}")
        return []

print("Available cameras:", list_cameras())

方法三:直接读取 /dev 目录

使用以下代码获取摄像头设备列表:

import os

def list_cameras():
    video_devices = [f"/dev/{f}" for f in os.listdir('/dev') if f.startswith('video')]
    return video_devices

print("Available cameras:", list_cameras())

方法四:使用 OpenCV

OpenCV 是一个流行的计算机视觉库,也可以用于检测摄像头设备。

  1. 安装 OpenCV:
$ sudo apt-get install python3-opencv
$ pip install numpy
  1. 使用以下代码获取摄像头设备列表:
import cv2

def list_cameras():
    index = 0
    arr = []
    while True:
        cap = cv2.VideoCapture(index)
        if not cap.read()[0]:
            break
        else:
            arr.append(index)
        cap.release()
        index += 1
    return arr

print("Available cameras:", list_cameras())

方法五:使用 Picamera

Picamera 库是专门为树莓派摄像头模块设计的。

  1. 安装 picamera
$ pip install picamera
  1. 使用以下代码检查摄像头是否连接:
from picamera import PiCamera
from time import sleep

camera = PiCamera()
try:
    camera.start_preview()
    sleep(5)
    camera.capture('/home/pi/Desktop/image.jpg')
    camera.stop_preview()
    print("Camera is working and captured an image.")
except PiCameraError as e:
    print(f"Failed to access camera: {e}")

方法六:使用 libcamera

  1. 使用 /dev 目录列出设备
import os

def list_video_devices():
    video_devices = [f"/dev/{device}" for device in os.listdir('/dev') if device.startswith('video')]
    return video_devices

print("Video devices:", list_video_devices())
  1. 使用 libcamera 工具检查设备兼容性
import subprocess
import os

def list_video_devices():
    video_devices = [f"/dev/{device}" for device in os.listdir('/dev') if device.startswith('video')]
    return video_devices

def check_libcamera_compatibility(device):
    try:
        result = subprocess.run(["libcamera-hello"], capture_output=True, text=True, timeout=5)
        if "No cameras available" in result.stderr:
            return False
        return True
    except subprocess.TimeoutExpired:
        return False
    except Exception as e:
        print(f"Error checking device {device}: {e}")
        return False

video_devices = list_video_devices()
compatible_devices = [device for device in video_devices if check_libcamera_compatibility(device)]

print("All video devices:", video_devices)
print("Compatible with libcamera:", compatible_devices)

4. 实测

从这里,我们可以真实的看到摄像头存在,并且经过libcamera验证也是可以出图的。

$ libcamera-hello --list-camera
Available cameras
-----------------
0 : ov5647 [2592x1944] (/base/soc/i2c0mux/i2c@1/ov5647@36)
    Modes: 'SGBRG10_CSI2P' : 640x480 [58.92 fps - (16, 0)/2560x1920 crop]
                             1296x972 [43.25 fps - (0, 0)/2592x1944 crop]
                             1920x1080 [30.62 fps - (348, 434)/1928x1080 crop]
                             2592x1944 [15.63 fps - (0, 0)/2592x1944 crop]

方法一:使用 pyudev 库

仅仅只是遍历了/dev/video*的效果,并未很好的发现设备。

$ python3 test-pyudev.py
Available cameras: ['/dev/video10', '/dev/video11', '/dev/video12', '/dev/video18', '/dev/video31', '/dev/video13', '/dev/video14', '/dev/video15', '/dev/video16', '/dev/video20', '/dev/video21', '/dev/video22', '/dev/video23', '/dev/v4l-subdev0', '/dev/video0']

方法二:使用 v4l2-ctl 工具

仅仅只是遍历了/dev/video*的效果,并未很好的发现设备。

$ python3 test-v4l2-ctl.py
Available cameras: ['/dev/video0', '/dev/video10', '/dev/video11', '/dev/video12', '/dev/video18', '/dev/video31', '/dev/video13', '/dev/video14', '/dev/video15', '/dev/video16', '/dev/video20', '/dev/video21', '/dev/video22', '/dev/video23']

方法三:直接读取 /dev 目录

仅仅只是遍历了/dev/video*,未很好的发现设备,与遍历目录结果一致。

 $ python3 test-dev.py
Available cameras: ['/dev/video0', '/dev/video31', '/dev/video18', '/dev/video12', '/dev/video11', '/dev/video10', '/dev/video23', '/dev/video22', '/dev/video21', '/dev/video20', '/dev/video16', '/dev/video15', '/dev/video14', '/dev/video13']

方法四:使用 OpenCV

未发现摄像头设备。

 $ python3 test-opencv.py
Available cameras: []

方法五:使用 Picamera

略. 树莓派目前已经从Picamera升级到libcamera,这里不做介绍。

方法六:使用 libcamera

未发现摄像头设备。

$ python3 test-libcamera.py
All video devices: ['/dev/video0', '/dev/video31', '/dev/video18', '/dev/video12', '/dev/video11', '/dev/video10', '/dev/video23', '/dev/video22', '/dev/video21', '/dev/video20', '/dev/video16', '/dev/video15', '/dev/video14', '/dev/video13']
Compatible with libcamera: []

方法七:命令v4l2-ctl

发现摄像头unicam (platform:3f801000.csi):/dev/video0

$ sudo v4l2-ctl --list-devices
unicam (platform:3f801000.csi):
        /dev/video0
        /dev/media2

bcm2835-codec-decode (platform:bcm2835-codec):
        /dev/video10
        /dev/video11
        /dev/video12
        /dev/video18
        /dev/video31
        /dev/media3

bcm2835-isp (platform:bcm2835-isp):
        /dev/video13
        /dev/video14
        /dev/video15
        /dev/video16
        /dev/video20
        /dev/video21
        /dev/video22
        /dev/video23
        /dev/media0
        /dev/media1

方法八:命令libcamera

发现摄像头ov5647

$ libcamera-hello  --list-camera
Available cameras
-----------------
0 : ov5647 [2592x1944] (/base/soc/i2c0mux/i2c@1/ov5647@36)
    Modes: 'SGBRG10_CSI2P' : 640x480 [58.92 fps - (16, 0)/2560x1920 crop]
                             1296x972 [43.25 fps - (0, 0)/2592x1944 crop]
                             1920x1080 [30.62 fps - (348, 434)/1928x1080 crop]
                             2592x1944 [15.63 fps - (0, 0)/2592x1944 crop]

5. 总结

从上述分析和实测情况看:

  • 方法三采用遍历目录的方式,很直接,效果就是遍历
  • 其他pyudev、v4l2-ctl采用的细节不清楚,但是效果与遍历目录一致
  • 使用opencv、libcamera似乎更是玄学,结果也是没有找到摄像头设备
  • 相信上面除了遍历目录以外,或多或少会有通过驱动API去发现设备,但是结果没有成功
  • 命令v4l2-ctl --list-devices枚举设备成功
  • 命令libcamera-hello --list-camera枚举设备成功,并反馈正确参数

因此,期望能定位原因,并找到解决编码方法能够正确的找到摄像头设备。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description:    Debian GNU/Linux 11 (bullseye)
Release:        11
Codename:       bullseye
$ uname -a
Linux rpanion 6.1.21-v8+ #1642 SMP PREEMPT Mon Apr  3 17:24:16 BST 2023 aarch64 GNU/Linux
r40_tinav2.1_最终验证通过_使用CB-S来验证OV5640有横条纹fpscamera+SPI2.0成功_20171114_1443没有外层目录.7z 开发板:CB-S 1、(可选修改/调试技巧:) 除了ov5640.c之外,其它的驱动都不编译,节省编译时间! W:\ov5640_spi20_r40t\lichee\linux-3.10\drivers\media\platform\sunxi-vfe\device\Makefile obj-m += ov5640.o #obj-m += ov2640.o #obj-m += ov7736.o #obj-m += s5k4ec.o #obj-m += s5k4ec_mipi.o #obj-m += gc2035.o #obj-m += gt2005.o #obj-m += gc0307.o #obj-m += gc0308.o #obj-m += gc0328.o #obj-m += gc0328c.o #obj-m += gc2145.o #obj-m += gc0329.o #obj-m += gc0311.o #obj-m += hi253.o #obj-m += sp2518.o #obj-m += sp2519.o #obj-m += sp0718.o #obj-m += sp0838.o #obj-m += ov16825.o #obj-m += ov5650.o #obj-m += ov5647.o #obj-m += ov5647_mipi.o #obj-m += t8et5.o #obj-m += s5k4e1.o #obj-m += s5k4e1_mipi.o #obj-m += sp2518.o #obj-m += sp0718.o #obj-m += gc5004.o #obj-m += gc5004_mipi.o #obj-m += ov5648.o #obj-m += ar0330.o #obj-m += ov5648.o #obj-m += sp5408.o #obj-m += ov12830.o #obj-m += ov8825.o #obj-m += ov8850.o #obj-m += gc2155.o #obj-m += ov8858.o #obj-m += ov13850.o #obj-m += imx214.o #obj-m += ov8858_4lane.o #obj-m += sp5409.o #obj-m += s5k5e2yx.o #obj-m += ov2710_mipi.o #obj-m += ov2686.o (这里是看ov5640的驱动的probe执行是否正确?设备ID是否读取成功!) W:\ov5640_spi20_r40t\lichee\linux-3.10\drivers\media\platform\sunxi-vfe\device\ov5640.c static int sensor_detect(struct v4l2_subdev *sd) { data_type rdval; printk("****wyb %s:%d/%s()! \n", __FILE__, __LINE__, __func__); LOG_ERR_RET(sensor_read(sd, 0x300a, &rdval;)) printk("****wyb %s:%d/%s()! 0x300a rdval=0xx\n", __FILE__, __LINE__, __func__, rdval); if(rdval != 0x56) return -ENODEV; LOG_ERR_RET(sensor_read(sd, 0x300b, &rdval;)) printk("****wyb %s:%d/%s()! 0x300b rdval=0xx\n", __FILE__, __LINE__, __func__, rdval); if(rdval != 0x40) return -ENODEV; return 0; } (在全志R16平台改过这个文件,让摄像头不要休眠,但是全志R40平台的tina v2.1系统下不需要修改!) W:\ov5640_spi20_r40t\lichee\linux-3.10\drivers\media\platform\sunxi-vfe\vfe.c 2、(可
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值