Libraries

We'll need to make sure we have these libraries installed. (Check out this link on installing libraries if needed.)

  • adafruit_bitmap_font
  • adafruit_bus_device
  • adafruit_display_text
  • adafruit_esp32spi
  • adafruit_io
  • adafruit_matrixportal
  • adafruit_requests.mpy
  • neopixel.mpy

Connect to the Internet

Once you have CircuitPython setup and libraries installed we can get your board connected to the Internet. The process for connecting can be found here.

Text Editor

Adafruit recommends using the Mu editor for editing your CircuitPython code. You can get more info in this guide.

Alternatively, you can use any text editor that saves simple text files.

Code

Click the Download: Zip File link below in the code window to get a zip file with all the files needed for the project. Copy code.py from the zip file and place it on the CIRCUITPY drive.

# SPDX-FileCopyrightText: 2020 John Park for Adafruit Industries
#
# SPDX-License-Identifier: MIT

# Quote board matrix display
# uses AdafruitIO to serve up a quote text feed and color feed
# random quotes are displayed, updates periodically to look for new quotes
# avoids repeating the same quote twice in a row

import time
import random
import board
import terminalio
from adafruit_matrixportal.matrixportal import MatrixPortal

# --- Display setup ---
matrixportal = MatrixPortal(status_neopixel=board.NEOPIXEL, debug=True)

