computers suck

qrclock, the demo reel

classy cable for the Quite Rubbish clock

The video of the Quite Rubbish Clock isn’t running the same code that’s in the listing. Here it is, showing off some of the handy code that’s in bgreat’s nokiaSPI Python class:

# -*- coding: utf-8 -*-
# qrmovie

import time
# need to use git://
import qrcode
from PIL import Image, ImageFont
import ImageOps
# uses bgreat's SPI code; see
import nokiaSPI

noki = nokiaSPI.NokiaSPI()              # create display device
qr = qrcode.QRCode(version=1,           # V.1 QR Code: 21x21 px
box_size=2, border=1)
bg ='1', (84, 48))           # blank (black) image background

# intro
for i in range(0,769,32):

# display is 14 columns by 8 rows
noki.centre_word(1, '')
noki.centre_word(3, 'presents')
noki.centre_word(1, 'qrclock')
noki.centre_word(2, 'the')
noki.text(" Clock")

start_time = time.time()
while (elapsed<12):
    newbg = bg.copy()                   # copy blank background
    s = time.strftime('%Y-%m-%d %H:%M:%S')
    qr.add_data(s)                      # make QR Code of YYYY-MM-DD HH:MM:SS
    qrim = qr.make_image()              # convert qrcode object to PIL image
    qrim = qrim.convert('L')            # make greyscale
    qrim = ImageOps.invert(qrim)        # invert colours: B->W and W->B
    qrim = qrim.convert('1')            # convert back to 1-bit
    newbg.paste(qrim, (18, 0))          # paste QR Code into blank background
    noki.show_image(newbg)              # display code on LCD
    time.sleep(0.4)                     # pause before next display
    elapsed = time.time() - start_time

noki.centre_word(1, 'for')
noki.centre_word(2, 'more')
noki.centre_word(3, 'details')
noki.load_bitmap("blogpost-nokia.bmp", True)
noki.centre_word(3, 'fin')
noki.centre_word(5, 'scruss, 2013')
for i in range(768,-1,-32):

(This source, plus nokiaSPI class:

Lines 43-58 show off the QR clock for a maximum of 12 seconds. Any more, and you’d get really bored.

The screen handling functions I used are:

  • cls() — Clears the screen.
  • led(brightness) — sets the backlight to brightness. For me, full brightness is at 768. A value of zero turns the backlight off. If you don’t have the screen LED connected to one of the Raspberry Pi’s PWM pin, this will either be full on (for any brightness >= 1), or off, for brightness=0. This is used to fade up the screen in lines 24-26, and fade it down far too theatrically in lines 72-74.
  • show_image(PILImage) — display a single bit depth black and white Python Imaging Library object PILImage. This can be no larger than 84×48 pixels.
  • load_bitmap(file, Invert) — load a single bit depth black and white BMP file of maximum size 48×84. If Invert is true, keep the colours as they are, otherwise swap black and white to make a negative image. nokiSPI flips images by 90°, so the image I loaded to show the URL of the blog post looks like this:
    (I know, I could have generated this in code, but I’d already made the image using qrencode. I couldn’t be bothered working out the image size and offsets.)

The text handling functions I used are:

  • gotorc(row, column) — move the text cursor to row, column. The screen only has 14 columns by 8 rows if you use the standard 6×6 pixel font, so keep your text short to avoid disappointment.
  • text(text) — write text at the current cursor position.
  • centre_word(row, text) — write text centred in row row. Since the text rows are a maximum of 14 columns, text with an odd number of characters will appear slightly off-centre.

There are many more functions in the nokiaSPI class; watch the demo, have a dig through the source and see what you can use.

5 replies on “qrclock, the demo reel”

Traceback (most recent call last):
File “”, line 14, in
noki = nokiaSPI.NokiaSPI() # create display device
File “/home/pi/python-qrcode/”, line 158, in __init__[0],[1])
IOError: [Errno 2] No such file or directory

Did you enable the SPI kernel module? I haven’t touched this code in years, so maybe the kernel/codebase has moved on.

Leave a Reply

Your email address will not be published. Required fields are marked *