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.
Set up the IO Feed
Create a feed called "barcode". (You can choose another feed name but you'll need to make sure that Adafruit IO's "key" for the feed matches what you use in your CircuitPython program!)
You can also add this Feed to a Dashboard, if you want to show it together with information from other Feeds.
settings.toml File Setup for Adafruit IO
If you don't have a settings.toml file in your CIRCUITPY drive yet, create one and add the information about your wifi connection.
Then, add the following code to your settings.toml file, replacing your-aio-username with your Adafruit IO username.
Then, replace your-super-long-aio-key with your Adafruit IO Active Key.
CIRCUITPY_WIFI_SSID="your-wifi-ssid" CIRCUITPY_WIFI_PASSWORD="your-wifi-password" ADAFRUIT_AIO_USERNAME="your-aio-username" ADAFRUIT_AIO_KEY="your-super-long-aio-key"
Make sure you save this file before proceeding as settings.toml in the root directory of your board CIRCUITPY drive.
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.
# 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. Your settings.toml must be populated with your wifi credentials
and your Adafruit IO credentials.
"""
from os import getenv
import ssl
from ulab import numpy as np
from terminalio import FONT
import board
import busio
import displayio
import fourwire
import qrio
import socketpool
import wifi
import adafruit_ov2640
from adafruit_display_text.bitmap_label import Label
from adafruit_ili9341 import ILI9341
from adafruit_io.adafruit_io import IO_MQTT
import adafruit_minimqtt.adafruit_minimqtt as MQTT
# Get WiFi details and Adafruit IO keys, ensure these are setup in settings.toml
# (visit io.adafruit.com if you need to create an account, or if you need your Adafruit IO key.)
ssid = getenv("CIRCUITPY_WIFI_SSID")
password = getenv("CIRCUITPY_WIFI_PASSWORD")
aio_username = getenv("ADAFRUIT_AIO_USERNAME")
aio_key = getenv("ADAFRUIT_AIO_KEY")
if None in [ssid, password, aio_username, aio_key]:
raise RuntimeError(
"WiFi and Adafruit IO settings are kept in settings.toml, "
"please add them there. The settings file must contain "
"'CIRCUITPY_WIFI_SSID', 'CIRCUITPY_WIFI_PASSWORD', "
"'ADAFRUIT_AIO_USERNAME' and 'ADAFRUIT_AIO_KEY' at a minimum."
)
# To change the name of the feed on adafruit_io, just modify this string:
feed_name = "qrstring"
print("Initializing display")
displayio.release_displays()
spi = busio.SPI(MOSI=board.LCD_MOSI, clock=board.LCD_CLK)
display_bus = fourwire.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
print("Connecting to WIFI")
wifi.radio.connect(ssid, password)
pool = socketpool.SocketPool(wifi.radio)
print("Connecting to Adafruit IO")
mqtt_client = MQTT.MQTT(
broker="io.adafruit.com",
username=aio_username,
password=aio_key,
socket_pool=pool,
ssl_context=ssl.create_default_context(),
)
mqtt_client.connect()
io = IO_MQTT(mqtt_client)
# Blank out any previously published message
io.publish(feed_name, "\ufeff")
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)
if payload != old_payload:
label.text = payload
print(payload)
for i in range(3):
try:
io.publish(feed_name, payload)
old_payload = payload
break
except OSError as e:
print(e)
mqtt_client.reconnect()
# 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 uploaded to Adafruit IO via WiFi.
If something goes wrong, you can use the REPL to diagnose the problem.
Page last edited March 19, 2025
Text editor powered by tinymce.