|
| 1 | +# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries |
| 2 | +# SPDX-License-Identifier: MIT |
| 3 | +""" |
| 4 | +CircuitPython Quad-Alphanumeric Display Holiday Countdown. |
| 5 | +
|
| 6 | +This demo requires a separate file named .env (including the dot) on your CIRCUITPY drive, which |
| 7 | +should contain your WiFi credentials and Adafruit IO credentials. |
| 8 | +""" |
| 9 | + |
| 10 | +import os |
| 11 | +import time |
| 12 | +import ssl |
| 13 | +import wifi |
| 14 | +import socketpool |
| 15 | +import microcontroller |
| 16 | +import board |
| 17 | +import adafruit_requests |
| 18 | +from adafruit_ht16k33.segments import Seg14x4 |
| 19 | +from adafruit_io.adafruit_io import IO_HTTP, AdafruitIO_RequestError # pylint: disable=unused-import |
| 20 | + |
| 21 | +# Date and time of event. Update YEAR, MONTH, DAY, HOUR, MINUTE to match the date and time of the |
| 22 | +# event to which you are counting down. Update NAME to the name of the event. Update MSG to the |
| 23 | +# message you'd like to display when the countdown has completed and the event has started. |
| 24 | +EVENT_YEAR = 2022 |
| 25 | +EVENT_MONTH = 12 |
| 26 | +EVENT_DAY = 25 |
| 27 | +EVENT_HOUR = 0 |
| 28 | +EVENT_MINUTE = 0 |
| 29 | +EVENT_NAME = "Christmas" |
| 30 | +EVENT_MSG = "Merry Christmas * " |
| 31 | + |
| 32 | +# The speed of the text scrolling on the displays. Increase this to slow down the scrolling. |
| 33 | +# Decrease it to speed up the scrolling. |
| 34 | +scroll_speed = 0.25 |
| 35 | + |
| 36 | +# Create the I2C object using STEMMA_I2C() |
| 37 | +i2c = board.STEMMA_I2C() |
| 38 | +# Alphanumeric segment display setup using three displays in series. |
| 39 | +display = Seg14x4(i2c, address=(0x70, 0x71, 0x72)) |
| 40 | +# Display brightness is a number between 0.0 (off) and 1.0 (maximum). Update this if you want |
| 41 | +# to alter the brightness of the characters on the displays. |
| 42 | +display.brightness = 0.2 |
| 43 | +# The setup-successful message. If this shows up on your displays, you have wired them up |
| 44 | +# properly and the code setup is correct. |
| 45 | +display.print("HELLO WORLD") |
| 46 | + |
| 47 | + |
| 48 | +def reset_on_error(delay, error): |
| 49 | + """Resets the code after a specified delay, when encountering an error.""" |
| 50 | + print("Error:\n", str(error)) |
| 51 | + display.print("Error :(") |
| 52 | + print("Resetting microcontroller in %d seconds" % delay) |
| 53 | + time.sleep(delay) |
| 54 | + microcontroller.reset() |
| 55 | + |
| 56 | + |
| 57 | +try: |
| 58 | + wifi.radio.connect(os.getenv("WIFI_SSID"), os.getenv("WIFI_PASSWORD")) |
| 59 | +# any errors, reset MCU |
| 60 | +except Exception as e: # pylint: disable=broad-except |
| 61 | + reset_on_error(10, e) |
| 62 | + |
| 63 | +aio_username = os.getenv("aio_username") |
| 64 | +aio_key = os.getenv("aio_key") |
| 65 | +location = os.getenv("aio_location") |
| 66 | + |
| 67 | +pool = socketpool.SocketPool(wifi.radio) |
| 68 | +requests = adafruit_requests.Session(pool, ssl.create_default_context()) |
| 69 | +# Initialize an Adafruit IO HTTP API object |
| 70 | +try: |
| 71 | + io = IO_HTTP(aio_username, aio_key, requests) |
| 72 | +except Exception as e: # pylint: disable=broad-except |
| 73 | + reset_on_error(10, e) |
| 74 | +print("Connected to Adafruit IO") |
| 75 | +display.print("Connected IO") |
| 76 | + |
| 77 | +clock = time.monotonic() |
| 78 | + |
| 79 | +event_time = time.struct_time( |
| 80 | + (EVENT_YEAR, EVENT_MONTH, EVENT_DAY, EVENT_HOUR, EVENT_MINUTE, 0, -1, -1, False) |
| 81 | +) |
| 82 | +scroll_time = 0 |
| 83 | + |
| 84 | +while True: |
| 85 | + try: |
| 86 | + if (clock + scroll_time) < time.monotonic(): |
| 87 | + now = io.receive_time() |
| 88 | + # print(now) |
| 89 | + # print(event_time) |
| 90 | + remaining = time.mktime(event_time) - time.mktime(now) |
| 91 | + # if it's the day of the event... |
| 92 | + if remaining < 0: |
| 93 | + # scroll the event message on a loop |
| 94 | + display.marquee(EVENT_MSG, scroll_speed, loop=True) |
| 95 | + # calculate the seconds remaining |
| 96 | + secs_remaining = remaining % 60 |
| 97 | + remaining //= 60 |
| 98 | + # calculate the minutes remaining |
| 99 | + mins_remaining = remaining % 60 |
| 100 | + remaining //= 60 |
| 101 | + # calculate the hours remaining |
| 102 | + hours_remaining = remaining % 24 |
| 103 | + remaining //= 24 |
| 104 | + # calculate the days remaining |
| 105 | + days_remaining = remaining |
| 106 | + # pack the calculated times into a string to scroll |
| 107 | + countdown_string = ( |
| 108 | + "* %d Days, %d Hours, %d Minutes & %s Seconds until %s *" |
| 109 | + % ( |
| 110 | + days_remaining, |
| 111 | + hours_remaining, |
| 112 | + mins_remaining, |
| 113 | + secs_remaining, |
| 114 | + EVENT_NAME, |
| 115 | + ) |
| 116 | + ) |
| 117 | + # get the length of the packed string |
| 118 | + display_length = len(countdown_string) |
| 119 | + # print(display_length) |
| 120 | + # calculate the amount of time needed to scroll the string |
| 121 | + scroll_time = display_length * scroll_speed |
| 122 | + # print(scroll_time) |
| 123 | + # reset the clock |
| 124 | + clock = time.monotonic() |
| 125 | + # scroll the string once |
| 126 | + display.marquee(countdown_string, scroll_speed, loop=False) |
| 127 | + |
| 128 | + # any errors, reset MCU |
| 129 | + except Exception as e: # pylint: disable=broad-except |
| 130 | + reset_on_error(10, e) |
0 commit comments