A frame-capture demo with Pi Pico, OV5640 camera, and CircuitPython.
This is a simple camera demo project to capture a 240x240 px grayscale frame every 2 seconds, convert the 8-bit pixel data to 1-bit, then print pixels to the serial console with Unicode Block Element characters.
Getting Started
To begin,
solder the headers,
assemble the stack of boards,
install CircuitPython,
then copy the project bundle code to your CIRCUITPY drive (check out the "Download Project Bundle" button below). Once
that's all done, code.py will begin capturing camera frames and printing them
to the
serial console.
If you want to keep a frame, press the shutter button to
stop the camera. To restart the camera, type Ctrl-C then Ctrl-D in your serial
terminal emulator.
It helps to use a serial terminal emulator that can run at a fast baud rate, like 115200. On macOS, I use screen -fn /dev/tty.usbmodem2201 115200 in a Terminal window (Ctrl-A, then k, then y to exit when you're done).
If you point the camera at a browser window with the qr-code Learn guide, the output should look similar to this (if you make your terminal's font size really small):
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2024 Sam Blenny
#
# CamTest: A simple demo of Pi Pico + Adafruit PiCowbell Camera Breakout
#
# Related Docs and Code:
# - https://learn.adafruit.com/adafruit-picowbell-camera-breakout
# - https://docs.circuitpython.org/projects/ov5640/en/latest/
# - https://github.com/adafruit/Adafruit_CircuitPython_OV5640/blob/main/adafruit_ov5640/__init__.py
#
from board import (
GP0, GP1, GP2, GP3, GP4, GP5, GP6, GP7, GP8, GP9, GP10,
GP11, GP12, GP13, GP14, GP18, GP19, GP22,
)
from busio import I2C, SPI
from digitalio import DigitalInOut, Pull
from displayio import Bitmap
from gc import collect, mem_free
from time import sleep
import adafruit_bus_device
from adafruit_ov5640 import (
OV5640, OV5640_SIZE_96X96, OV5640_SIZE_240X240, OV5640_COLOR_GRAYSCALE
)
def gcCol():
collect()
print("mem_free", mem_free())
def ttyPrint(pxBuf):
# Print pixel buffer using Unicode Block Element characters
blocks = [' ', 'â–€', 'â–„', 'â–ˆ']
for y in range(pxBuf.height >> 1):
y0 = y << 1
y1 = y0 + 1
s = []
for x in range(pxBuf.width):
s.append(blocks[
((pxBuf[x,y1]>> 7) << 1) | (pxBuf[x,y0] >> 7) ])
print(''.join(s))
def main():
# Make a buffer to hold captured pixel data
gcCol()
pxBuf = Bitmap(240, 240, 256)
# Configure the camera
spi = SPI(clock=GP18, MOSI=GP19)
i2c = I2C(GP5, GP4) # I2C(SCL, SDA)
shutter = DigitalInOut(GP22)
shutter.switch_to_input(Pull.UP) # active low
cam = OV5640(
i2c,
vsync=GP0,
href=GP2,
clock=GP3,
shutdown=DigitalInOut(GP1),
data_pins=(GP6, GP7, GP8, GP9, GP10, GP11, GP12, GP13),
reset=DigitalInOut(GP14),
mclk=None,
size=OV5640_SIZE_240X240,
)
cam.flip_x = True
cam.colorspace = OV5640_COLOR_GRAYSCALE
gcCol()
# Capture and print a frame every 2 seconds. Press shutter button to stop
# capturing frames (I use this for making screenshots).
stop = False
while True:
for _ in range(20):
sleep(0.1)
if not shutter.value:
stop = True
break
if stop:
break
cam.capture(pxBuf)
ttyPrint(pxBuf)
gcCol()
while True:
pass
main()
This page (CamTest: PiCowbell Camera Breakout Demo) was last updated on July 07, 2024.
Text editor powered by tinymce.