# Create a new label with the color and text selected
matrixportal.add_text(
    text_font=terminalio.FONT,
    text_position=(0, (matrixportal.graphics.display.height // 2) - 1),
    scrolling=True,
)

# Static 'Connecting' Text
matrixportal.add_text(
    text_font=terminalio.FONT,
    text_position=(2, (matrixportal.graphics.display.height // 2) - 1),
)

QUOTES_FEED = "sign-quotes.signtext"
COLORS_FEED = "sign-quotes.signcolor"
SCROLL_DELAY = 0.02
UPDATE_DELAY = 600

quotes = []
colors = []
last_color = None
last_quote = None


def update_data():
    print("Updating data from Adafruit IO")
    matrixportal.set_text("Connecting", 1)

    try:
        quotes_data = matrixportal.get_io_data(QUOTES_FEED)
        quotes.clear()
        for json_data in quotes_data:
            quotes.append(matrixportal.network.json_traverse(json_data, ["value"]))
        print(quotes)
    # pylint: disable=broad-except
    except Exception as error:
        print(error)

    try:
        color_data = matrixportal.get_io_data(COLORS_FEED)
        colors.clear()
        for json_data in color_data:
            colors.append(matrixportal.network.json_traverse(json_data, ["value"]))
        print(colors)
    # pylint: disable=broad-except
    except Exception as error:
        print(error)

    if not quotes or not colors:
        raise RuntimeError("Please add at least one quote and color to your feeds")
    matrixportal.set_text(" ", 1)


update_data()
last_update = time.monotonic()
matrixportal.set_text(" ", 1)
quote_index = None
color_index = None

while True:
    # Choose a random quote from quotes
    if len(quotes) > 1 and last_quote is not None:
        while quote_index == last_quote:
            quote_index = random.randrange(0, len(quotes))
    else:
        quote_index = random.randrange(0, len(quotes))
    last_quote = quote_index

    # Choose a random color from colors
    if len(colors) > 1 and last_color is not None:
        while color_index == last_color:
            color_index = random.randrange(0, len(colors))
    else:
        color_index = random.randrange(0, len(colors))
    last_color = color_index

    # Set the quote text
    matrixportal.set_text(quotes[quote_index])

    # Set the text color
    matrixportal.set_text_color(colors[color_index])

    # Scroll it
    matrixportal.scroll_text(SCROLL_DELAY)

    if time.monotonic() > last_update + UPDATE_DELAY:
        update_data()
        last_update = time.monotonic()

Adafruit IO Setup

Our project will use Adafruit IO to serve up a feed of quotes and colors. Adafruit IO is absolutely free to use, but you'll need to log in with your Adafruit account to use it. If you don't already have an Adafruit login, create one here.

If you haven't used Adafruit IO before, check out this guide for more info.

Once you have logged into your account, there are two pieces of information you'll need to place in your secrets.py file: Adafruit IO username, and Adafruit IO key. Head to io.adafruit.com and simply click the View AIO Key link on the left hand side of the Adafruit IO page to get this information.

Then, add them to the secrets.py file like this:

secrets = {
    'ssid' : 'your_wifi_ssid',
    'password' : 'your_wifi_password',
    'aio_username' : '_your_aio_username_',
    'aio_key' : '_your_big_huge_super_long_aio_key_'
}

Problems Getting Quotes

If you have any problems getting the data to display correctly, check that the secrets.py file has the information noted above.

Adafruit IO Group, Feeds, Dashboard

Next, we'll create the necessary Adafruit IO Group, Feeds, and Dashboard to host our quotes and colors.

First, if you're new to Adafruit IO, take a look at this excellent guide on getting started.

Next, we'll create a Group that will contain our two Feeds.

Group Creation

In the Feeds screen click on the Actions menu and then pick Create a New Group from the dropdown menu.

Name the Group as Sign Quotes, then click Create.

Feed Creation

In the Feeds screen click on the Actions menu and then pick Create a New Feed from the dropdown menu.

Name this feed signcolor, and select Sign Quotes from the Add to groups field, then click Create.

Repeat this process a second time to make a new Feed called signtext.

Dashboard Creation

Now that we have the two feeds we need, let's create a Dashboard with a couple of UI block elements that will make it easy to add data points to our two feeds.

From the Dashboards page, click the Actions dropdown menu and select Create a New Dashboard.

Name the Dashboard as Quotes and then click Create.

Click on the create a new block + sign in the Dashboard page, this will present you with a number of UI element block options.

Pick the Text block.

From the Chose feed pop-up window that appears, chose the signtext feed, then click Next step.

In the Block settings popup window, give the block the title Text quote, then click Update block.

Repeat this process to create a Color picker block, assigning it to the signcolor feed.

Create Quotes

Now, you can pick a few different colors with the color picker to add to your arsenal of sign text colors.

Type in text in the text block to add quotes to your feed.

If you ever decide you don't want one of the colors or quotes, simply head to the relevant feed and click the red 'x' to remove a data point!

What the Code Does

Here's a look at how the code works.

First, it loads a few libraries:

import time
import random
import board
import terminalio
from adafruit_matrixportal.matrixportal import MatrixPortal

Next, the Display is set up using the matrixportal object. We also create text label objects:

# --- Display setup ---
matrixportal = MatrixPortal(status_neopixel=board.NEOPIXEL, debug=True)

# Create a new label with the color and text selected
matrixportal.add_text(
    text_font=terminalio.FONT,
    text_position=(0, (matrixportal.graphics.display.height // 2) - 1),
    scrolling=True,
)

# Static 'Connecting' Text
matrixportal.add_text(
    text_font=terminalio.FONT,
    text_position=(2, (matrixportal.graphics.display.height // 2) - 1),
)

Feed Variables

In order to use the feed data, we need a couple of variables to help traverse the AIO json data.

We also create variables for the scroll speed and update time.

QUOTES_FEED = "sign-quotes.signtext"
COLORS_FEED = "sign-quotes.signcolor"
SCROLL_DELAY = 0.02
UPDATE_DELAY = 600

quotes = []
colors = []
last_color = None
last_quote = None

Update Data

The update_data() function is created to handle the quote feed and color feed data queries. This will be the key function that is run each time the code checks for new quotes and colors.

def update_data():
    print("Updating data from Adafruit IO")
    matrixportal.set_text("Connecting", 1)

    try:
        quotes_data = matrixportal.get_io_data(QUOTES_FEED)
        quotes.clear()
        for json_data in quotes_data:
            quotes.append(matrixportal.network.json_traverse(json_data, ["value"]))
        print(quotes)
    # pylint: disable=broad-except
    except Exception as error:
        print(error)

    try:
        color_data = matrixportal.get_io_data(COLORS_FEED)
        colors.clear()
        for json_data in color_data:
            colors.append(matrixportal.network.json_traverse(json_data, ["value"]))
        print(colors)
    # pylint: disable=broad-except
    except Exception as error:
        print(error)

    if not quotes or not colors:
        raise "Please add at least one quote and color to your feeds"
    matrixportal.set_text(" ", 1)

This is run as soon as the function has been defined, so that we now have a list of quotes and colors to work with.

Main Loop

In the main loop of the code, a random quote is selected from the list that has been returned by the update_data() function. This includes a while loop that ensures we don't get the same quote or color twice in a row!

# Choose a random quote from quotes
    if len(quotes) > 1 and last_quote is not None:
        while quote_index == last_quote:
            quote_index = random.randrange(0, len(quotes))
    else:
        quote_index = random.randrange(0, len(quotes))
    last_quote = quote_index

    # Choose a random color from colors
    if len(colors) > 1 and last_color is not None:
        while color_index == last_color:
            color_index = random.randrange(0, len(colors))
    else:
        color_index = random.randrange(0, len(colors))
    last_color = color_index

Display the Quote

Now, the randomly selected quote is displayed using the matrixportal.set_text() and matrixportal.set_text_color() commands, and the text is scrolled using matrixportal.scroll_text().

# Set the quote text
    matrixportal.set_text(quotes[quote_index])

    # Set the text color
    matrixportal.set_text_color(colors[color_index])

    # Scroll it
    matrixportal.scroll_text(SCROLL_DELAY)

Update Time

After ten minutes, the code will go and fetch the quotes and colors from the AIO feeds anew, in case anything has changed.

if time.monotonic() > last_update + UPDATE_DELAY:
        update_data()
        last_update = time.monotonic()

This guide was first published on Sep 16, 2020. It was last updated on Mar 28, 2024.

This page (Code the Quote Board) was last updated on Mar 28, 2024.

Text editor powered by tinymce.