CircuitPython Code
In the embedded code element below, click on the Download Project Bundle button, and save the .zip archive file to your computer.
Then, uncompress the .zip file, it will unpack to a folder named PyPortal_Reddit.
Copy the contents of the PyPortal_Reddit directory to your PyPortal CIRCUITPY drive.
This is what the final contents of the CIRCUITPY drive will look like:

# SPDX-FileCopyrightText: 2019 Limor Fried for Adafruit Industries # # SPDX-License-Identifier: MIT """ This example will access the reddit API, grab a number like subreddit followers and display it on a screen If you can find something that spits out JSON data, we can display it! """ import time import board from adafruit_pyportal import PyPortal SUBREDDIT = "circuitpython" # Set up where we'll be fetching data from DATA_SOURCE = "https://www.reddit.com/r/"+SUBREDDIT+"/about.json" DATA_LOCATION = ["data", "subscribers"] CAPTION="reddit.com/r/"+SUBREDDIT # the current working directory (where this file is) cwd = ("/"+__file__).rsplit('/', 1)[0] pyportal = PyPortal(url=DATA_SOURCE, json_path=DATA_LOCATION, status_neopixel=board.NEOPIXEL, default_bg=cwd+"/reddit_background.bmp", text_font=cwd+"/fonts/Collegiate-50.bdf", text_position=(210, 80), text_color=0xFFFFFF, caption_text=CAPTION, caption_font=cwd+"/fonts/Collegiate-24.bdf", caption_position=(40, 200), caption_color=0xFFFFFF) # track the last value so we can play a sound when it updates last_value = 0 while True: try: value = pyportal.fetch() print("Response is", value) if last_value < value: # ooh it went up! print("New subscriber!") pyportal.play_file(cwd+"/coin.wav") last_value = value except (ValueError, RuntimeError, ConnectionError, OSError) as e: print("Some error occured, retrying! -", e) time.sleep(60)
How It Works
The PyPortal Stats Trophy is doing a couple of neat-o things to provide for your stats-tastic display needs!
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 the subreddit's name as a caption, created with bitmapped fonts to overlay on top of the background. The font used here is a bitmap font made from the Collegiate typeface. You can learn more about converting type in this guide.
Next, the PyPortal will display the current number of subscribers to the subreddit.
JSON
To keep things current, the subscriber count is grabbed from the website itself.
Reddit automatically generates a JSON file for each subreddit, in this case at the address https://www.reddit.com/r/circuitpython/about.json
This file contains all sorts of information, delivered in an easy-to-parse format. If you visit that URL by copying the address in to your browser, your browser may return it as a somewhat difficult to read chunk of raw text, or if you view it in Firefox, it will format it nicely for reading.
You can also use online code "beautifiers" such as https://codebeautify.org/jsonviewer or http://jsonviewer.stack.hu
Here it is in a raw-er form, but still using indentation and carriage returns to make it readable:
{ "kind": "t5", "data": { "notification_level": "low", "user_flair_background_color": null, "wls": null, "banner_img": "", "user_sr_theme_enabled": true, "user_flair_text": null, "submit_text_html": null, "user_flair_css_class": null, "user_flair_template_id": null, "user_is_banned": false, "free_form_reports": true, "subreddit_type": "public", "community_icon": "https://styles.redditmedia.com/t5_hsaso/styles/communityIcon_61bytmoqpd521.png", "banner_background_image": "https://styles.redditmedia.com/t5_hsaso/styles/bannerBackgroundImage_rwkjzfh8vd521.png", "header_title": null, "wiki_enabled": true, "over18": false, "show_media": true, "banner_background_color": "#ffffff", "description": "CircuitPython is Adafruit's branch of MicroPython designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Reddit wiki: [https://www.reddit.com/r/circuitpython/wiki/index](https://www.reddit.com/r/circuitpython/wiki/index)\n\nWith CircuitPython you can write clean and simple Python code to control hardware instead of having to use complex low-level languages like C or C++ (what Arduino uses for programming). It's great for beginners!", "user_is_muted": false, "user_flair_type": "text", "user_can_flair_in_sr": null, "display_name": "circuitpython", "header_img": null, "description_html": "<!-- SC_OFF --><div class=\"md\"><p>CircuitPython is Adafruit's branch of MicroPython designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Reddit wiki: <a href=\"https://www.reddit.com/r/circuitpython/wiki/index\">https://www.reddit.com/r/circuitpython/wiki/index</a></p>\n\n<p>With CircuitPython you can write clean and simple Python code to control hardware instead of having to use complex low-level languages like C or C++ (what Arduino uses for programming). It's great for beginners!</p>\n</div><!-- SC_ON -->", "title": "CircuitPython", "collapse_deleted_comments": false, "user_has_favorited": false, "emojis_custom_size": null, "id": "hsaso", "emojis_enabled": false, "public_description_html": "<!-- SC_OFF --><div class=\"md\"><p>CircuitPython - Python on microcontrollers! Welcome to our community! All things Python, CircuitPython, MicroPython and more! </p>\n</div><!-- SC_ON -->", "can_assign_user_flair": false, "allow_videos": true, "spoilers_enabled": true, "icon_size": null, "primary_color": "#a71ff2", "user_is_contributor": false, "suggested_comment_sort": null, "active_user_count": 18, "icon_img": "", "original_content_tag_enabled": false, "display_name_prefixed": "r/circuitpython", "can_assign_link_flair": false, "submit_text": "", "allow_videogifs": true, "user_flair_text_color": null, "accounts_active": 18, "public_traffic": false, "header_size": null, "subscribers": 318, "user_flair_position": "right", "submit_text_label": null, "key_color": "", "link_flair_position": "", "user_flair_richtext": [], "all_original_content": false, "lang": "en", "has_menu_widget": false, "is_enrolled_in_new_modmail": null, "whitelist_status": null, "name": "t5_hsaso", "user_flair_enabled_in_sr": true, "created": 1523121954, "url": "/r/circuitpython/", "submit_link_label": null, "quarantine": false, "hide_ads": false, "created_utc": 1523121954, "banner_size": null, "user_is_moderator": false, "user_sr_flair_enabled": true, "allow_discovery": true, "accounts_active_is_fuzzed": false, "advertiser_category": "", "public_description": "CircuitPython - Python on microcontrollers! Welcome to our community! All things Python, CircuitPython, MicroPython and more! ", "link_flair_enabled": false, "allow_images": true, "videostream_links_count": 0, "comment_score_hide_mins": 0, "show_media_preview": true, "submission_type": "any", "user_is_subscriber": true } }
Keys
If we look a bit further down the JSON page, we'll see a key called subscribers
that has a value of 318
. The raw JSON for this key : value pair looks like this: "subscribers": 318
Our CircuitPython code is able to grab and parse this data using these variables:
SUBREDDIT = "circuitpython" DATA_SOURCE = "https://www.reddit.com/r/"+SUBREDDIT+"/about.json" DATA_LOCATION = ["data", "subscribers"]
The SUBREDDIT
variable and DATA_SOURCE
work together to construct the URL that is queried.
Traversing JSON
The DATA_LOCATION
is a list that we use to traverse the JSON file. In the image above, note how there is a tree hierarchy indicated by the indentation level. The data key is the parent of a subtree containing many other keys, including the subscribers
key for which we want to find out the value, in this case 318
PyPortal Constructor
When we set up the pyportal
constructor, we are providing it with these things:
-
url
to query -
json_path
to traverse and find the key:value pair we need -
default_bg
path and name to display the background bitmap -
text_font
path and name to the font used for displaying the subscriber count value -
text_position
on the screen's x/y coordinate system text_color
-
caption_text
to display statically -- in this case the name of the subreddit caption_font
caption_position
caption_color
Fetch
With the pyportal set up, we can then use pyportal.fetch()
to do the query and parsing of the subreddit subscriber data and then display it on screen along with the caption text on top of the background image.
Ba-Ding!
Additionally, we use the last_value
variable's state to compare against the latest value. If they differ, we play the coin.wav file for a satisfying ding over the PyPortal's built in speaker!
To make your own .wav files, check out this guide.
Customization
You can customize this project to make it your own and point to different website API's as the source of your JSON data, as well as adjust the graphics and text.
Text Position
Depending on the design of your background bitmap and the length of the text you're displaying, you may want to reposition the text and caption. You can do this with the text_position
and caption_position
options.
The PyPortal's display is 320 pixels wide and 240 pixels high. In order to refer to those positions on the screen, we use an x/y coordinate system, where x is horizontal and y is vertical.
The origin of this coordinate system is the upper left corner. This means that a pixel placed at the upper left corner would be (0,0) and the lower right corner would be (320, 240).
So, if you wanted to move the subscriber count text to the right and up closer to the top, your code may look like this for that part of the pyportal constructor: text_position=(250, 10)
Text Color
Another way to customize your stats trophy is to adjust the color of the text. The line text_color=0xFFFFFF
in the constructor shows how. You will need to use the hexidecimal value for any color you want to display.
You can use something like https://htmlcolorcodes.com/ to pick your color and then copy the hex value, in this example it would be 0x0ED9EE
Background Image
If you would like to create your own background, awesome! You'll want to save the file with these specifications:
- 320 x 240 pixels
- 24-bit RGB color (8-bits per channel)
- Save file as .bmp format
You can then copy the .bmp file to the root level of the CIRCUITPY drive. Make sure you refer to this new filename in the pyportal constructor line:
default_bg=cwd+"/reddit_background.bmp"
Change that line to use the new filename name, such as:
default_bg=cwd+"/my_new_background.bmp"
Now, we'll look at mounting the PyPortal onto a trophy for display!
Page last edited January 21, 2025
Text editor powered by tinymce.