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
相关产品推荐
相关产品推荐

