Skip to content

Instantly share code, notes, and snippets.

@idriszmy

idriszmy/code.py

Last active Feb 10, 2021
Embed
What would you like to do?
Build a Light Theremin Using Maker Pi Pico and CircuitPython
#
# Build a Light Theremin Using Raspberry Pi Pico
# (Maker Pi Pico) and CircuitPython
#
# Raspberry Pi Pico
# - [Maker Pi Pico] https://my.cytron.io/p-maker-pi-pico?tracking=idris
# Grove - Light Sensor v1.2
# - https://my.cytron.io/p-grove-light-sensor-v1.2?tracking=idris
#
# Update:
# 9 Feb 2021 - Tested with CircuitPython Pico 6.2.0-beta.1-127-ga10ce39ae
#
from time import sleep
from board import *
from digitalio import DigitalInOut, Direction, Pull
from analogio import AnalogIn
from pwmio import PWMOut
from pitches import tones
from neopixel_write import neopixel_write
sleep(1)
btn1 = DigitalInOut(GP20)
btn1.direction = Direction.INPUT
btn1.pull = Pull.UP
btn2 = DigitalInOut(GP21)
btn2.direction = Direction.INPUT
btn2.pull = Pull.UP
btn3 = DigitalInOut(GP22)
btn3.direction = Direction.INPUT
btn3.pull = Pull.UP
pixel_off = bytearray([0, 0, 0])
pixel_red = bytearray([0, 20, 0])
pixel_green = bytearray([20, 0, 0])
pixel_blue = bytearray([0, 0, 20])
rgb = DigitalInOut(GP28)
rgb.direction = Direction.OUTPUT
neopixel_write(rgb, pixel_off)
light = AnalogIn(GP27)
tempo = 1
melody_start = ['c4', 'g4']
rhythm_start = [8, 8]
def playTone(melody, rhythm):
for tone, length in zip(melody, rhythm):
beeper = PWMOut(GP18, variable_frequency=True)
if tones[tone] != 0:
beeper.duty_cycle = 2 ** 15
beeper.frequency = tones[tone]
sleep(tempo / length)
beeper.deinit()
def map(x, in_min, in_max, out_min, out_max):
if x > in_max:
x = in_max
if x < in_min:
x = in_min
return (x-in_min) * (out_max-out_min) / (in_max-in_min) + out_min
playTone(melody_start, rhythm_start)
while btn1.value:
pass
notes_theremin = [
'c3', 'cs3', 'd3', 'ds3', 'e3', 'f3', 'fs3', 'g3', 'gs3', 'a3', 'as3', 'b3',
'c4', 'cs4', 'd4', 'ds4', 'e4', 'f4', 'fs4', 'g4', 'gs4', 'a4', 'as4', 'b4',
'c5', 'cs5', 'd5', 'ds5', 'e5', 'f5', 'fs5', 'g5', 'gs5', 'a5', 'as5', 'b5',
'c6', 'cs6', 'd6', 'ds6', 'e6', 'f6', 'fs6', 'g6', 'gs6', 'a6', 'as6', 'b6',
]
enable_theremin = False
delay = 0.2
while True:
if not btn1.value:
enable_theremin = not enable_theremin
if enable_theremin:
neopixel_write(rgb, pixel_green)
else:
neopixel_write(rgb, pixel_off)
sleep(1)
if enable_theremin:
light_ADC = light.value
note = int(map(light_ADC, 1000, 40000, 0, 47))
print("ADC: {}\tMap: {}\t\tNote: {}".format(light_ADC, note, notes_theremin[note]))
beeper = PWMOut(GP18, variable_frequency=True)
beeper.duty_cycle = 2 ** 15
beeper.frequency = tones[notes_theremin[note]]
sleep(delay)
beeper.deinit()
sleep(0.01)
if not btn2.value:
neopixel_write(rgb, pixel_green)
delay -= 0.01
if delay < 0.1:
neopixel_write(rgb, pixel_red)
delay = 0.1
elif not btn3.value:
neopixel_write(rgb, pixel_green)
delay += 0.01
if delay > 0.2:
delay = 0.2
neopixel_write(rgb, pixel_blue)
tones = {
'': 0,
'b0': 31,
'c1': 33,
'cs1': 35,
'd1': 37,
'ds1': 39,
'e1': 41,
'f1': 44,
'fs1': 46,
'g1': 49,
'gs1': 52,
'a1': 55,
'as1': 58,
'b1': 62,
'c2': 65,
'cs2': 69,
'd2': 73,
'ds2': 78,
'e2': 82,
'f2': 87,
'fs2': 93,
'g2': 98,
'gs2': 104,
'a2': 110,
'as2': 117,
'b2': 123,
'c3': 131,
'cs3': 139,
'd3': 147,
'ds3': 156,
'e3': 165,
'f3': 175,
'fs3': 185,
'g3': 196,
'gs3': 208,
'a3': 220,
'as3': 233,
'b3': 247,
'c4': 262,
'cs4': 277,
'd4': 294,
'ds4': 311,
'e4': 330,
'f4': 349,
'fs4': 370,
'g4': 392,
'gs4': 415,
'a4': 440,
'as4': 466,
'b4': 494,
'c5': 523,
'cs5': 554,
'd5': 587,
'ds5': 622,
'e5': 659,
'f5': 698,
'fs5': 740,
'g5': 784,
'gs5': 831,
'a5': 880,
'as5': 932,
'b5': 988,
'c6': 1047,
'cs6': 1109,
'd6': 1175,
'ds6': 1245,
'e6': 1319,
'f6': 1397,
'fs6': 1480,
'g6': 1568,
'gs6': 1661,
'a6': 1760,
'as6': 1865,
'b6': 1976,
'c7': 2093,
'cs7': 2217,
'd7': 2349,
'ds7': 2489,
'e7': 2637,
'f7': 2794,
'fs7': 2960,
'g7': 3136,
'gs7': 3322,
'a7': 3520,
'as7': 3729,
'b7': 3951,
'c8': 4186,
'cs8': 4435,
'd8': 4699,
'ds8': 4978,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment