code.py
  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)