Adsense HTML/JavaScript

Monday, September 27, 2021

nanoESP32-S2 + ov7670 cam module/ST7789 SPI TFT (CircuitPython 7.0.0)


The previous post descripted how to install CircuitPython 7.0.0 and Library Bundle on nanoESP32-S2, and and SPI ST7789 LCD. This exercise capture image from ov7670 camera module and display it on ST7789 SPI LCD.


Libraries

adafruit_ov7670 and adafruit_st7789. How to download and install Adafruit Library, refer to the previous post.


Connection between nanoESP32-S2 and ov7670 cam module/ST7789 SPI TFT


	ov7670 header
	+-----------+
3V3	|3V3	DGND|	GND
IO7	|SCL*	SDA*|	IO8
IO9	|VS	HS  |	IO10
IO11	|PLK	XLK |	IO12
IO40	|D7	D6  |	IO39
IO38	|D5	D4  |	IO37
IO36	|D3	D2  |	IO35
IO34	|D1	D0  |	IO33
IO13	|RET	PWDN|
	+-----------+
		
*cam.SCL/SDA are I2C control pin, pull-up resistors are needed.
 I use 2K ohm resistor for it.


ST7789	    +-------------------------------+
-----       |				    |
 GND | -----+	+-------------------+	    |
 VCC | -------- | 3V3	        GND | ------+
 SCL | -------- | 0		RST |
 SDA | -------- | 1		46  |
 RES | -------- | 2		45  |
 DC  | -------- | 3		44  |
 CS  | -------- | 4		43  |
 BLK | -------- | 5		42  |
----- 		| 6		41  |
	cam.scl	| 7		40  | cam.D7
	cam.sda	| 8		39  | cam.D6
	cam.VS	| 9		38  | cam.D5
	cam.HS	| 10		37  | cam.D4
	cam.PLK	| 11		36  | cam.D3
	cam.XLK	| 12		35  | cam.D2
	cam.RET	| 13		34  | cam.D1
		| 14		33  | cam.D0
		| 15		26  |
		| 16		21  | 
		| 17		20  | 
		| 5V0		19  | 
		| GND		18  | 
		+-------------------+
		nanoESP32-S2

Exercise code

ov7670_displayio_nanoESP32S2_st7789_2in.py
"""
CircuitPython (7.0.0) exercise run on nanoESP32-S2,
capture image from ov7670 camera module and
display it on ST7789 SPI LCD.

Modified from ov7670_displayio_pico_st7789_2in.py example
in CircuitPython Bundle for Version 7.x
"""

import time
from displayio import (
    Bitmap,
    Group,
    TileGrid,
    FourWire,
    release_displays,
    ColorConverter,
    Colorspace,
)
import adafruit_st7789
import board
import busio
import digitalio
import adafruit_ov7670

import gc

print(adafruit_ov7670.__name__, ":", adafruit_ov7670.__version__)
print(adafruit_st7789.__name__, ":", adafruit_st7789.__version__)
print()
time.sleep(1)
gc.collect()
print("free mem@power up", gc.mem_free())  # print free memory

# Set up the display (You must customize this block for your display!)
release_displays()

#assign pins for nanoESP32-S2
tft_blk = board.IO5
tft_cs = board.IO4
tft_dc = board.IO3
tft_res = board.IO2
spi_mosi = board.IO1
spi_clk = board.IO0

pin_blk = digitalio.DigitalInOut(tft_blk)
pin_blk.direction = digitalio.Direction.OUTPUT
pin_blk.value = True

spi = busio.SPI(spi_clk, MOSI=spi_mosi)

display_bus = FourWire(
    spi, command=tft_dc, chip_select=tft_cs, reset=tft_res
)

#for 240x320
display = adafruit_st7789.ST7789(display_bus,
                    width=320, height=240, rotation=90)

cam_scl = board.IO7
cam_sda = board.IO8
cam_reset = board.IO13

# Ensure the camera is shut down, so that it releases the SDA/SCL lines,
# then create the configuration I2C bus

with digitalio.DigitalInOut(cam_reset ) as reset:
    reset.switch_to_output(False)
    time.sleep(0.001)
    bus = busio.I2C(scl=cam_scl, sda=cam_sda)

# Set up the camera (you must customize this for your board!)
cam = adafruit_ov7670.OV7670(
    bus,
    data_pins=[
        board.IO33,
        board.IO34,
        board.IO35,
        board.IO36,
        board.IO37,
        board.IO38,
        board.IO39,
        board.IO40,
    ], 
    clock=board.IO11,   #PLK
    vsync=board.IO9,    #VS
    href=board.IO10,    #HS
    mclk=board.IO12,    #XLK
    shutdown=None,
    reset=cam_reset ,
)  # [14]

width = display.width
height = display.height

# cam.test_pattern = OV7670_TEST_PATTERN_COLOR_BAR

bitmap = None
# Select the biggest size for which we can allocate a bitmap successfully, and
# which is not bigger than the display
#
# *** Remark by Erik: due to limited memory for bitmap,
# *** OV7670_SIZE_DIV8 (80x60) is selected.
#
gc.collect()
print("free mem@before bitmap", gc.mem_free())  # print free memory

for size in range(adafruit_ov7670.OV7670_SIZE_DIV1,
                  adafruit_ov7670.OV7670_SIZE_DIV16 + 1):
    cam.size = size
    if cam.width > width:
        continue
    if cam.height > height:
        continue
    try:
        bitmap = Bitmap(cam.width, cam.height, 65536)
        break
    except MemoryError:
        print("MemoryError in allocate bitmap", cam.width, " x ", cam.height)
        continue

"""
# Erik: to use fixed cam.size
cam.size = adafruit_ov7670.OV7670_SIZE_DIV8
bitmap = Bitmap(cam.width, cam.height, 65536)
"""

print("free mem@after bitmap", gc.mem_free())  # print free memory

print(width, height, cam.width, cam.height)
print()

if bitmap is None:
    raise SystemExit("Could not allocate a bitmap")

# Erik: change gScale to enlarge image on screen
gScale = 1
g = Group(scale=gScale,
          x=(width - (gScale*cam.width)) // 2,
          y=(height - (gScale*cam.height)) // 2)

tg = TileGrid(
    bitmap, pixel_shader=ColorConverter(input_colorspace=Colorspace.RGB565_SWAPPED)
)
g.append(tg)
display.show(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

In my test, due to limited memory, I can create bitmap of 80x60 only!



No comments:

Post a Comment