Once you've finished setting up your QT Py ESP32-S2 with CircuitPython, you can access the code and necessary libraries by downloading the Project Bundle.
To do this, click on the Download Project Bundle button in the window below. It will download to your computer as a zipped folder.
# SPDX-FileCopyrightText: 2024 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import os
import time
import wifi
import microcontroller
import board
import neopixel
import adafruit_connection_manager
import adafruit_requests
from adafruit_io.adafruit_io import IO_HTTP
from adafruit_ticks import ticks_ms, ticks_add, ticks_diff
timezone = "America/New_York"
color = 0xFF00FF
# The time of the thing!
EVENT_YEAR = 2024
EVENT_MONTH = 8
EVENT_DAY = 16
EVENT_HOUR = 0
EVENT_MINUTE = 0
# we'll make a python-friendly structure
event_time = time.struct_time((EVENT_YEAR, EVENT_MONTH, EVENT_DAY,
EVENT_HOUR, EVENT_MINUTE, 0, # we don't track seconds
-1, -1, False)) # we dont know day of week/year or DST
print("Connecting to WiFi...")
wifi.radio.connect(
os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD")
)
pool = adafruit_connection_manager.get_radio_socketpool(wifi.radio)
ssl_context = adafruit_connection_manager.get_radio_ssl_context(wifi.radio)
requests = adafruit_requests.Session(pool, ssl_context)
io = IO_HTTP(
os.getenv("AIO_USERNAME"), os.getenv("AIO_KEY"), requests
)
pixel_pin = board.SCL1
pixel_num = 16
pixels = neopixel.NeoPixel(pixel_pin, n = pixel_num, brightness=1, auto_write=True)
pixel_length = 0
last_length = -1
refresh_clock = ticks_ms()
refresh_timer = 3600 * 1000 # 1 hour
first_run = True
finished = False
while True:
if not finished:
if ticks_diff(ticks_ms(), refresh_clock) >= refresh_timer or first_run:
try:
print("Getting time from internet!")
now = time.struct_time(io.receive_time(timezone))
print(now)
total_seconds = time.mktime(now)
remaining = time.mktime(event_time) - total_seconds
if remaining < 0:
pixel_length = pixel_num + 1
finished = True
else:
if now.tm_mon == EVENT_MONTH:
pixel_length = now.tm_mday % (pixel_num + 1)
refresh_clock = ticks_add(refresh_clock, refresh_timer)
except Exception as e: # pylint: disable=broad-except
print("Some error occured, retrying via reset in 15 seconds! - ", e)
time.sleep(15)
microcontroller.reset()
if last_length != pixel_length:
if not pixel_length:
pixels.fill(0x000000)
else:
for i in range(pixel_length):
pixels[i] = color
last_length = pixel_length
first_run = False
Upload the Code and Libraries to the QT Py ESP32-S2
After downloading the Project Bundle, plug your QT Py ESP32-S2 into the computer's USB port with a known good USB data+power cable. You should see a new flash drive appear in the computer's File Explorer or Finder (depending on your operating system) called CIRCUITPY. Unzip the folder and copy the following items to the QT Py ESP32-S2's CIRCUITPY drive.
- lib folder
- code.py
Your QT Py ESP32-S2 CIRCUITPY drive should look like this after copying the lib folder and the code.py file.
Add Your settings.toml File
As of CircuitPython 8.0.0, there is support for Environment Variables. Environment variables are stored in a settings.toml file. Similar to secrets.py, the settings.toml file separates your sensitive information from your main code.py file. Add your settings.toml file as described in the Create Your settings.toml File page earlier in this guide. You'll need to include your AIO_USERNAME, AIO_KEY, CIRCUITPY_WIFI_SSID and CIRCUITPY_WIFI_PASSWORD.
CIRCUITPY_WIFI_SSID = "your-ssid-here" CIRCUITPY_WIFI_PASSWORD = "your-ssid-password-here" AIO_USERNAME = "your-username-here" AIO_KEY = "your-key-here"
How the CircuitPython Code Works
At the top of the code, you'll edit timezone to reflect your timezone location. You can edit color to change the color of the NeoPixels. The event time is also set. In this case, it's August 16, 2024 at midnight.
timezone = "America/New_York"
color = 0xFF00FF
# The time of the thing!
EVENT_YEAR = 2024
EVENT_MONTH = 8
EVENT_DAY = 16
EVENT_HOUR = 0
EVENT_MINUTE = 0
# we'll make a python-friendly structure
event_time = time.struct_time((EVENT_YEAR, EVENT_MONTH, EVENT_DAY,
EVENT_HOUR, EVENT_MINUTE, 0, # we don't track seconds
-1, -1, False)) # we dont know day of week/year or DST
WiFi
The board connects to WiFi and then establishes a connection with Adafruit IO. Adafruit IO is used as a time server for this project.
print("Connecting to WiFi...")
wifi.radio.connect(
os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD")
)
pool = adafruit_connection_manager.get_radio_socketpool(wifi.radio)
ssl_context = adafruit_connection_manager.get_radio_ssl_context(wifi.radio)
requests = adafruit_requests.Session(pool, ssl_context)
io = IO_HTTP(
os.getenv("AIO_USERNAME"), os.getenv("AIO_KEY"), requests
)
NeoPixels
The NeoPixels are setup on pin SCL1 for the data connection. This is not the standard use for this STEMMA I2C pin, but using it makes it a solderless project. pixel_length and last_length are used in the loop to keep track of which NeoPixels are lit for the countdown.
pixel_pin = board.SCL1 pixel_num = 16 pixels = neopixel.NeoPixel(pixel_pin, n = pixel_num, brightness=1, auto_write=True) pixel_length = 0 last_length = -1
Time and States
adafruit_ticks is used for timekeeping in the loop. first_run and finished are used as states for tracking the state of the timekeeping.
refresh_clock = ticks_ms() refresh_timer = 3600 * 1000 # 1 hour first_run = True finished = False
The Loop
In the loop, the time is checked every hour via Adafruit IO. Since the NeoPixels are representing days until an event, the time does not need to be checked as often as with other countdown projects. The date is used as the count for the NeoPixels. For example, if it's the 6th of the event month, then 6 NeoPixels will be lit. If the countdown is over, then all of the NeoPixels are lit.
while True:
if not finished:
if ticks_diff(ticks_ms(), refresh_clock) >= refresh_timer or first_run:
try:
print("Getting time from internet!")
now = time.struct_time(io.receive_time(timezone))
print(now)
total_seconds = time.mktime(now)
remaining = time.mktime(event_time) - total_seconds
if remaining < 0:
pixel_length = pixel_num + 1
finished = True
else:
if now.tm_mon == EVENT_MONTH:
pixel_length = now.tm_mday % (pixel_num + 1)
refresh_clock = ticks_add(refresh_clock, refresh_timer)
except Exception as e: # pylint: disable=broad-except
print("Some error occured, retrying via reset in 15 seconds! - ", e)
time.sleep(15)
microcontroller.reset()
if last_length != pixel_length:
if not pixel_length:
pixels.fill(0x000000)
else:
for i in range(pixel_length):
pixels[i] = color
last_length = pixel_length
first_run = False
Page last edited January 22, 2025
Text editor powered by tinymce.