{"id":8218,"date":"2013-01-25T08:02:25","date_gmt":"2013-01-25T13:02:25","guid":{"rendered":"http:\/\/scruss.com\/blog\/?p=8218"},"modified":"2013-01-31T21:26:38","modified_gmt":"2013-02-01T02:26:38","slug":"qrclock-the-demo-reel","status":"publish","type":"post","link":"https:\/\/scruss.com\/blog\/2013\/01\/25\/qrclock-the-demo-reel\/","title":{"rendered":"qrclock, the demo reel"},"content":{"rendered":"<p><a href=\"http:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2013\/01\/c012f97a6b4111e2a8b922000a1f8ac2_7.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-8242\" alt=\"classy cable for the Quite Rubbish clock\" src=\"http:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2013\/01\/c012f97a6b4111e2a8b922000a1f8ac2_7-320x320.jpg\" width=\"320\" height=\"320\" srcset=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2013\/01\/c012f97a6b4111e2a8b922000a1f8ac2_7-320x320.jpg 320w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2013\/01\/c012f97a6b4111e2a8b922000a1f8ac2_7-160x160.jpg 160w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2013\/01\/c012f97a6b4111e2a8b922000a1f8ac2_7-300x300.jpg 300w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2013\/01\/c012f97a6b4111e2a8b922000a1f8ac2_7-120x120.jpg 120w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2013\/01\/c012f97a6b4111e2a8b922000a1f8ac2_7.jpg 612w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><\/a><\/p>\n<p>The <a href=\"http:\/\/www.youtube.com\/watch?v=PyvJUN5JRkM\">video<\/a> of the <a href=\"http:\/\/scruss.com\/blog\/2013\/01\/19\/the-quite-rubbish-clock\/\">Quite Rubbish Clock<\/a> isn&#8217;t running the same code that&#8217;s in the listing. Here it is, showing off some of the handy code that&#8217;s in bgreat&#8217;s nokiaSPI Python class:<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\n#!\/usr\/bin\/python\r\n# -*- coding: utf-8 -*-\r\n# qrmovie\r\n\r\nimport time\r\n# need to use git:\/\/github.com\/mozillazg\/python-qrcode.git\r\nimport qrcode\r\nfrom PIL import Image, ImageFont\r\nimport ImageOps\r\n# uses bgreat's SPI code; see\r\n# raspberrypi.org\/phpBB3\/viewtopic.php?f=32&amp;t=9814&amp;p=262274&amp;hilit=nokia#p261925\r\nimport nokiaSPI\r\n\r\nnoki = nokiaSPI.NokiaSPI()\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 # create display device\r\nqr = qrcode.QRCode(version=1,\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 # V.1 QR Code: 21x21 px\r\nerror_correction=qrcode.constants.ERROR_CORRECT_M,\r\nbox_size=2, border=1)\r\nbg = Image.new('1', (84, 48))\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 # blank (black) image background\r\n\r\n# intro\r\nnoki.cls()\r\nnoki.led(0)\r\ntime.sleep(3)\r\nfor i in range(0,769,32):\r\n    noki.led(i)\r\n    time.sleep(0.04)\r\n\r\n# display is 14 columns by 8 rows\r\nnoki.centre_word(1, 'scruss.com')\r\nnoki.centre_word(3, 'presents')\r\ntime.sleep(3)\r\nnoki.cls()\r\nnoki.centre_word(1, 'qrclock')\r\nnoki.centre_word(2, 'the')\r\nnoki.gotorc(3,3)\r\nnoki.text(&quot;&#x5B;Q]uite&quot;)\r\nnoki.gotorc(4,3)\r\nnoki.text(&quot;&#x5B;R]ubbish&quot;)\r\nnoki.gotorc(5,3)\r\nnoki.text(&quot; Clock&quot;)\r\ntime.sleep(3)\r\n\r\nelapsed=0\r\nstart_time = time.time()\r\nwhile (elapsed&lt;12):\r\n    qr.clear()\r\n    newbg = bg.copy()\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 # copy blank background\r\n    s = time.strftime('%Y-%m-%d %H:%M:%S')\r\n    qr.add_data(s)\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 # make QR Code of YYYY-MM-DD HH:MM:SS\r\n    qr.make()\r\n    qrim = qr.make_image()\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 # convert qrcode object to PIL image\r\n    qrim = qrim.convert('L')\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 # make greyscale\r\n    qrim = ImageOps.invert(qrim)\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 # invert colours: B-&gt;W and W-&gt;B\r\n    qrim = qrim.convert('1')\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 # convert back to 1-bit\r\n    newbg.paste(qrim, (18, 0))\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 # paste QR Code into blank background\r\n    noki.show_image(newbg)\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 # display code on LCD\r\n    time.sleep(0.4)\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 # pause before next display\r\n    elapsed = time.time() - start_time\r\n\r\nnoki.cls()\r\nnoki.centre_word(1, 'for')\r\nnoki.centre_word(2, 'more')\r\nnoki.centre_word(3, 'details')\r\ntime.sleep(3)\r\nnoki.cls()\r\nnoki.load_bitmap(&quot;blogpost-nokia.bmp&quot;, True)\r\ntime.sleep(7)\r\nnoki.cls()\r\nnoki.centre_word(3, 'fin')\r\nnoki.centre_word(5, 'scruss, 2013')\r\ntime.sleep(1)\r\nfor i in range(768,-1,-32):\r\n    noki.led(i)\r\n    time.sleep(0.05)\r\ntime.sleep(1)\r\nnoki.cls()\r\n<\/pre>\n<p>(This source, plus nokiaSPI class: <a href=\"http:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2013\/01\/qrclock-movie.zip\">qrclock-movie.zip<\/a>)<\/p>\n<p>Lines 43-58 show off the QR clock for a maximum of 12 seconds. Any more, and you&#8217;d get really bored.<\/p>\n<p>The screen handling functions I used are:<\/p>\n<ul>\n<li><strong>cls<\/strong>() \u00e2\u20ac\u201d Clears the screen.<\/li>\n<li><strong>led<\/strong>(<em>brightness<\/em>) \u00e2\u20ac\u201d sets the backlight to <em>brightness<\/em>. For me, full brightness is at 768. A value of zero turns the backlight off. If you don&#8217;t have the screen LED connected to one of the Raspberry Pi&#8217;s PWM pin, this will either be full on (for any <em>brightness<\/em> &gt;= 1), or off, for <em>brightness<\/em>=0. This is used to fade up the screen in lines 24-26, and fade it down far too theatrically in lines 72-74.<\/li>\n<li><strong>show_image<\/strong>(<em>PILImage<\/em>) \u00e2\u20ac\u201d display a single bit depth black and white Python Imaging Library object PILImage. This can be no larger than 84\u00c3\u201448 pixels.<\/li>\n<li><strong>load_bitmap<\/strong>(<em>file<\/em>, <em>Invert<\/em>) \u00e2\u20ac\u201d load a single bit depth black and white BMP <em>file<\/em> of maximum size 48\u00c3\u201484. If <em>Invert<\/em> is true, keep the colours as they are, otherwise swap black and white to make a negative image. nokiSPI flips images by 90\u00c2\u00b0, so the image I loaded to show the URL of the blog post looks like this:<br \/>\n<img decoding=\"async\" class=\"alignnone size-large wp-image-8223\" alt=\"blogpost-nokia\" src=\"http:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2013\/01\/blogpost-nokia.bmp\" \/><br \/>\n(I know, I could have generated this in code, but I&#8217;d already made the image using <a href=\"http:\/\/fukuchi.org\/works\/qrencode\/index.html.en\">qrencode.<\/a> I couldn&#8217;t be bothered working out the image size and offsets.)<\/li>\n<\/ul>\n<p>The text handling functions I used are:<\/p>\n<ul>\n<li><strong>gotorc<\/strong>(<em>row<\/em>, <em>column<\/em>) \u00e2\u20ac\u201d move the text cursor to row, column. The screen only has 14 columns by 8 rows if you use the standard 6\u00c3\u20146 pixel font, so keep your text short to avoid disappointment.<\/li>\n<li><strong>text<\/strong>(<em>text<\/em>) \u00e2\u20ac\u201d write <em>text<\/em> at the current cursor position.<\/li>\n<li><strong>centre_word<\/strong>(<em>row<\/em>, <em>text<\/em>) \u00e2\u20ac\u201d write <em>text<\/em> centred in row <em>row<\/em>. Since the text rows are a maximum of 14 columns, text with an odd number of characters will appear slightly off-centre.<\/li>\n<\/ul>\n<p>There are many more functions in the nokiaSPI class; watch the <a href=\"http:\/\/www.youtube.com\/watch?v=kBHRh9dZXm0\">demo<\/a>, have a dig through the source and see what you can use.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The video of the Quite Rubbish Clock isn&#8217;t running the same code that&#8217;s in the listing. Here it is, showing off some of the handy code that&#8217;s in bgreat&#8217;s nokiaSPI Python class: #!\/usr\/bin\/python # -*- coding: utf-8 -*- # qrmovie import time # need to use git:\/\/github.com\/mozillazg\/python-qrcode.git import qrcode from PIL import Image, ImageFont import [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[7],"tags":[2612,2613,2540,2609,2510,2617,790],"class_list":["post-8218","post","type-post","status-publish","format-standard","hentry","category-computers-suck","tag-lcd","tag-nokia","tag-python","tag-qrcode","tag-raspberrypi","tag-spi","tag-youtube"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/pQNZZ-28y","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/8218","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/comments?post=8218"}],"version-history":[{"count":18,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/8218\/revisions"}],"predecessor-version":[{"id":8255,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/8218\/revisions\/8255"}],"wp:attachment":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/media?parent=8218"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/categories?post=8218"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/tags?post=8218"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}