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