code.py
 1  # SPDX-FileCopyrightText: Copyright (c) 2022 Dan Halbert for Adafruit Industries
 2  # SPDX-FileCopyrightText: Copyright (c) 2022 Kattni Rembor for Adafruit Industries
 3  #
 4  # SPDX-License-Identifier: MIT
 5  """
 6  CircuitPython asyncio example for two NeoPixel rings and one button.
 7  """
 8  import asyncio
 9  import board
10  import neopixel
11  import keypad
12  from rainbowio import colorwheel
13  
14  button_pin = board.BUTTON  # The pin the button is connected to.
15  num_pixels = 16  # The number of NeoPixels on a single ring.
16  brightness = 0.2  # The LED brightness.
17  
18  # Set up NeoPixel rings.
19  ring_one = neopixel.NeoPixel(board.A1, num_pixels, brightness=brightness, auto_write=False)
20  ring_two = neopixel.NeoPixel(board.A2, num_pixels, brightness=brightness, auto_write=False)
21  
22  
23  class AnimationControls:
24      """The controls to allow you to vary the rainbow and blink animations."""
25      def __init__(self):
26          self.reverse = False
27          self.wait = 0.0
28          self.delay = 0.5
29  
30  
31  async def rainbow_cycle(controls):
32      """Rainbow cycle animation on ring one."""
33      while True:
34          for j in range(255, -1, -1) if controls.reverse else range(0, 256, 1):
35              for i in range(num_pixels):
36                  rc_index = (i * 256 // num_pixels) + j
37                  ring_one[i] = colorwheel(rc_index & 255)
38              ring_one.show()
39              await asyncio.sleep(controls.wait)
40  
41  
42  async def blink(controls):
43      """Blink animation on ring two."""
44      while True:
45          ring_two.fill((0, 0, 255))
46          ring_two.show()
47          await asyncio.sleep(controls.delay)
48          ring_two.fill((0, 0, 0))
49          ring_two.show()
50          await asyncio.sleep(controls.delay)
51          await asyncio.sleep(controls.wait)
52  
53  
54  async def monitor_button(button, controls):
55      """Monitor button that reverses rainbow direction and changes blink speed.
56      Assume button is active low.
57      """
58      with keypad.Keys((button,), value_when_pressed=False, pull=True) as key:
59          while True:
60              key_event = key.events.get()
61              if key_event:
62                  if key_event.pressed:
63                      controls.reverse = True
64                      controls.delay = 0.1
65                  elif key_event.released:
66                      controls.reverse = False
67                      controls.delay = 0.5
68              await asyncio.sleep(0)
69  
70  
71  async def main():
72      animation_controls = AnimationControls()
73      button_task = asyncio.create_task(monitor_button(button_pin, animation_controls))
74      animation_task = asyncio.create_task(rainbow_cycle(animation_controls))
75      blink_task = asyncio.create_task(blink(animation_controls))
76  
77      # This will run forever, because no tasks ever finish.
78      await asyncio.gather(button_task, animation_task, blink_task)
79  
80  asyncio.run(main())