code.py
 1  # SPDX-FileCopyrightText: 2022 Dan Halbert for Adafruit Industries
 2  #
 3  # SPDX-License-Identifier: MIT
 4  
 5  import asyncio
 6  
 7  import board
 8  import keypad
 9  import neopixel
10  from rainbowio import colorwheel
11  
12  pixel_pin = board.A0
13  num_pixels = 24
14  
15  pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.03, auto_write=False)
16  
17  
18  class Controls:
19      def __init__(self):
20          self.reverse = False
21          self.wait = 0.0
22  
23  
24  async def rainbow_cycle(controls):
25      while True:
26          # Increment by 2 instead of 1 to speed the cycle up a bit.
27          for j in range(255, -1, -2) if controls.reverse else range(0, 256, 2):
28              for i in range(num_pixels):
29                  rc_index = (i * 256 // num_pixels) + j
30                  pixels[i] = colorwheel(rc_index & 255)
31              pixels.show()
32              await asyncio.sleep(controls.wait)
33  
34  
35  async def monitor_buttons(reverse_pin, slower_pin, faster_pin, controls):
36      """Monitor buttons that reverse direction and change animation speed.
37      Assume buttons are active low.
38      """
39      with keypad.Keys(
40          (reverse_pin, slower_pin, faster_pin), value_when_pressed=False, pull=True
41      ) as keys:
42          while True:
43              key_event = keys.events.get()
44              if key_event and key_event.pressed:
45                  key_number = key_event.key_number
46                  if key_number == 0:
47                      controls.reverse = not controls.reverse
48                  elif key_number == 1:
49                      # Lengthen the interval.
50                      controls.wait = controls.wait + 0.001
51                  elif key_number == 2:
52                      # Shorten the interval.
53                      controls.wait = max(0.0, controls.wait - 0.001)
54              # Let another task run.
55              await asyncio.sleep(0)
56  
57  
58  async def main():
59      controls = Controls()
60  
61      buttons_task = asyncio.create_task(
62          monitor_buttons(board.A1, board.A2, board.A3, controls)
63      )
64      animation_task = asyncio.create_task(rainbow_cycle(controls))
65  
66      # This will run forever, because no tasks ever finish.
67      await asyncio.gather(buttons_task, animation_task)
68  
69  
70  asyncio.run(main())