/ Crickits / carousel / code.py
code.py
  1  # SPDX-FileCopyrightText: 2018 Limor Fried for Adafruit Industries
  2  #
  3  # SPDX-License-Identifier: MIT
  4  
  5  import time
  6  #import math
  7  import array
  8  from digitalio import DigitalInOut, Direction, Pull
  9  import analogio
 10  import supervisor
 11  import audioio
 12  import audiocore
 13  import board
 14  from rainbowio import colorwheel
 15  import neopixel
 16  
 17  # NeoPixels
 18  pixel_pin = board.A1
 19  num_pixels = 30
 20  pixels = neopixel.NeoPixel(pixel_pin, num_pixels,
 21                             brightness=1, auto_write=False)
 22  pixels.fill((0, 0, 0))
 23  pixels.show()
 24  
 25  ring = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=1)
 26  ring.fill((255, 0, 0))
 27  
 28  # Light sensor
 29  light = analogio.AnalogIn(board.LIGHT)
 30  
 31  BRIGHT = 40000
 32  DARK = 10000
 33  ACTIVITY_THRESHOLD = 20000
 34  
 35  # button
 36  button_a = DigitalInOut(board.BUTTON_A)
 37  button_a.direction = Direction.INPUT
 38  button_a.pull = Pull.DOWN
 39  
 40  # audio output
 41  cpx_audio = audioio.AudioOut(board.A0)
 42  def play_file(wavfile):
 43      with open(wavfile, "rb") as f:
 44          wav = audiocore.WaveFile(f)
 45          cpx_audio.play(wav)
 46          while cpx_audio.playing:
 47              pass
 48  # Generate one period of wave.
 49  length = 8000 // 440
 50  wave_array = array.array("H", [0] * length)
 51  for i in range(length):
 52      # Sine wave
 53      # wave_array[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15)
 54      # Triangle wave
 55      # wave_array[i] = int( i/length * (2 ** 16))
 56      # Saw wave
 57      if i < length/2:
 58          wave_array[i] = int(i*2/length * (2 ** 16 - 1))
 59      else:
 60          wave_array[i] = int((2**16 - 1) - i*2/length * (2 ** 16))
 61      print((wave_array[i],))
 62  
 63  def map_range(x, in_min, in_max, out_min, out_max):
 64      # Maps a number from one range to another.
 65      mapped = (x-in_min) * (out_max - out_min) / (in_max-in_min) + out_min
 66      if out_min <= out_max:
 67          return max(min(mapped, out_max), out_min)
 68      return min(max(mapped, out_max), out_min)
 69  
 70  
 71  time.sleep(2)
 72  
 73  play_file("01_approach.wav")
 74  
 75  while not button_a.value:
 76      pass  # wait for it to be pressed
 77  
 78  if button_a.value:  # A pressed
 79      while button_a.value:  # wait for release
 80          pass
 81  
 82  time.sleep(1)
 83  
 84  play_file("02_last_day.wav")
 85  
 86  time.sleep(1)
 87  
 88  timeout = time.monotonic()
 89  
 90  while True:
 91      print((light.value,))
 92  
 93      # determine height of pixels
 94      pixel_height = map_range(light.value, DARK, BRIGHT, 0, num_pixels)
 95      pixels.fill((0, 0, 0))
 96      for p in range(pixel_height):
 97          pixels[p] = colorwheel(int(p / num_pixels * 255))
 98          pixels.show()
 99  
100      # determine squeek
101      freq = int(map_range(light.value, DARK, BRIGHT, 440, 8800))
102      sine_wave = audiocore.RawSample(wave_array, channel_count=1, sample_rate=freq)
103      cpx_audio.stop()
104      cpx_audio.play(sine_wave, loop=True)
105  
106      # check no activity
107      if light.value > ACTIVITY_THRESHOLD:
108          timeout = time.monotonic()  # reset our timeout
109  
110      # 4 seconds no activity
111      if time.monotonic() - timeout > 4:
112          break
113  
114  pixels.fill((255, 0, 0))
115  pixels.show()
116  play_file("03_no_sanctuary.wav")
117  
118  time.sleep(1)
119  
120  # restart
121  supervisor.reload()