ESP32-S3/CircuitPython, generate QR Code, display on ILI9341 SPI TFT.

ESP32-S3-DevKitC-1/CircuitPython 7.3.2 exercise generate QR code using adafruit_miniqr.mpy library, and display on 2.4" 320x240 ILI9341 SPI TFT using adafruit_ili9341.mpy library.


Adafruit miniQR Library is a non-hardware dependant miniature QR generator library. All native Python!

How to display on 2.4" 320x240 ILI9341 SPI TFT, using ESP32-S3-DevKitC-1/CircuitPython, and connection, read the post "320x240 ILI9341 SPI TFT drived with ESP32-S3/CircuitPython".

Download and install CircuitPython Library, it's a example miniqr_simpletest.py in CircuitPython Library Bundle's example folder, to draw QR Code to the the REPL console.

Another example miniqr_displaytest.py example display QR Code on board with build-in display.
But...not work on my case without build-in display.

Here, cpyS3_ili9341_miniqr_displaytest.py, modified from miniqr_displaytest.py. To display on my 2.4" 320x240 ILI9341 SPI TFT.
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT

import board
import displayio
import adafruit_miniqr

import adafruit_ili9341
import busio

# Release any resources currently in use for the displays
displayio.release_displays()

#===init display ======================
disp_width = 320
disp_height = 240

disp_cs  = board.IO4
disp_res = board.IO5
disp_dc  = board.IO6

disp_mosi = board.IO7
disp_clk = board.IO15
disp_spi = busio.SPI(clock=disp_clk,
                     MOSI=disp_mosi)

display_bus = displayio.FourWire(
    disp_spi,
    command=disp_dc,
    chip_select=disp_cs,
    reset=disp_res
)

display = adafruit_ili9341.ILI9341(display_bus,
                                   width=disp_width,
                                   height=disp_height)
#=======================================

def bitmap_QR(matrix):
    # monochome (2 color) palette
    BORDER_PIXELS = 2

    # bitmap the size of the screen, monochrome (2 colors)
    bitmap = displayio.Bitmap(
        matrix.width + 2 * BORDER_PIXELS, matrix.height + 2 * BORDER_PIXELS, 2
    )
    # raster the QR code
    for y in range(matrix.height):  # each scanline in the height
        for x in range(matrix.width):
            if matrix[x, y]:
                bitmap[x + BORDER_PIXELS, y + BORDER_PIXELS] = 1
            else:
                bitmap[x + BORDER_PIXELS, y + BORDER_PIXELS] = 0
    return bitmap


qr = adafruit_miniqr.QRCode(qr_type=3, error_correct=adafruit_miniqr.L)
qr.add_data(b"https://www.adafruit.com/circuitpython")
qr.make()

# generate the 1-pixel-per-bit bitmap
qr_bitmap = bitmap_QR(qr.matrix)
# We'll draw with a classic black/white palette
palette = displayio.Palette(2)
palette[0] = 0xFFFFFF
palette[1] = 0x000000
# we'll scale the QR code as big as the display can handle
scale = min(
    display.width // qr_bitmap.width, display.height // qr_bitmap.height
)

# then center it!
pos_x = int(((display.width / scale) - qr_bitmap.width) / 2)
pos_y = int(((display.height / scale) - qr_bitmap.height) / 2)
qr_img = displayio.TileGrid(qr_bitmap, pixel_shader=palette, x=pos_x, y=pos_y)

splash = displayio.Group(scale=scale)
splash.append(qr_img)
display.show(splash)

# Hang out forever
while True:
    pass

cpyS3_ili9341_miniqr_input.py, further modified, you can enter text/URL in REPL console to generate QR Code.
"""
ESP32-S3/CircuitPython exercise to generate QR Code,
display on TFT.

Tested on ESP32-S3-DevKitC-1/CircuitPython 7.3.2
with 2.4" 320x240 ILI9341 SPI TFT

libs need:
- adafruit_miniqr.mpy
- adafruit_ili9341.mpy
"""

import board
import displayio
import adafruit_miniqr
import adafruit_ili9341
import busio

# Release any resources currently in use for the displays
displayio.release_displays()

#===init display ======================
disp_width = 320
disp_height = 240

disp_cs  = board.IO4
disp_res = board.IO5
disp_dc  = board.IO6

disp_mosi = board.IO7
disp_clk = board.IO15
disp_spi = busio.SPI(clock=disp_clk,
                     MOSI=disp_mosi)

display_bus = displayio.FourWire(
    disp_spi,
    command=disp_dc,
    chip_select=disp_cs,
    reset=disp_res
)

display = adafruit_ili9341.ILI9341(display_bus,
                                   width=disp_width,
                                   height=disp_height)
#=======================================

def bitmap_QR(matrix):
    # monochome (2 color) palette
    BORDER_PIXELS = 2

    # bitmap the size of the screen, monochrome (2 colors)
    bitmap = displayio.Bitmap(
        matrix.width + 2 * BORDER_PIXELS, matrix.height + 2 * BORDER_PIXELS, 2
    )
    # raster the QR code
    for y in range(matrix.height):  # each scanline in the height
        for x in range(matrix.width):
            if matrix[x, y]:
                bitmap[x + BORDER_PIXELS, y + BORDER_PIXELS] = 1
            else:
                bitmap[x + BORDER_PIXELS, y + BORDER_PIXELS] = 0
    return bitmap

def generate_qr(btogen):
    qr = adafruit_miniqr.QRCode(qr_type=3,
                                error_correct=adafruit_miniqr.L)
    qr.add_data(btogen)
    qr.make()
    
    # generate the 1-pixel-per-bit bitmap
    qr_bitmap = bitmap_QR(qr.matrix)
    # We'll draw with a classic black/white palette
    
    # we'll scale the QR code as big as the display can handle
    scale = min(display.width // qr_bitmap.width,
                display.height // qr_bitmap.height
                )
    
    pos_x = int(((display.width / scale) - qr_bitmap.width) / 2)
    pos_y = int(((display.height / scale) - qr_bitmap.height) / 2)
    return([qr_bitmap,
            pos_x,
            pos_y,
            scale])


palette = displayio.Palette(2)
palette[0] = 0xFFFFFF
palette[1] = 0x000000
    
qr = generate_qr(b"https://coxxect.blogspot.com/")

# then center it!
qr_img = displayio.TileGrid(qr[0],
                            pixel_shader=palette,
                            x=qr[1], y=qr[2])

splash = displayio.Group(scale=qr[3])
splash.append(qr_img)
display.show(splash)

"""
Examples:
https://coxxect.blogspot.com/
https://twitter.com/KcCoxxect
https://bit.ly/3bJh2RQ
"""

while True:
    user_input = input("Enter something:")
    # note: input() is a blocking function
    # it will not return untill user press "ENTER"
    if user_input == "":
        print("~ bye ~")
        break
    else:
        b_user_input = bytes(user_input, 'utf-8')
        qr = generate_qr(b_user_input)
        qr_img.bitmap = qr[0]
        qr_img.x = qr[1]
        qr_img.y = qr[2]
        splash.scale = qr[3]



Comments

Popular posts from this blog

480x320 TFT/ILI9488 SPI wih EP32C3 (arduino-esp32) using Arduino_GFX Library

my dev.tools - FNIRSI 2C23T 3-in-1 Dual Channel Oscilloscope/Multimeter/Signal Generator