Skip to content

Instantly share code, notes, and snippets.

@joeycastillo
Created December 11, 2022 08:11
Show Gist options
  • Save joeycastillo/afc037cf75ec1d6a3580fe2d9dfed54d to your computer and use it in GitHub Desktop.
Save joeycastillo/afc037cf75ec1d6a3580fe2d9dfed54d to your computer and use it in GitHub Desktop.
Neopixel Christmas Tree with CircuitPython Deep Sleep
import board
from digitalio import DigitalInOut, Direction, Pull
from adafruit_debouncer import Debouncer
boot0 = DigitalInOut(board.BOOT0)
boot0.direction = Direction.INPUT
boot0.pull = Pull.UP
button = Debouncer(boot0)
def update():
press = False
long_press = False
button.update()
if button.rose:
if button.last_duration < 0.5:
press = True
else:
long_press = True
return (press, long_press)
def prepare_for_sleep():
boot0.deinit()
import board
from digitalio import DigitalInOut, Direction, Pull
from oso_lcd.lcdwing_lite import LCDWingLite, Indicator
import time
import alarm
import rtc
import lights
import network
import button
display = LCDWingLite(board.I2C())
clock = rtc.RTC()
if clock.datetime.tm_year < 2020:
display.print("5tClk")
display.set_indicator(Indicator.WIFI)
network.set_time_if_needed()
display.clear_indicator(Indicator.WIFI)
alarm.sleep_memory[0] = 10 # The default hour for the lights to turn on, 10 AM
alarm.sleep_memory[1] = 0 # The default minute for the lights to turn on (10:00 AM)
alarm.sleep_memory[2] = 1 # The default duration for the lights to remain on (1 hour)
def display_time(hour, minute):
hour_12 = hour % 12
display.print("{:2d}:{:02d}".format(hour_12 if hour_12 else 12, minute))
if hour < 12:
display.clear_indicator(Indicator.PM)
display.set_indicator(Indicator.AM)
else:
display.clear_indicator(Indicator.AM)
display.set_indicator(Indicator.PM)
MODE_SHOW_TIME = 0
MODE_SET_ON_TIME = 1
MODE_SET_DURATION = 2
NUM_MODES = 3
mode = 0
time_needs_display = True
deep_sleep_at = time.monotonic() + 120
lights_on = False
while True:
dt = clock.datetime
(press, long_press) = button.update()
if press or long_press:
deep_sleep_at = max(deep_sleep_at, time.monotonic() + 120)
if long_press:
mode = (mode + 1) % NUM_MODES
display.clear_indicator(Indicator.ALL)
time_needs_display = True
if mode == MODE_SHOW_TIME:
if time_needs_display or dt.tm_sec == 0:
display_time(dt.tm_hour, dt.tm_min)
time_needs_display = False
elif mode == MODE_SET_ON_TIME:
display.set_indicator(Indicator.BELL)
if press:
alarm.sleep_memory[1] += 15
if alarm.sleep_memory[1] == 60:
alarm.sleep_memory[1] = 0
alarm.sleep_memory[0] = (alarm.sleep_memory[0] + 1) % 24
alarm.sleep_memory[0] = alarm.sleep_memory[0]
alarm.sleep_memory[1] = alarm.sleep_memory[1]
display_time(alarm.sleep_memory[0], alarm.sleep_memory[1])
elif mode == MODE_SET_DURATION:
if press:
if alarm.sleep_memory[2] == 12:
alarm.sleep_memory[2] = 1
else:
alarm.sleep_memory[2] += 1
alarm.sleep_memory[2] = alarm.sleep_memory[2]
display.print("{:2d} hr".format(alarm.sleep_memory[2]))
if lights_on:
display.set_indicator(Indicator.DATA)
lights.animate()
elif dt.tm_hour == alarm.sleep_memory[0] and dt.tm_min >= alarm.sleep_memory[1] and mode == 0:
lights.turn_on()
lights_on = True
deep_sleep_at = 1 + time.monotonic() + alarm.sleep_memory[2] * 60 * 60
if isinstance(alarm.wake_alarm, alarm.time.TimeAlarm) and not lights_on:
deep_sleep_at = time.monotonic()
if time.monotonic() >= deep_sleep_at:
button.prepare_for_sleep()
lights.prepare_for_sleep()
display.clear_indicator(Indicator.DATA)
display.set_indicator(Indicator.MOON)
pin_alarm = alarm.pin.PinAlarm(pin=board.BOOT0, value=False, pull=True)
time_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + 60)
alarm.exit_and_deep_sleep_until_alarms(pin_alarm, time_alarm)
time.sleep(0.01667)
import random
import board
import neopixel
import time
from digitalio import DigitalInOut, Direction, Pull
NUM_PIXELS = 30 # The number of Neopixels in our Neopixel strip
NUM_TWINKLES = 15 # The number of active twinkles
MAX_TWINKLE_FRAMES = 30
MIN_TWINKLE_FRAMES = 15
TWINKLE_COLORS = [[255, 0, 0], # Red
[255, 180, 100], # Warm White
]
strip = neopixel.NeoPixel(board.D5, NUM_PIXELS, brightness=1, auto_write=False)
enable_lights = DigitalInOut(board.D10)
enable_lights.direction = Direction.OUTPUT
enable_lights.value = False
twinkles = list()
class Twinkle:
def __init__(self, location, color, frames):
self.location = location # pixel number on strand
self.color = color # color of the twinkle
self.frames = frames # number of frames to animate
self.current_frame = 0 # current frame in animation
self.state = 1 # 1 for starting / running, -1 for ending
def advance(self):
if self.current_frame == self.frames:
self.state = -1 # mark twinkle as ending
if self.current_frame == 0 and self.state == -1:
# if twinkle has ended, pick a new color / location and start again
self.location = random.randint(0, NUM_PIXELS - 1)
self.color = TWINKLE_COLORS[random.randint(0, len(TWINKLE_COLORS) - 1)]
self.frames = random.randint(MIN_TWINKLE_FRAMES, MAX_TWINKLE_FRAMES)
self.current_frame = 0
self.state = 1
self.current_frame = self.current_frame + self.state # advance to next frame
for i in range(NUM_TWINKLES):
location = random.randint(0, NUM_PIXELS - 1)
color = random.randint(1, len(TWINKLE_COLORS) - 1)
flash_len = random.randint(MIN_TWINKLE_FRAMES, MAX_TWINKLE_FRAMES)
twinkles.append(Twinkle(location, TWINKLE_COLORS[color], flash_len))
def turn_on():
enable_lights.value = True
def prepare_for_sleep():
strip.deinit()
enable_lights.value = False
enable_lights.deinit()
def animate():
for i in range(NUM_TWINKLES):
location = twinkles[i].location
brightness = (twinkles[i].current_frame/twinkles[i].frames)
scaled_color = (int(twinkles[i].color[0]*brightness),
int(twinkles[i].color[1]*brightness),
int(twinkles[i].color[2]*brightness))
strip[location] = scaled_color
twinkles[i].advance()
strip.show()
import rtc
import time
import ssl
import wifi
import socketpool
import adafruit_requests
try:
from secrets import secrets
except ImportError:
print("WiFi secrets are kept in secrets.py, please add them there!")
raise
def set_time_if_needed():
aio_username = secrets["aio_username"]
aio_key = secrets["aio_key"]
location = secrets.get("timezone", None)
TIME_URL = f"https://io.adafruit.com/api/v2/{aio_username}/integrations/time/strftime?x-aio-key={aio_key}&tz={location}&fmt=%25Y-%25m-%25d+%25H%3A%25M%3A%25S"
wifi.radio.connect(secrets["ssid"], secrets["password"])
pool = socketpool.SocketPool(wifi.radio)
requests = adafruit_requests.Session(pool, ssl.create_default_context())
response = requests.get(TIME_URL)
components = response.text.split(' ')
(year, month, day) = components[0].split('-')
(hour, minute, second) = components[1].split(':')
rtc.RTC().datetime = time.struct_time((int(year), int(month), int(day), int(hour), int(minute), int(second), 0, -1, -1))
# This file is where you keep secret settings, passwords, and tokens!
# If you put them in the code you risk committing that info or sharing it
secrets = {
"ssid" : "YOUR_WIFI_NETWORK",
"password" : "YOUR_WIFI_PASSWORD",
"aio_username" : "ADAFRUIT_IO_USERNAME",
"aio_key" : "ADAFRUIT_IO_KEY",
"timezone" : "America/Chicago", # http://worldtimeapi.org/timezones
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment