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

Arducam OV2640与Pico通信异常:无法获取图像数据

Arducam OV2640在Raspberry Pi Pico CircuitPython下的拍摄问题排查

问题背景

将Arducam 2MP Plus(OV2640)连接到运行CircuitPython的Raspberry Pi Pico,尝试拍摄并本地存储单张图像时遇到以下问题:

  • 标记为this line here的mycam.get_bit(ARDUCHIP_TRIG,CAP_DONE_MASK)!=0始终返回0,无法触发FIFO数据读取逻辑
  • 移除该判断后能获取字节数组,但用UTF-8解码时报错:UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte

核心代码基于Arducam官方示例修改,将原USB CDC传输逻辑改为本地文件存储,代码如下:

import time as utime
import busio
import board
from Arducam import *
from board import *

once_number=128
mode = 0
start_capture = 1
stop_flag=0
data_in=0
value_command=0
flag_command=0
buffer=bytearray(once_number)
i2c = busio.I2C(board.GP27, board.GP26)

mycam = ArducamClass(OV2640, i2c)
mycam.Camera_Detection()
mycam.Spi_Test()
mycam.Camera_Init()
utime.sleep(1)
mycam.clear_fifo_flag()

mycam.OV2640_set_JPEG_size(OV2640_800x600)
mycam.set_format(JPEG)
mycam.OV2640_set_Light_Mode(Auto)
mycam.OV2640_set_Color_Saturation(Saturation2)
mycam.OV2640_set_Brightness(Brightness2)
mycam.OV2640_set_Contrast(Contrast2)
mycam.OV2640_set_Special_effects(Normal)

def read_fifo_burst():
    count=0
    lenght=mycam.read_fifo_length()
    mycam.SPI_CS_LOW()
    mycam.set_fifo_burst()
    file = open("file.txt", 'a')  # 用txt查看输出内容
    while True:
        mycam.spi.readinto(buffer,start=0,end=once_number)
        file.write(buffer)
        utime.sleep(0.00015)
        count+=once_number
        if count+once_number>lenght:
            count=lenght-count
            mycam.spi.readinto(buffer,start=0,end=count)
            file.write(buffer)
            mycam.SPI_CS_HIGH()
            mycam.clear_fifo_flag()
            break
        
while True:
    if start_capture==1:
        mycam.flush_fifo();
        mycam.clear_fifo_flag();
        mycam.start_capture();
        start_capture=0
        print("here")
    if mycam.get_bit(ARDUCHIP_TRIG,CAP_DONE_MASK)!=0:  # this line here
        read_fifo_burst()
        print("done")

问题解答

1. 为什么get_bit()始终返回0?

可能的原因及排查方向:

  • SPI通信时序不匹配:CircuitPython的SPI实现与原MicroPython示例存在差异,需确保SPI速率(建议≤10MHz)、模式(OV2640默认SPI模式0)与摄像头要求一致,检查库中SPI初始化参数是否正确。
  • CAP_DONE标志位读取逻辑问题:直接打印ARDUCHIP_TRIG寄存器的原始值(print(mycam.read_reg(ARDUCHIP_TRIG))),确认是否包含CAP_DONE对应的位,排查get_bit函数是否正确解析寄存器值。
  • 初始化流程不完整:Camera_Init()后仅等待1秒可能不足,部分模块需要更长时间完成配置;或clear_fifo_flag()未正确清除历史标志位,导致后续判断失效。
  • 硬件接线错误:检查SPI的CS引脚是否正确连接(未拉低会导致寄存器读取失效),同时确认I2C接线(SDA/GP26、SCL/GP27)无虚接。

2. 字节数组是否为图像数据?

是的。UTF-8解码报错是因为JPEG是二进制格式,并非文本数据,不能用文本编码方式解码。直接将字节数组保存为.jpg文件即可正常查看图像。

3. 更优实现方案

修复CAP_DONE检测逻辑

将主循环中的单次判断改为循环等待,确保捕获完成后再读取数据:

while True:
    if start_capture==1:
        mycam.flush_fifo()
        mycam.clear_fifo_flag()
        mycam.start_capture()
        start_capture=0
        print("Capturing...")
        # 循环等待CAP_DONE信号,降低CPU占用
        while mycam.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK) == 0:
            utime.sleep(0.01)
        read_fifo_burst()
        print("done")
        start_capture = 1  # 可选:开启下一次拍摄循环

优化文件存储逻辑

使用二进制模式打开文件,避免文本模式的自动转换问题,同时确保文件正确关闭:

def read_fifo_burst():
    count=0
    length=mycam.read_fifo_length()
    if length == 0:
        print("FIFO empty, skip read")
        return
    mycam.SPI_CS_LOW()
    mycam.set_fifo_burst()
    # 用二进制追加模式打开,直接保存为JPG文件
    with open("captured.jpg", 'ab') as file:
        while count < length:
            read_size = min(once_number, length - count)
            mycam.spi.readinto(buffer, start=0, end=read_size)
            file.write(buffer[:read_size])
            utime.sleep(0.00015)
            count += read_size
    mycam.SPI_CS_HIGH()
    mycam.clear_fifo_flag()

调试与验证

  • 在start_capture()后打印FIFO长度:print("FIFO length after capture:", mycam.read_fifo_length()),若长度>0说明摄像头已捕获数据,问题出在CAP_DONE信号的读取上。
  • 确认ARDUCHIP_TRIG寄存器地址(通常为0x4)和CAP_DONE_MASK位值(通常为0x08)与库中常量定义一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 01:25:28