Overview
This PyPortal project shows one notable electronic or science fact every day. Based on what day it is, CircuitPython code grabs JSON data from a database and then prints information about the person associated with that day. Want more info on the person? Use the QR code!
We created our very own database with data on the most memorable electronics and sciencey peoples. The CircuitPython code grabs from this database to bring you all these great factoids!
Parts
You can pick up an Adafruit PyPortal and a USB cable (if needed). If you like, you can mount the PyPortal in the Adafruit laser-cut acrylic stand.
You can use any case you like. If you get the stand enclosure kit, the instructions for assembly are in this guide page. You can see some other cases (3D printed, etc. via this Adafruit Learning System link.
Page last edited March 08, 2024
Text editor powered by tinymce.
Install CircuitPython
CircuitPython is a derivative 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. Simply copy and edit files on the CIRCUITPY "flash" drive to iterate.
The following instructions will show you how to install CircuitPython. If you've already installed CircuitPython but are looking to update it or reinstall it, the same steps work for that as well!
Click the link above to download the latest version of CircuitPython for the PyPortal.
Download and save it to your desktop (or wherever is handy).
Plug your PyPortal into your computer using a known-good USB cable.
A lot of people end up using charge-only USB cables and it is very frustrating! So make sure you have a USB cable you know is good for data sync.
Double-click the Reset button on the top in the middle (magenta arrow) on your board, and you will see the NeoPixel RGB LED (green arrow) turn green. If it turns red, check the USB cable, try another USB port, etc. Note: The little red LED next to the USB connector will pulse red. That's ok!
If double-clicking doesn't work the first time, try again. Sometimes it can take a few tries to get the rhythm right!
You will see a new disk drive appear called PORTALBOOT.
Drag the adafruit-circuitpython-pyportal-<whatever>.uf2 file to PORTALBOOT.
The LED will flash. Then, the PORTALBOOT drive will disappear and a new disk drive called CIRCUITPY will appear.
If you haven't added any code to your board, the only file that will be present is boot_out.txt. This is absolutely normal! It's time for you to add your code.py and get started!
That's it, you're done! :)
PyPortal Default Files
Click below to download a zip of the files that shipped on the PyPortal or PyPortal Pynt.
Page last edited March 08, 2024
Text editor powered by tinymce.
Create Your settings.toml File
CircuitPython works with WiFi-capable boards to enable you to make projects that have network connectivity. This means working with various passwords and API keys. As of CircuitPython 8, there is support for a settings.toml file. This is a file that is stored on your CIRCUITPY drive, that contains all of your secret network information, such as your SSID, SSID password and any API keys for IoT services. It is designed to separate your sensitive information from your code.py file so you are able to share your code without sharing your credentials.
CircuitPython previously used a secrets.py file for this purpose. The settings.toml file is quite similar.
CircuitPython settings.toml File
This section will provide a couple of examples of what your settings.toml file should look like, specifically for CircuitPython WiFi projects in general.
The most minimal settings.toml file must contain your WiFi SSID and password, as that is the minimum required to connect to WiFi. Copy this example, paste it into your settings.toml, and update:
your_wifi_ssidyour_wifi_password
CIRCUITPY_WIFI_SSID = "your_wifi_ssid" CIRCUITPY_WIFI_PASSWORD = "your_wifi_password"
Many CircuitPython network-connected projects on the Adafruit Learn System involve using Adafruit IO. For these projects, you must also include your Adafruit IO username and key. Copy the following example, paste it into your settings.toml file, and update:
your_wifi_ssidyour_wifi_passwordyour_aio_usernameyour_aio_key
CIRCUITPY_WIFI_SSID = "your_wifi_ssid" CIRCUITPY_WIFI_PASSWORD = "your_wifi_password" ADAFRUIT_AIO_USERNAME = "your_aio_username" ADAFRUIT_AIO_KEY = "your_aio_key"
Some projects use different variable names for the entries in the settings.toml file. For example, a project might use ADAFRUIT_AIO_ID in the place of ADAFRUIT_AIO_USERNAME. If you run into connectivity issues, one of the first things to check is that the names in the settings.toml file match the names in the code.
Here is an example settings.toml file.
# Comments are supported CIRCUITPY_WIFI_SSID = "guest wifi" CIRCUITPY_WIFI_PASSWORD = "guessable" CIRCUITPY_WEB_API_PORT = 80 CIRCUITPY_WEB_API_PASSWORD = "passw0rd" test_variable = "this is a test" thumbs_up = "\U0001f44d"
In a settings.toml file, it's important to keep these factors in mind:
- Strings are wrapped in double quotes; ex:
"your-string-here" - Integers are not quoted and may be written in decimal with optional sign (
+1,-1,1000) or hexadecimal (0xabcd).- Floats (decimal numbers), octal (
0o567) and binary (0b11011) are not supported.
- Floats (decimal numbers), octal (
- Use
\uescapes for weird characters,\xand\oooescapes are not available in .toml files- Example:
\U0001f44dfor 👍 (thumbs up emoji) and\u20acfor € (EUR sign)
- Example:
- Unicode emoji, and non-ASCII characters, stand for themselves as long as you're careful to save in "UTF-8 without BOM" format
When your settings.toml file is ready, you can save it in your text editor with the .toml extension.
In your code.py file, you'll need to import the os library to access the settings.toml file. Your settings are accessed with the os.getenv() function. You'll pass your settings entry to the function to import it into the code.py file.
import os
print(os.getenv("test_variable"))
In the upcoming CircuitPython WiFi examples, you'll see how the settings.toml file is used for connecting to your SSID and accessing your API keys.
Page last edited March 08, 2024
Text editor powered by tinymce.
PyPortal CircuitPython Setup
To use all the amazing features of your PyPortal with CircuitPython, you must first install a number of libraries. This page covers that process.
Adafruit CircuitPython Bundle
Download the Adafruit CircuitPython Library Bundle. You can find the latest release here:
Download the adafruit-circuitpython-bundle-*.x-mpy-*.zip bundle zip file where *.x MATCHES THE VERSION OF CIRCUITPYTHON YOU INSTALLED, and unzip a folder of the same name. Inside you'll find a lib folder. You have two options:
- You can add the lib folder to your CIRCUITPY drive. This will ensure you have all the drivers. But it will take a bunch of space on the 8 MB disk
- Add each library as you need it, this will reduce the space usage but you'll need to put in a little more effort.
At a minimum we recommend the following libraries, in fact we more than recommend. They're basically required. So grab them and install them into CIRCUITPY/lib now!
- adafruit_esp32spi - This is the library that gives you internet access via the ESP32 using (you guessed it!) SPI transport. You need this for anything Internet
- adafruit_requests - This library allows us to perform HTTP requests and get responses back from servers. GET/POST/PUT/PATCH - they're all in here!
- adafruit_connection_manager - used by adafruit_requests.
- adafruit_pyportal - This is our friendly wrapper library that does a lot of our projects, displays graphics and text, fetches data from the internet. Nearly all of our projects depend on it!
- adafruit_portalbase - This library is the base library that adafruit_pyportal library is built on top of.
- adafruit_touchscreen - a library for reading touches from the resistive touchscreen. Handles all the analog noodling, rotation and calibration for you.
- adafruit_io - this library helps connect the PyPortal to our free datalogging and viewing service
- adafruit_imageload - an image display helper, required for any graphics!
- adafruit_display_text - not surprisingly, it displays text on the screen
- adafruit_bitmap_font - we have fancy font support, and its easy to make new fonts. This library reads and parses font files.
- adafruit_slideshow - for making image slideshows - handy for quick display of graphics and sound
- neopixel - for controlling the onboard neopixel
- adafruit_adt7410 - library to read the temperature from the on-board Analog Devices ADT7410 precision temperature sensor (not necessary for Titano or Pynt)
- adafruit_bus_device - low level support for I2C/SPI
- adafruit_fakerequests - This library allows you to create fake HTTP requests by using local files.
Page last edited March 08, 2024
Text editor powered by tinymce.
Download Project Files from GitHub
All of the files required for this project (the code, graphics, and font) are available for download on GitHub. There are two code files for this project, our regular code.py along with secrets.py
You'll need to edit secrets.py with your applicable information. You can find more info on all of the code files in the next two pages of this guide.
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_on_this_day.
Copy the contents of the PyPortal_on_this_day directory to your PyPortal CIRCUITPY drive.
# SPDX-FileCopyrightText: 2019 Isaac Wellish for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
'of this day' demo
Display notable info about famous electronics-related peoples
Data sources: https://github.com/adafruit/OTD/tree/master/electronics
"""
import time
import board
from adafruit_pyportal import PyPortal
from adafruit_pyportal.network import CONTENT_JSON
cwd = ("/"+__file__).rsplit('/', 1)[0] # the current working directory (where this file is)
DAY = ["Day of the year"]
PERSON = ["Person"]
NOTABLE = ["Notable for"]
YEAR = ["Year"]
ACCOMPLISH = ["Accomplishment"]
WEB = ["Web Reference"]
BASE_DATA = "https://raw.githubusercontent.com/adafruit/OTD/master/electronics/"
# a function that returns whatever is passed in
def identity(x):
return x
# create pyportal object w no data source (we'll feed it text later)
pyportal = PyPortal(url = BASE_DATA, debug=True,
json_path = (DAY, PERSON, NOTABLE, YEAR, ACCOMPLISH, WEB),
status_neopixel = board.NEOPIXEL,
default_bg = cwd + "/on_this_day_bg.bmp",
text_font = cwd+"fonts/Arial-ItalicMT-17.bdf",
text_transform = [identity]*6, # we do this so the date doesnt get commas
text_position=((10, 60), (10, 90), (10, 120),(60, 150), (105, 180), (10, 210)),
text_color=(0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF),
text_maxlen=(50, 50, 50, 50, 50, 50), # cut off characters
)
while True:
try:
print("Getting time from internet!")
pyportal.get_local_time()
refresh_time = time.monotonic()
except RuntimeError as e:
print("Some error occured, retrying! -", e)
continue
now = time.localtime()
print("Current time:", now)
url = BASE_DATA+"%02d_%02d.json" % (now.tm_mon, now.tm_mday)
print(url)
response = None
try:
response = pyportal.fetch(url, force_content_type = CONTENT_JSON)
print("Response is", response)
except RuntimeError as e:
print("Some error occured, retrying! -", e)
# Make a QR code from web reference
pyportal.show_QR(bytearray(response[5], "utf-8"), qr_size=3,
x=220, y=10)
# wait 10 minutes before running again
time.sleep(10*60)
This project uses the following CircuitPython libraries loaded in the Project Bundle:
- adafruit_bitmap_font (directory)
- adafruit_bus_device (directory)
- adafruit_display_shapes (directory)
- adafruit_display_text (directory)
- adafruit_esp32spi (directory)
- adafruit_io (directory)
- adafruit_miniqr.mpy (file)
- adafruit_pyportal.mpy (file)
- adafruit_requests (file)
- adafruit_touchscreen.mpy (file)
- neopixel.mpy (file)
This is what the final contents of the CIRCUITPY drive will look like:
Page last edited March 08, 2024
Text editor powered by tinymce.
Code Walkthrough - code.py
code.py is the file where the main code of the program resides!
Background
First, the program displays a bitmap graphic as the screen's background.
This background has the title of the program as well as a couple of sub-titles to make the data more readable.
This is a 320 x 240 pixel RGB 16-bit raster graphic in .bmp format.
If you would like to create your own background, awesome! You'll want to save the file with these specifications:
- 320 x 240 pixels
- 16-bit RGB color
- 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+ "/on_this_day_bg.bmp"
Change that line to use the new filename name, such as:
default_bg=cwd+"/my_new_background.bmp"
Font
The fonts used here are bitmap fonts made from the Arial Italic 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 taken from a website!
The Adafruit "OTD" repository on Github is where we're storing all this enlightening data. We can grab the JSON directly from Github site and display it on the PyPortal.
- Head to the site here to see the lovely home of all this data.
- Click on the "electronics" folder.
- Now click any of the dates you want to see that data for, and voila there's the data!
- Now click on the "raw" button.
- This leads to the direct source of the JSON data, where the data is pulled from.
{
"Day of the year":"January 25",
"Person":"Robert Boyle",
"Notable for":"Chemist, Physicist",
"Year":"1627",
"Accomplishment":"Chemistry, pV=Nrt",
"Web Reference":"wikipedia.org/wiki/Robert_Boyle"
}
If we look through the JSON file, we'll see 6 keys called Day of the year, Person, Notable for etc.
Each key has an associated value paired with it.
Our CircuitPython code is able to grab and parse this data using these variables:
DAY = ["Day of the year"] PERSON = ["Person"] NOTABLE = ["Notable for"] YEAR = ["Year"] ACCOMPLISH = ["Accomplishment"] WEB = ["Web Reference"]
Next, here's our data source from above!
BASE_DATA = "https://raw.githubusercontent.com/adafruit/OTD/master/electronics/"
PyPortal Constructor
Then, in the pyportal query we ask for the Day of the year, Person, Notable for etc. from that URL, and then use the text_ arguments to set the font, transform, position, color, and maxlen of the text when it is displayed.
pyportal = PyPortal(url = BASE_DATA, debug=True,
json_path = (DAY, PERSON, NOTABLE, YEAR, ACCOMPLISH, WEB),
status_neopixel = board.NEOPIXEL,
default_bg = cwd + "/on_this_day_bg.bmp",
text_font = cwd+"fonts/Arial-ItalicMT-17.bdf",
text_transform = [identity]*6, # we do this so the date doesnt get commas
text_position=((10, 70), (10, 100), (10, 130),(60, 160), (105, 190), (10, 220)),
text_color=(0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF),
text_maxlen=(50, 50, 50, 50, 50, 50), # cut off characters
)
With all of this prepared, during the main loop of while True: the code will:
- Find out what day it is and insert that date at the end of the data URL.
- With that new URL, the porgram will query the Adafruit OTD Github page for the JSON data, and display it, along with the QR code for the associated Wikipedia link.
- Then the program will wait 10 minutes until repeating the process.
And that's the whole program!
Page last edited March 08, 2024
Text editor powered by tinymce.