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: Project 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 # Scoreboard matrix display # uses AdafruitIO to set scores and team names for a scoreboard # Perfect for cornhole, ping pong, and other games import time import board import terminalio from adafruit_matrixportal.matrixportal import MatrixPortal # --- Display setup --- matrixportal = MatrixPortal(status_neopixel=board.NEOPIXEL, debug=False) RED_COLOR = 0xAA0000 BLUE_COLOR = 0x0000AA # Red Score matrixportal.add_text( text_font=terminalio.FONT, text_position=(4, int(matrixportal.graphics.display.height * 0.75) - 3), text_color=RED_COLOR, text_scale=2, ) # Blue Score matrixportal.add_text( text_font=terminalio.FONT, text_position=(36, int(matrixportal.graphics.display.height * 0.75) - 3), text_color=BLUE_COLOR, text_scale=2, ) # Red Team name matrixportal.add_text( text_font=terminalio.FONT, text_position=(4, int(matrixportal.graphics.display.height * 0.25) - 4), text_color=RED_COLOR, ) # Blue Team name matrixportal.add_text( text_font=terminalio.FONT, text_position=(36, int(matrixportal.graphics.display.height * 0.25) - 4), text_color=BLUE_COLOR, ) # Static 'Connecting' Text matrixportal.add_text( text_font=terminalio.FONT, text_position=(59, 0), ) SCORES_RED_FEED = "scores-group.red-team-score-feed" SCORES_BLUE_FEED = "scores-group.blue-team-score-feed" TEAM_RED_FEED = "scores-group.red-team-name" TEAM_BLUE_FEED = "scores-group.blue-team-name" UPDATE_DELAY = 4 matrixportal.set_text_color(RED_COLOR, 0) matrixportal.set_text_color(BLUE_COLOR, 1) def show_connecting(show): if show: matrixportal.set_text(".", 4) else: matrixportal.set_text(" ", 4) def get_last_data(feed_key): feed = matrixportal.get_io_feed(feed_key, detailed=True) value = feed["details"]["data"]["last"] if value is not None: return value["value"] return None def customize_team_names(): team_red = "Red" team_blue = "Blue" show_connecting(True) team_name = get_last_data(TEAM_RED_FEED) if team_name is not None: print("Team {} is now Team {}".format(team_red, team_name)) team_red = team_name matrixportal.set_text(team_red, 2) team_name = get_last_data(TEAM_BLUE_FEED) if team_name is not None: print("Team {} is now Team {}".format(team_blue, team_name)) team_blue = team_name matrixportal.set_text(team_blue, 3) show_connecting(False) def update_scores(): print("Updating data from Adafruit IO") show_connecting(True) score_red = get_last_data(SCORES_RED_FEED) if score_red is None: score_red = 0 matrixportal.set_text(score_red, 0) score_blue = get_last_data(SCORES_BLUE_FEED) if score_blue is None: score_blue = 0 matrixportal.set_text(score_blue, 1) show_connecting(False) customize_team_names() update_scores() last_update = time.monotonic() while True: # Set the red score text if time.monotonic() > last_update + UPDATE_DELAY: update_scores() 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 Score Data
If you have any problems getting the data to update 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 scores and team/player names.
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 four Feeds (two per player name, two per score).
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 Scores Group and 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 Blue Team Name, and select Scores Group from the Add to groups field, then click Create.
Repeat this process a second time to make a new Feed called Red Team Name.
Repeat this process two more times to create feeds named Blue Team Score Feed and Red Team Score Feed.
Dashboard Creation
Now that we have the four 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 feeds.
From the Dashboards page, click the Actions dropdown menu and select Create a New Dashboard.
Name the Dashboard as Scoreboard Dashboard. You can make a custom head image to display by checking the checkbox for Show Header Image and browsing to an image file -- you can use the one shown below if you like.
Then click Create.
Dashboard Widgets
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 Choose feed pop-up window that appears, chose the Blue Team Name 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 Slider block with a Min value of 0 and a Max value of 21 (or whatever your game calls for), assigning it to the Blue Team Score Feed feed.
Repeat the two steps from above for the Red Team Name and Red Team Score Feed.
Score a Game
Time to score a game! You will adjust those values from any web browser -- including a mobile device browser. This puts a centralized score keeping remote right in your hands while playing or officiating a game.
Start by setting the two team names, and set the scores to 0-0.
Now, any time a player or team scores, move the slider. After a few moments, the Matrix Scoreboard will update to match!
Here, the Poughkeepsie Slugs have beaten the New Haven Orcs with a final score of 21-11!
Winner stays in the game, but a new contender emerges -- the East Marion Imps have made it all the way from Long Island for the game! In the Dashboard, we'll change the name from Orcs to Imps and press Return on the keyboard (or browser simulacrum thereof), then set the sliders to 0-0.
You can press the reset button on the Matrix Portal so it will grab the new team names (these are only set at startup to keep things fast).
We're ready to start scoring the new game! Go Slugs!!
import time import board import terminalio from adafruit_matrixportal.matrixportal import MatrixPortal
Next, the Display is set up using the matrixportal
object. We also define the team colors and create text label objects for the team names and scores and static connecting text:
matrixportal = MatrixPortal(status_neopixel=board.NEOPIXEL, debug=False) RED_COLOR = 0xAA0000 BLUE_COLOR = 0x0000AA # Red Score matrixportal.add_text( text_font=terminalio.FONT, text_position=(4, int(matrixportal.graphics.display.height * 0.75) - 3), text_color=RED_COLOR, text_scale=2, ) # Blue Score matrixportal.add_text( text_font=terminalio.FONT, text_position=(36, int(matrixportal.graphics.display.height * 0.75) - 3), text_color=BLUE_COLOR, text_scale=2, ) # Red Team name matrixportal.add_text( text_font=terminalio.FONT, text_position=(4, int(matrixportal.graphics.display.height * 0.25) - 4), text_color=RED_COLOR, ) # Blue Team name matrixportal.add_text( text_font=terminalio.FONT, text_position=(36, int(matrixportal.graphics.display.height * 0.25) - 4), text_color=BLUE_COLOR, ) # Static 'Connecting' Text matrixportal.add_text( text_font=terminalio.FONT, text_position=(59, 0), )
Feed Variables
In order to use the feed data, we need a few variables to help traverse the AIO json data, as well as set the update delay variable to 4 seconds.
We also set the text colors here.
SCORES_RED_FEED = "scores-group.red-team-score-feed" SCORES_BLUE_FEED = "scores-group.blue-team-score-feed" TEAM_RED_FEED = "scores-group.red-team-name" TEAM_BLUE_FEED = "scores-group.blue-team-name" UPDATE_DELAY = 4 matrixportal.set_text_color(RED_COLOR, 0) matrixportal.set_text_color(BLUE_COLOR, 1)
Connecting Function
The show_connecting()
function is used to display a dot symbol when the device is connecting to AIO over the WiFi access point.
def show_connecting(show): if show: matrixportal.set_text(".", 4) else: matrixportal.set_text(" ", 4)
def get_last_data(feed_key): feed = matrixportal.get_io_feed(feed_key, detailed=True) value = feed["details"]["data"]["last"] if value is not None: return value["value"] return None
def customize_team_names(): team_red = "Red" team_blue = "Blue" show_connecting(True) team_name = get_last_data(TEAM_RED_FEED) if team_name is not None: print("Team {} is now Team {}".format(team_red, team_name)) team_red = team_name matrixportal.set_text(team_red, 2) team_name = get_last_data(TEAM_BLUE_FEED) if team_name is not None: print("Team {} is now Team {}".format(team_blue, team_name)) team_blue = team_name matrixportal.set_text(team_blue, 3) show_connecting(False)
Update Scores Function
This function is used to pull in the updated score data and then adjust the text to match.
def update_scores(): print("Updating data from Adafruit IO") show_connecting(True) score_red = get_last_data(SCORES_RED_FEED) if score_red is None: score_red = 0 matrixportal.set_text(score_red, 0) score_blue = get_last_data(SCORES_BLUE_FEED) if score_blue is None: score_blue = 0 matrixportal.set_text(score_blue, 1) show_connecting(False)
The last steps of the setup are to run the customize_team_names()
function and the update_scores()
function, and then set a timekeeping variable.
customize_team_names() update_scores() last_update = time.monotonic()
Main Loop
The main loop of the program simply waits for the four second update delay to pass and then calls update_scores()
, and resets the last_update
time.
while True: # Set the red score text if time.monotonic() > last_update + UPDATE_DELAY: update_scores() last_update = time.monotonic()
Page last edited February 24, 2025
Text editor powered by tinymce.