Thursday, March 31, 2022

Raspberry Pi Pico/MicroPython generate QR Code and display on SSD1306 I2C OLED

Run on Raspberry Pi Pico/MicroPython, to generate QR Code, and display on SSD1306 128x64 I2C OLED.


I2C(0) is used to connect to SSD1306 I2C, scl=9 and sda=8.

For SSD1306 driver, visit https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py to download ssd1306.py, save to Raspberry Pi Pico driver.

For QR Code, JASchilz/uQR is used. Download uQR.py and save to Raspberry Pi Pico driver.


mpyPico_i2c.py, simple verify I2C(0) pins and connection to SSD1306 I2C OLED.
import uos
import usys

print("====================================================")
print(usys.implementation[0],
      str(usys.implementation[1][0]) + "." +
      str(usys.implementation[1][1]) + "." +
      str(usys.implementation[1][2]))
print(uos.uname()[3])
print("run on", uos.uname()[4])
print("====================================================")

i2c0 = machine.I2C(0)
print(i2c0)
print("Available i2c devices: "+ str(i2c0.scan()))

print("~ bye ~")

mpyPico_ssd1306.py, simple test program for SSD1306 I2C OLED.
"""
Run on Raspbery Pi Pico/MicroPython
display on ssd1306 I2C OLED

connec ssd1306 using I2C(0)
scl=9
sda=8

- Libs needed:

ssd1306 library
https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py
"""
import uos 
import usys
from ssd1306 import SSD1306_I2C

print("====================================================")
print(usys.implementation[0],
      str(usys.implementation[1][0]) + "." +
      str(usys.implementation[1][1]) + "." +
      str(usys.implementation[1][2]))
print(uos.uname()[3])
print("run on", uos.uname()[4])
print("====================================================")

i2c0 = machine.I2C(0)
print(i2c0)
print("Available i2c devices: "+ str(i2c0.scan()))

WIDTH = 128
HEIGHT = 64

oled = SSD1306_I2C(WIDTH, HEIGHT, i2c0)
oled.fill(0)

oled.text(usys.implementation[0], 0, 0)

strVersion = str(usys.implementation[1][0]) + "." + \
             str(usys.implementation[1][1]) + "." + \
             str(usys.implementation[1][2])
oled.text(strVersion, 0, 10)
oled.text(uos.uname()[3], 0, 20)
oled.text(uos.uname()[4], 0, 40)
oled.show()

mpyPico_ssd1306_uQR.py, generate QR Code using uQR.py, and display on SSD1306 I2C OLED.
"""
Run on Raspbery Pi Pico/MicroPython
to generate QR code using uQR,
and display on ssd1306 I2C OLED

- Libs needed:

ssd1306 library
https://github.com/micropython/micropython/blob/master/drivers/
display/ssd1306.py

JASchilz/uQR:
https://github.com/JASchilz/uQR

remark:
in the original example on uQR to display on ssd1306, scale of 2 is used.
It's found:
- If the data is too long, the small 128x64 OLED cannot display the whole matrix.
- In my test using my phone, scale of 1 is more easy to recognize.
Such that I use scale of 1 inside the loop to generate  qr code.
"""
from uos import uname
from usys import implementation
from machine import I2C
from time import sleep
from ssd1306 import SSD1306_I2C
from uQR import QRCode

print("====================================================")
print(implementation[0],
      str(implementation[1][0]) + "." +
      str(implementation[1][1]) + "." +
      str(implementation[1][2]))
print(uname()[3])
print("run on", uname()[4])
print("====================================================")

i2c0 = I2C(0)
print(i2c0)
print("Available i2c devices: "+ str(i2c0.scan()))

WIDTH = 128
HEIGHT = 64

oled = SSD1306_I2C(WIDTH, HEIGHT, i2c0)
oled.fill(0)

oled.text("RPi Pico", 0, 0)
oled.text("MicroPython", 0, 10)
oled.text("OLED(ssd1306)", 0, 20)
oled.text("uQR exercise", 0, 40)
oled.show()

sleep(5)
qr = QRCode()

qr.add_data("uQR example")
matrix = qr.get_matrix()
print("version:", qr.version)
print("len of matrix", len(matrix))

oled.fill(1)
for y in range(len(matrix)*2):                   # Scaling the bitmap by 2
    for x in range(len(matrix[0])*2):            # because my screen is tiny.
        value = not matrix[int(y/2)][int(x/2)]   # Inverting the values because
        oled.pixel(x, y, value)                  # black is `True` in the matrix.
oled.show()

while True:
    userinput = input("\nEnter something: ")
    if userinput == "":
        break
    print(userinput)
    qr.clear()
    qr.add_data(userinput)
    matrix = qr.get_matrix()
    print("version:", qr.version)
    print("len of matrix", len(matrix))
    
    oled.fill(1)
    scale = 1
    for y in range(len(matrix)*scale): 
        for x in range(len(matrix[0])*scale): 
            value = not matrix[int(y/scale)][int(x/scale)]
            oled.pixel(x, y, value)
    oled.show()
    
print("~ bye ~")

mpyPico_simpletest_uQR.py, generate QR Code and display on REPL.
"""
Run on Raspbery Pi Pico/MicroPython
to generate QR code using uQR,
and display on screen

- Libs needed:

JASchilz/uQR:
https://github.com/JASchilz/uQR

"""
from uos import uname
from usys import implementation
from usys import stdout

from uQR import QRCode

print("====================================================")
print(implementation[0],
      str(implementation[1][0]) + "." +
      str(implementation[1][1]) + "." +
      str(implementation[1][2]))
print(uname()[3])
print("run on", uname()[4])
print("====================================================")

# For drawing filled rectangles to the console:
stdout = stdout
WHITE = "\x1b[1;47m  \x1b[40m"
BLACK = "  "
NORMAL = '\033[1;37;0m'

def print_QR(uqr):

    qr_matrix = uqr.get_matrix()
    
    print("version:", uqr.version)
    qr_height = len(qr_matrix)
    qr_width = len(qr_matrix[0])
    print("qr_height:  ", qr_height)
    print("qr_width:   ", qr_width)

    for _ in range(4):
        for _ in range(qr_width + 8): #margin on top
            stdout.write(WHITE)
        print()
    for y in range(qr_height):
        stdout.write(WHITE * 4)       #margin on right
        for x in range(len(matrix[0])):
            value = qr_matrix[int(y)][int(x)]
            if value == True:
                stdout.write(BLACK)
            else:
                stdout.write(WHITE)
        stdout.write(WHITE * 4)        #margin on left
        print()
    for _ in range(4):
        for _ in range(qr_width + 8):  #margin on bottom
            stdout.write(WHITE)
        print()
    print(NORMAL)
        
qr = QRCode()

qr.add_data("uQR example")
matrix = qr.get_matrix()

print_QR(qr)

while True:
    userinput = input("\nEnter something: ")
    if userinput == "":
        break
    print(userinput)
    qr.clear()
    qr.add_data(userinput)
    matrix = qr.get_matrix()
    
    print_QR(qr)


print("~ bye ~")
More exercise for Raspberry Pi Pico

No comments: