{"id":16732,"date":"2021-06-02T22:18:14","date_gmt":"2021-06-03T02:18:14","guid":{"rendered":"https:\/\/scruss.com\/blog\/?p=16732"},"modified":"2021-06-02T22:18:17","modified_gmt":"2021-06-03T02:18:17","slug":"cardkb-mini-keyboard-with-micropython","status":"publish","type":"post","link":"https:\/\/scruss.com\/blog\/2021\/06\/02\/cardkb-mini-keyboard-with-micropython\/","title":{"rendered":"CardKB mini keyboard with MicroPython"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2021\/06\/CARDKB_1200x1200really-1024x1024.jpg\" alt=\"small computer screen with text\n*** APPALLING TYPEWRITER ***\n** Type stuff, Esc to end **\n\nthen further down: &quot;hello I am smol keeb&quot;\" class=\"wp-image-16736\" srcset=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2021\/06\/CARDKB_1200x1200really-1024x1024.jpg 1024w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2021\/06\/CARDKB_1200x1200really-320x320.jpg 320w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2021\/06\/CARDKB_1200x1200really-160x160.jpg 160w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2021\/06\/CARDKB_1200x1200really-768x768.jpg 768w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2021\/06\/CARDKB_1200x1200really-120x120.jpg 120w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2021\/06\/CARDKB_1200x1200really.jpg 1200w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>it really is the size of a credit card<br>(running with a SeeedStudio <a href=\"https:\/\/wiki.seeedstudio.com\/Wio-Terminal-Getting-Started\/\">Wio Terminal<\/a>)<\/figcaption><\/figure>\n\n\n\n<p>I got one of these <a href=\"https:\/\/shop.m5stack.com\/products\/cardkb-mini-keyboard\">CardKB Mini Keyboard<\/a>s to see if I could use it for small interactives with MicroPython devices. It&#8217;s very small, and objectively not great as a mass data entry tool. &#8220;<em>Better than a Pocket C.H.I.P. keyboard<\/em>&#8221; is how I&#8217;d describe the feel. It&#8217;s also pretty reliable.<\/p>\n\n\n\n<p>It&#8217;s got an I\u00c2\u00b2C <a href=\"https:\/\/wiki.seeedstudio.com\/Grove_System\/\">Grove<\/a> connector, and its brains are an ATMega chip just like an Arduino. It&#8217;s strictly an ASCII keyboard: that is, it sends the 8-bit ASCII code of the key combination you pressed. It doesn&#8217;t send scan codes like a PC keyboard. The driver source is in the <a href=\"https:\/\/docs.m5stack.com\/en\/unit\/cardkb?id=description\">CardKB m5-docs<\/a>, so if you really felt ambitious you could write a scan code-like firmware for yourself.<\/p>\n\n\n\n<p>The device appears at I\u00c2\u00b2C peripheral address 95, and returns a single byte when polled. That byte&#8217;s either 0 if no key was pressed, or the character code of what was pressed. The <kbd>Esc<\/kbd> key returns chr(27), and <kbd>Enter<\/kbd> returns CR. If you poll the keyboard too fast it seems to lose the plot a little, so a tiny delay seems to help<\/p>\n\n\n\n<p>Here&#8217;s a small demo for MicroPython that acts as the world&#8217;s worst typewriter:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n# M5Stack CardKB tiny keyboard - scruss, 2021-06\n# MicroPython - Raspberry Pi Pico\n\nfrom machine import Pin, I2C\nfrom time import sleep_ms\n\ni2c = I2C(1, scl=Pin(7), sda=Pin(6))\ncardkb = i2c.scan()&#x5B;0]  # should return 95\nif cardkb != 95:\n    print(&quot;!!! Check I2C config: &quot; + str(i2c))\n    print(&quot;!!! CardKB not found. I2C device&quot;, cardkb,\n          &quot;found instead.&quot;)\n    exit(1)\n\nESC = chr(27)\nNUL = &#039;\\x00&#039;\nCR = &quot;\\r&quot;\nLF = &quot;\\n&quot;\nc = &#039;&#039;\n\nprint(&quot;*** APPALLING TYPEWRITER ***&quot;)\nprint(&quot;** Type stuff, Esc to end **&quot;)\n\nwhile (c != ESC):\n    # returns NUL char if no character read\n    c = i2c.readfrom(cardkb, 1).decode()\n    if c == CR:\n        # convert CR return key to LF\n        c = LF\n    if c != NUL or c != ESC:\n        print(c, end=&#039;&#039;)\n    sleep_ms(5)\n<\/pre><\/div>\n\n\n<p>And here&#8217;s the CircuitPython version. It has annoying tiny differences. It won&#8217;t let me use the I\u00c2\u00b2C Grove connector on the Wio Terminal for some reason, but it does work much the same:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n# M5Stack CardKB tiny keyboard - scruss, 2021-06\n# CircuitPython - SeeedStudio Wio Terminal\n# NB: can&#039;t use Grove connector under CPY because CPY\n\nimport time\nimport board\nimport busio\n\ni2c = busio.I2C(board.SCL, board.SDA)\n\nwhile not i2c.try_lock():\n    pass\n\ncardkb = i2c.scan()&#x5B;0]  # should return 95\nif cardkb != 95:\n    print(&quot;!!! Check I2C config: &quot; + str(i2c))\n    print(&quot;!!! CardKB not found. I2C device&quot;, cardkb,\n          &quot;found instead.&quot;)\n    exit(1)\n\nESC = chr(27)\nNUL = &#039;\\x00&#039;\nCR = &quot;\\r&quot;\nLF = &quot;\\n&quot;\nc = &#039;&#039;\nb = bytearray(1)\n\n# can&#039;t really clear screen, so this will do\nfor i in range(12):\n    print()\nprint(&quot;*** APPALLING TYPEWRITER ***&quot;)\nprint(&quot;** Type stuff, Esc to end **&quot;)\nfor i in range(8):\n    print()\n\nwhile (c != ESC):\n    # returns NUL char if no character read\n    i2c.readfrom_into(cardkb, b)\n    c = b.decode()\n    if c == CR:\n        # convert CR return key to LF\n        c = LF\n    if c != NUL or c != ESC:\n        print(c, end=&#039;&#039;)\n    time.sleep(0.005)\n\n# be nice, clean up\ni2c.unlock()\n<\/pre><\/div>\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I got one of these CardKB Mini Keyboards to see if I could use it for small interactives with MicroPython devices. It&#8217;s very small, and objectively not great as a mass data entry tool. &#8220;Better than a Pocket C.H.I.P. keyboard&#8221; is how I&#8217;d describe the feel. It&#8217;s also pretty reliable. It&#8217;s got an I\u00c2\u00b2C Grove [&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":[3105,2208,3165,3094],"class_list":["post-16732","post","type-post","status-publish","format-standard","hentry","category-computers-suck","tag-circuitpython","tag-electronics","tag-keyboard","tag-micropython"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/pQNZZ-4lS","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/16732","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=16732"}],"version-history":[{"count":5,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/16732\/revisions"}],"predecessor-version":[{"id":16739,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/16732\/revisions\/16739"}],"wp:attachment":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/media?parent=16732"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/categories?post=16732"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/tags?post=16732"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}