adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
Other
4.11k stars 1.22k forks source link

SPI display goes black when running camera mirror example on Pico 2 #9662

Closed BlitzCityDIY closed 4 weeks ago

BlitzCityDIY commented 1 month ago

CircuitPython version

Adafruit CircuitPython 9.2.0-beta.0-12-gcd5c9d2632 on 2024-09-25; Raspberry Pi Pico 2 with rp2350a

Code/REPL

import board
import busio
import terminalio
import displayio
import adafruit_ov5640
import digitalio
import time
import adafruit_st7789

# Support both 8.x.x and 9.x.x. Change when 8.x.x is discontinued as a stable release.
try:
    from fourwire import FourWire
except ImportError:
    from displayio import FourWire

# Release any resources currently in use for the displays
displayio.release_displays()
spi = busio.SPI(clock=board.GP18, MOSI=board.GP19, MISO=board.GP16)
tft_cs = board.GP21
tft_dc = board.GP20
display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs, reset=None)
display = adafruit_st7789.ST7789(display_bus, width=240, height=240, rowstart=80, rotation=0)
print(spi.frequency)
freq = spi.frequency
spi.try_lock()
spi.configure(baudrate=int(freq / 2))
spi.unlock()
print(spi.frequency)
print("construct bus")
i2c = busio.I2C(board.GP5, board.GP4)
print("construct camera")
reset = digitalio.DigitalInOut(board.GP14)
cam = adafruit_ov5640.OV5640(
    i2c,
    data_pins=(
        board.GP6,
        board.GP7,
        board.GP8,
        board.GP9,
        board.GP10,
        board.GP11,
        board.GP12,
        board.GP13,
    ),
    clock=board.GP3,
    vsync=board.GP0,
    href=board.GP2,
    mclk=None,
    shutdown=None,
    reset=reset,
    size=adafruit_ov5640.OV5640_SIZE_240X240,
)
print("print chip id")
print(cam.chip_id)

cam.colorspace = adafruit_ov5640.OV5640_COLOR_RGB
cam.flip_y = False
cam.flip_x = False
cam.test_pattern = False

width = display.width
height = display.height

try:
    bitmap = displayio.Bitmap(cam.width, cam.height, 65535)
except MemoryError:
    print("Oops, 240x240 is a little too big, trying 240x176..")
    cam.size = adafruit_ov5640.OV5640_SIZE_QCIF
    bitmap = displayio.Bitmap(cam.width, cam.height, 65535)
print(width, height, cam.width, cam.height)
if bitmap is None:
    raise SystemExit("Could not allocate a bitmap")

g = displayio.Group(scale=1, x=(width-cam.width)//2, y=(height-cam.height)//2)
tg = displayio.TileGrid(bitmap,
    pixel_shader=displayio.ColorConverter(input_colorspace=displayio.Colorspace.RGB565_SWAPPED)
)
g.append(tg)
display.root_group = g

t0 = time.monotonic_ns()
display.auto_refresh = False
while True:
    cam.capture(bitmap)
    bitmap.dirty()
    display.refresh(minimum_frames_per_second=0)
    t1 = time.monotonic_ns()
    print("fps", 1e9 / (t1 - t0))
    t0 = t1

Behavior

The preview for the camera will show correctly on the display for a while, but then the colors will either invert or the display will go black. The code is still running because the camera FPS is still printing to the serial console. The hardware setup I'm using is with a Pico 2, PiCowbell Camera and a PiCowbell Tripler. The display is connected via the EYESPI connector. I've tried a 1.54" ST7789 240x240 display and a 2.8" ILI9341 240x320 display.

I have tried setting the camera size to OV5640_SIZE_QCIF, OV5640_SIZE_HQVGA, OV5640_SIZE_240X240 and OV5640_SIZE_QVGA (QVGA only when using the 240x320 display)

Description

I have tried reducing the SPI frequency, which previously I didn't have to do for this example with the Pico. However, the issue still persists. I was trying increasingly lower frequencies all the way down to spi.configure(baudrate=1000) (which is an actual frequency of 2288 when I print it to the console) and that seemed to keep the display alive for the longest. The default SPI frequency prints as 18750000 and half of that prints as 9375000.

Additional information

I have not been able to recreate the issue using a Pico RP2040. When displaying the REPL the display does not go out.

BlitzCityDIY commented 1 month ago

testing with display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs, reset=None, baudrate = 9375000) instead of spi.configure(frequency=) and that actually affects display speed. display is staying up but the bottom 1/3 pixels on 240x240 disappear and show the REPL

