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()