123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- """
- Spectroshaker by The Dod:
- Adafruit CircuitPlayground Bluefruit dual-mode "bling"
- The RGB levels of neopixels around the circuit indicate:
- - Low/Mid/High sound levels (spectrogram mode)
- - X/Y/Z acceleration (shaker mode)
-
- Controls:
- slider switch: normal/standby mode
- button a: toggle between spectrogram/shaker mode
- button b: cycle between 4 brightness levels
-
- """
- import math
- import time
- from adafruit_circuitplayground import cp
- from teaandtechtime_fft import spectrogram
-
- NUM_PIXELS = 10
- # Like a clock, with connectors at 12 (USB) and 6 (power)
- LED_ANGLES = [
- i*math.pi/6.0
- for i in [11, 10, 9, 8, 7, 5, 4, 3, 2, 1]]
-
- minx = miny = minz = -5.0
- maxx = maxy = maxz = 5.0
-
- fft_size = 8 # power of 2
- samples = [0.0+0.0j]*fft_size
- MAX_2FREQ = 10.0 # After testing this a bit in the wild
-
- cp.pixels.brightness = 0.1
-
- MODE_SPECTRO = 1
- MODE_SHAKER = 2
- current_mode = MODE_SHAKER
- is_standby = cp.switch
- last_click = 0
- DEBOUNCE = 0.25
-
- def angles2level(led, val):
- led_angle = LED_ANGLES[led]
- val_angle = val * 2.0 * math.pi
- angle = led_angle - val_angle
- while angle > 2 * math.pi:
- angle -= 2*math.pi
- # the pow() makes sin() values sharper
- return int(255*pow(math.sin(angle/2), 4))
-
- while True:
- if time.monotonic() > last_click+DEBOUNCE:
- if is_standby != cp.switch:
- is_standby = cp.switch
- last_click = time.monotonic()
- if is_standby:
- for i in range(NUM_PIXELS):
- cp.pixels[i] = (0, 0, 0)
- if cp.button_a:
- last_click = time.monotonic()
- current_mode = (
- current_mode == MODE_SHAKER and MODE_SPECTRO
- or MODE_SHAKER)
- elif cp.button_b:
- last_click = time.monotonic()
- is_standby = False
- if cp.pixels.brightness >= 0.4:
- cp.pixels.brightness = 0.1
- else:
- cp.pixels.brightness += 0.1
-
- if not is_standby:
- samples.pop(0)
- samples.append(cp.sound_level+0.0j)
- x, y, z = cp.acceleration
- if x < minx:
- minx = x
- if y < miny:
- miny = y
- if z < minz:
- minz = z
- if x > maxx:
- maxx = x
- if y > maxy:
- maxy = y
- if z > maxz:
- maxz = z
- if current_mode == MODE_SHAKER: # accelerometer mode
- vals = (
- (x-minx)/(maxx-minx),
- (y-miny)/(maxy-miny),
- (z-minz)/(maxz-minz))
- else: # spectrogram mode
- raw_freqs = spectrogram(samples)
- pairs = [raw_freqs[i]+raw_freqs[i+1] for i in range(fft_size//2)]
- vals = [min(1.0, abs(x/MAX_2FREQ)) for x in pairs[:3]]
- for i in range(NUM_PIXELS):
- cp.pixels[i] = (
- angles2level(i, vals[0]),
- angles2level(i, vals[1]),
- angles2level(i, vals[2]))
- time.sleep(0.01)
|