Use CircuitPython 7 for the code in this guide! Revised code will be required for CircuitPython 8.

Are you new to using CircuitPython? No worries, there is a full getting started guide here.

Adafruit suggests using the Mu editor to edit your code and have an interactive REPL in CircuitPython. You can learn about Mu and installation in this tutorial.

Download the Project Bundle

Your project will use a specific set of CircuitPython libraries and the code.py file. In order to get the libraries you need, click on the Download Project Bundle link below, and uncompress the .zip file.

Drag the contents of the uncompressed bundle directory onto your board's CIRCUITPY drive, replacing any existing files or directories with the same names, and adding any new ones that are necessary.

Folder
# SPDX-FileCopyrightText: Copyright (c) 2021 Jeff Epler for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense

"""
This demo is designed for the Kaluga development kit version 1.3 with the
ILI9341 display.
"""

from ulab import numpy as np
from terminalio import FONT
import board
import busio
import displayio
import qrio
import adafruit_ov2640
from adafruit_display_text.bitmap_label import Label
from adafruit_ili9341 import ILI9341

print("Initializing display")
displayio.release_displays()
spi = busio.SPI(MOSI=board.LCD_MOSI, clock=board.LCD_CLK)
display_bus = displayio.FourWire(
    spi, command=board.LCD_D_C, chip_select=board.LCD_CS, reset=board.LCD_RST
)
display = ILI9341(display_bus, width=320, height=240, rotation=90)

print("Initializing camera")
bus = busio.I2C(scl=board.CAMERA_SIOC, sda=board.CAMERA_SIOD)
cam = adafruit_ov2640.OV2640(
    bus,
    data_pins=board.CAMERA_DATA,
    clock=board.CAMERA_PCLK,
    vsync=board.CAMERA_VSYNC,
    href=board.CAMERA_HREF,
    mclk=board.CAMERA_XCLK,
    mclk_frequency=20_000_000,
    size=adafruit_ov2640.OV2640_SIZE_QQVGA,
)
cam.flip_x = False
cam.flip_y = False
cam.colorspace = adafruit_ov2640.OV2640_COLOR_YUV

qrdecoder = qrio.QRDecoder(cam.width, cam.height)
bitmap = displayio.Bitmap(cam.width, cam.height, 65536)

# Create a greyscale palette
pal = displayio.Palette(256)
for i in range(256):
    pal[i] = 0x10101 * i

label = Label(
    font=FONT,
    text="Scan QR Code...",
    color=0xFFFFFF,
    background_color=0x0,
    padding_top=2,
    padding_left=2,
    padding_right=2,
    padding_bottom=2,
    anchor_point=(0.5, 1.0),
    anchored_position=(160, 230),
)
# Show the camera image at 2x size
g1 = displayio.Group(scale=2)
view = np.frombuffer(bitmap, dtype=np.uint8)
tg = displayio.TileGrid(
    bitmap,
    pixel_shader=pal,
)
tg.flip_y = True
g1.append(tg)
g = displayio.Group()
g.append(g1)
g.append(label)
display.root_group = g
display.auto_refresh = False

old_payload = None
while True:
    cam.capture(bitmap)

    for row in qrdecoder.decode(bitmap, qrio.PixelPolicy.EVEN_BYTES):
        payload = row.payload
        try:
            payload = payload.decode("utf-8")
        except UnicodeError:
            payload = str(payload)
        print(payload)

    # Clear out the odd bytes, so that the bitmap displays as greyscale
    view[1::2] = 0
    bitmap.dirty()
    display.refresh(minimum_frames_per_second=0)

Once the code is uploaded, the program will automatically start and display a greyscale capture from the camera.

Hold a printed QR code in front of the camera at a distance of about 6". The scanned QR code will be shown on the LCD and also in the REPL.

If something goes wrong, you can use the REPL to diagnose the problem.

This guide was first published on Aug 12, 2021. It was last updated on Mar 28, 2024.

This page (Scan To REPL) was last updated on Mar 28, 2024.

Text editor powered by tinymce.