Countdown to the Big Night
With the PyPortal coded in CircuitPython, we can set the date of the next halloween.
The PyPortal Halloween Countdown will do the following:
- Display a random background .bmp showing Adafruit characters in costume
- Determine the current local time using the WiFi connection to the internet
- Display the number of days remaining until the big night
- Display a custom background graphic once it's Halloween
Adafruit IO Time Server
In order to get the precise time, our project will query the Adafruit IO Internet of Things service for the time. 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 settings.toml 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 settings.toml file like this:
CIRCUITPY_WIFI_SSID="your-wifi-ssid" CIRCUITPY_WIFI_PASSWORD="your-wifi-password" ADAFRUIT_AIO_USERNAME="my_username" ADAFRUIT_AIO_KEY="my_key" timezone="America/New_York" # http://worldtimeapi.org/timezones
Riffing on Code
The code in this project is nearly identical to that of the more general event countdown project. There are two primary differences:
- it only looks at the day, not hours and minutes (they are zeroed before the time comparison),
- the background is changed every minute to a random image of one of the Adafruit characters in costume.
Install CircuitPython Code and Assets
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_Halloween_Countdown.
Copy the contents of the PyPortal_Halloween_Countdown directory to your PyPortal CIRCUITPYdrive.
# SPDX-FileCopyrightText: 2019 Dave Astels for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
PyPortal based countdown of days until Halloween.
Adafruit invests time and resources providing this open source code.
Please support Adafruit and open source hardware by purchasing
products from Adafruit!
Written by Dave Astels for Adafruit Industries
Copyright (c) 2019 Adafruit Industries
Licensed under the MIT license.
All text above must be included in any redistribution.
"""
from os import getenv
import time
import random
import board
from adafruit_pyportal import PyPortal
from adafruit_bitmap_font import bitmap_font
from adafruit_display_text.label import Label
# Get WiFi details, ensure these are setup in settings.toml
ssid = getenv("CIRCUITPY_WIFI_SSID")
password = getenv("CIRCUITPY_WIFI_PASSWORD")
if None in [ssid, password]:
raise RuntimeError(
"WiFi settings are kept in settings.toml, "
"please add them there. The settings file must contain "
"'CIRCUITPY_WIFI_SSID', 'CIRCUITPY_WIFI_PASSWORD', "
"at a minimum."
)
# The time of the thing!
EVENT_YEAR = 2019
EVENT_MONTH = 10
EVENT_DAY = 31
# we'll make a python-friendly structure
event_time = time.struct_time((EVENT_YEAR, EVENT_MONTH, EVENT_DAY,
0, 0, 0, # we don't track hours, minutes, or seconds
-1, -1, False)) # we dont know day of week/year or DST
# determine the current working directory
# needed so we know where to find files
cwd = ("/"+__file__).rsplit('/', 1)[0]
big_font = bitmap_font.load_font(cwd+"/fonts/Terror-94.bdf")
big_font.load_glyphs(b'0123456789') # pre-load glyphs for fast printing
backgrounds = ['background_1.bmp',
'background_2.bmp',
'background_3.bmp',
'background_4.bmp',
'background_5.bmp',
'background_6.bmp',
'background_7.bmp',
'background_8.bmp',
'background_9.bmp',
'background_10.bmp',
'background_11.bmp',
'background_12.bmp',
'background_13.bmp',
'background_14.bmp',
'background_15.bmp',
'background_16.bmp',
'background_17.bmp']
event_background = cwd+"/happy_halloween.bmp"
# Initialize the pyportal object and let us know what data to fetch and where
# to display it
pyportal = PyPortal(status_neopixel=board.NEOPIXEL,
default_bg=cwd + backgrounds[0],
caption_text='DAYS REMAINING',
caption_font=cwd+'/fonts/Terror-31.bdf',
caption_position=(24, 218),
caption_color=0x000000)
countdown_text = Label(big_font)
countdown_text.x = 25
countdown_text.y = 120
countdown_text.color = 0x7942a0
pyportal.root_group.append(countdown_text)
refresh_time = None
while True:
# only query the online time once per hour (and on first run)
if (not refresh_time) or (time.monotonic() - refresh_time) > 3600:
try:
print("Getting time from internet!")
pyportal.get_local_time(location=getenv("timezone"))
refresh_time = time.monotonic()
except RuntimeError as e:
print("Some error occured, retrying! -", e)
continue
timestamp = time.localtime()
now = time.struct_time((timestamp[0], timestamp[1], timestamp[2],
0, 0, 0, # we don't track seconds
-1, -1, False)) # we dont know day of week/year or DST
print("Current time:", now)
remaining = time.mktime(event_time) - time.mktime(now)
print("Time remaining (s):", remaining)
if remaining == 0:
# oh, its event time!
pyportal.set_background(event_background)
countdown_text.text = ''
pyportal.set_caption('', (13, 215), 0x000000)
while True: # that's all folks
pass
days_remaining = remaining // 86400
print("%d days remaining" % (days_remaining))
countdown_text.text = '{:>3}'.format(days_remaining)
pyportal.set_background(backgrounds[random.randint(0, len(backgrounds) - 1)])
# update every minute
time.sleep(60)
The PyPortal CIRCUITPY drive should have (at least) these files:
Page last edited April 09, 2025
Text editor powered by tinymce.