Code PyPortal with CircuitPython

Project Specific Libraries

Previously, we prepped the PyPortal with all of the libraries most commonly used for PyPortal projects. If you want to use the bare minimum set for this project, this is it:

  • adafruit_bitmap_font
  • adafruit_bus_device
  • adafruit_display_text
  • adafruit_esp32spi
  • adafruit_miniqr.mpy
  • adafruit_pyportal.mpy
  • adafruit_sdcard.mpy
  • adafruit_touchscreen.mpy
  • neopixel.mpy

CircuitPython Code

In the embedded code element below, click on the Download: Project Zip link, and save the .zip archive file to your computer.

Then, uncompress the .zip file, it will unpack to a folder named PyPortal_Quotes.

Copy the contents of the PyPortal_Quotes directory to your PyPortal's CIRCUITPY drive, and then be sure to rename the quote.py file to code.py so it will automatically run when the PyPortal re-starts.

import time
import board
from adafruit_pyportal import PyPortal

# Set up where we'll be fetching data from
DATA_SOURCE = "https://www.adafruit.com/api/quotes.php"
QUOTE_LOCATION = [0, 'text']
AUTHOR_LOCATION = [0, 'author']

# the current working directory (where this file is)
cwd = ("/"+__file__).rsplit('/', 1)[0]
pyportal = PyPortal(url=DATA_SOURCE,
                    json_path=(QUOTE_LOCATION, AUTHOR_LOCATION),
                    status_neopixel=board.NEOPIXEL,
                    default_bg=cwd+"/quote_background.bmp",
                    text_font=cwd+"/fonts/Arial-ItalicMT-17.bdf",
                    text_position=((20, 120),  # quote location
                                   (5, 210)), # author location
                    text_color=(0xFFFFFF,  # quote text color
                                0x8080FF), # author text color
                    text_wrap=(35, # characters to wrap for quote
                               0), # no wrap for author
                    text_maxlen=(180, 30), # max text size for quote & author
                   )

# speed up projects with lots of text by preloading the font!
pyportal.preload_font()

while True:
    try:
        value = pyportal.fetch()
        print("Response is", value)
    except (ValueError, RuntimeError) as e:
        print("Some error occured, retrying! -", e)
    time.sleep(60)
If you run into any errors, such as "ImportError: no module named `adafruit_display_text.label`" be sure to update your libraries to the latest release bundle!

This is what the final contents of the CIRCUITPY drive will look like:

How It Works

The PyPortal Quote Board is doing a couple of nifty things to deliver your delightful quote-y experience!

Background

First, it displays a bitmap graphic as the screen's background. This is a 320 x 240 pixel RGB 16-bit raster graphic in .bmp format.

Font

Then, it displays a quote and the author's name as text created with bitmapped fonts to overlay on top of the background. The font used here is a bitmap font made from an oblique Arial typeface. You can learn more about converting type in this guide.

JSON

The neat part is that the text is not coming from a file on the device, but rather it is grabbed from a website!

Adafruit.com has a PHP script at the adafruit.com/api/quotes.php page. Each time it is requested, it returns a new quote from a large database of quotes.

In fact, you can run the same query the PyPortal does to see the results. Copy and paste this link: https://www.adafruit.com/api/quotes.php

into your browser and you'll see a result like this:

[
  {
    "text": "Science, my lad, is made up of mistakes, but they are mistakes which it is useful to make, because they lead little by little to the truth",
    "author": "Jules Verne"
  }
]

That result is the quote formatted as a JSON (JavaScript Object Notation) array. It is comprised of a single element with two keys: text and author.

  • The value of the text key is Science, my lad, is made up of mistakes, but they are mistakes which it is useful to make, because they lead little by little to the truth
  • The value of the author key is Jules Verne

Since this JSON object has a consistent way to return the results to us, the code we're running on the PyPortal can easily parse the data and display it!

You can see how it's done in this part of code.py:

Download: file
# Set up where we'll be fetching data from
DATA_SOURCE = "https://www.adafruit.com/api/quotes.php"
QUOTE_LOCATION = [0, 'text']
AUTHOR_LOCATION = [0, 'author']

Then, in the pyportal query we ask for the text and author name from that URL, and then use the text_ arguments to set the font, position, color, wrap, and maxlen of the text when it is displayed.

Download: file
pyportal = PyPortal(url=DATA_SOURCE,
                    json_path=(QUOTE_LOCATION, AUTHOR_LOCATION),
                    status_neopixel=board.NEOPIXEL,
                    default_bg=cwd+"quote_background.bmp",
                    text_font=cwd+"fonts/Arial-ItalicMT-17.bdf",
                    text_position=((20, 40),  # quote location
                                   (5, 190)), # author location
                    text_color=(0xFFFFFF,  # quote text color
                                0x8080FF), # author text color
                    text_wrap=(35, # characters to wrap for quote
                               0), # no wrap for author
                    text_maxlen=(180, 30), # max text size for quote & author
                    )

With all of this prepared, during the main loop of while True: the code will query the Adafruit quotes page for the JSON data, and display it, and then wait one minute until repeating the process.

Want your quotes to update more quickly or slowly? Simply change the number of seconds specified in the time.sleep() line.

Now, you can test out the program and once it connects to your WiFi, it'll will pull in a quote!

Next, we'll make and enclosure for the PyPortal Quote Book.

This guide was first published on Feb 27, 2019. It was last updated on Feb 27, 2019. This page (Code PyPortal with CircuitPython) was last updated on Oct 23, 2019.