jepler commented 1 month ago

I'm trying to reproduce this with a similar setup:

PXL_20240925_220249882

clock for code.py for my setup ```py import board import busio import terminalio import displayio import adafruit_ov5640 import digitalio import time import adafruit_st7789 # Support both 8.x.x and 9.x.x. Change when 8.x.x is discontinued as a stable release. try: from fourwire import FourWire except ImportError: from displayio import FourWire # Release any resources currently in use for the displays displayio.release_displays() spi = busio.SPI(clock=board.GP18, MOSI=board.GP19, MISO=board.GP16) tft_cs = board.GP21 tft_dc = board.GP20 display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs, reset=None) #display = adafruit_st7789.ST7789(display_bus, width=240, height=240, rowstart=80, rotation=0) display = adafruit_st7789.ST7789(display_bus, height=320, width=170, colstart=35) print(spi.frequency) freq = spi.frequency spi.try_lock() spi.configure(baudrate=int(freq / 2)) spi.unlock() print(spi.frequency) print("construct bus") i2c = busio.I2C(board.GP5, board.GP4) print("construct camera") reset = digitalio.DigitalInOut(board.GP14) cam = adafruit_ov5640.OV5640( i2c, data_pins=( board.GP6, board.GP7, board.GP8, board.GP9, board.GP10, board.GP11, board.GP12, board.GP13, ), clock=board.GP3, vsync=board.GP0, href=board.GP2, mclk=None, shutdown=None, reset=reset, size=adafruit_ov5640.OV5640_SIZE_240X240, ) print("print chip id") print(cam.chip_id) cam.colorspace = adafruit_ov5640.OV5640_COLOR_RGB cam.flip_y = False cam.flip_x = False cam.test_pattern = False width = display.width height = display.height try: bitmap = displayio.Bitmap(cam.width, cam.height, 65535) except MemoryError: print("Oops, 240x240 is a little too big, trying 240x176..") cam.size = adafruit_ov5640.OV5640_SIZE_QCIF bitmap = displayio.Bitmap(cam.width, cam.height, 65535) print(width, height, cam.width, cam.height) if bitmap is None: raise SystemExit("Could not allocate a bitmap") g = displayio.Group(scale=1, x=(width-cam.width)//2, y=(height-cam.height)//2) tg = displayio.TileGrid(bitmap, pixel_shader=displayio.ColorConverter(input_colorspace=displayio.Colorspace.RGB565_SWAPPED) ) g.append(tg) display.root_group = g t0 = time.monotonic_ns() display.auto_refresh = False while True: cam.capture(bitmap) bitmap.dirty() display.refresh(minimum_frames_per_second=0) t1 = time.monotonic_ns() print("fps", 1e9 / (t1 - t0)) t0 = t1 ```
dhalbert commented 4 weeks ago

@BlitzCityDIY Are the boards on the tripler in the same place as in @jepler's photo?

The hardware setup I'm using is with a Pico 2, PiCowbell Camera and a PiCowbell Tripler.

dhalbert commented 4 weeks ago

I tested with a Pico 2, PiCowbell Camera, and the tripler. I used the 1.54" ST7789 240x240 display and a 100mm EYESPI cable. I put the Pico 2 in the same position as the EYESPI cable, and the camera in the middle.

I ran the test program in the original post for several hours, and saw no problems.

BlitzCityDIY commented 4 weeks ago

i did try rearranging the boards and had the same result. i think where no one else has been able to recreate it's okay to close this- it's probably some undiagnosed issue with my setup

dhalbert commented 4 weeks ago

Might be worth trying another Pico 2 if you have one, or another Cowbell doubler/tripler. Maybe there's an unsoldered pin?