Makes Marty play bells
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import pianohat | |
import martypy | |
import time | |
import random | |
''' | |
A set of Martys to connect to by name | |
You'll need to change this to have correct IPs for your Martys! | |
''' | |
martys = { | |
'Finlay': '192.168.8.192', | |
'Greeneyes': '192.168.8.174', | |
'Ghost': '192.168.8.210', | |
'Christine': '192.168.8.168', | |
'Jerry': '192.168.8.223', | |
'Marty Marty': '192.168.8.112', | |
'Flower Power': '192.168.8.183', | |
} | |
''' | |
Here we list the players that will be playing the bells. | |
Each player is a tuple. | |
- The 1st element is the name of a Marty, referencing `martys` | |
- The 2nd element is which hand to use - 'left' or 'right' | |
''' | |
players = { | |
'C': ('Marty Marty', 'right'), | |
'C#': ('Marty Marty', 'left'), | |
'D': ('Greeneyes', 'right'), | |
'D#': ('Greeneyes', 'left'), | |
'E': ('Ghost', 'right'), | |
'F': ('Ghost', 'left'), | |
'F#': ('Finlay', 'right'), | |
'G': ('Finlay', 'left'), | |
'G#': ('Flower Power', 'right'), | |
'A': ('Flower Power', 'left'), | |
'A#': ('Jerry', 'right'), | |
'B': ('Jerry', 'left'), | |
'C2': ('Christine', 'right'), | |
} | |
keymap = { | |
0: 'C', | |
1: 'C#', | |
2: 'D', | |
3: 'D#', | |
4: 'E', | |
5: 'F', | |
6: 'F#', | |
7: 'G', | |
8: 'G#', | |
9: 'A', | |
10: 'A#', | |
11: 'B', | |
12: 'C2', | |
} | |
# Makes a copy of keymap but going from key to number | |
rev_keymap = dict([(x, y) for y, x in keymap.items()]) | |
autoplay = True | |
bpm = 120 | |
def jingle(): | |
''' | |
We can blink LEDs at the user to do a | |
Guitar Hero type thingy | |
''' | |
# P is a pause | |
bpm = 200 | |
jinglebells = ['G','E','D','C','G','P' | |
'G','G','G','E','D','C','A','P', | |
'A','F','E','D','B','P', | |
'G','G','F','D','E','P', | |
'G','E','D','C','A','P', | |
'A','A','F','E','D','G','G','G','P', | |
'G','A','G','F','D','C','G','P', | |
'E','E','E','P','E','E','E','P', | |
'E','G','C','D','E','P', | |
'F','F','F','F','F','E','E', | |
'E','E','E','D','D','E','D','G', | |
'E','E','E','P','E','E','E','P', | |
'E','G','C','D','E','P', | |
'F','F','F','F','F','E','E', | |
'E','E','E','D','D','E','D','G','P','P','P','P','P','P'] | |
showtune(jinglebells) | |
def ships(): | |
# P is a pause | |
bpm = 160 | |
threeships = [ | |
'C', 'F', 'P', 'F', 'G', 'P', 'A', | |
'C2', 'P', 'A', 'G', 'P', 'A#', | |
'A', 'P', 'F', 'F', 'P', 'A', | |
'G', 'P', 'E', 'C', 'P', 'C', | |
'F', 'P', 'F', 'G', 'P', 'A', | |
'C2', 'P', 'A', 'G', 'P', 'A#', | |
'A', 'P', 'F', 'F', 'G', 'A', | |
'G', 'P', 'P', 'F', 'P', 'C', | |
'F', 'P', 'F', 'G', 'P', 'A', | |
'C2', 'P', 'A', 'G', 'P', 'A#', | |
'A', 'P', 'F', 'F', 'P', 'A', | |
'G', 'P', 'E', 'C', 'P', 'C', | |
'F', 'P', 'F', 'G', 'P', 'A', | |
'C2', 'P', 'A', 'G', 'P', 'A#', | |
'A', 'P', 'F', 'F', 'G', 'A', | |
'G', 'P', 'P', 'F', 'P', 'P','P','P','P','P','P','P'] | |
showtune(threeships) | |
def silentnight(): | |
bpm = 130 | |
snite = [ | |
'F','P','G','P','F','P','D','P','P','F','P','G','P','F','P','D','P','P', | |
'C','P','C','A','P','P','A#','P','A#','F','P','P', | |
'G','P','G','A#','A','G','F','P','G','F','D','P', | |
'G','P','G','A#','A','G','F','P','G','F','D','P', | |
'C','P','P','C','D#','C','A','A#','P','D', | |
'A#','F','D','F','E','C','A#','P','P','P','P','P','P' | |
] | |
showtune(snite) | |
def joytoworld(): | |
bpm = 130 | |
joy = [ | |
'C2','P','B','P','A','G','P','F','P','D','P','C','P','P', | |
'G','P','A','A','B','P','P','B','P','C2','P','P', | |
'C2','C2','B','A','G','G','F','E','P','P', | |
'C2','C2','B','P','A','G','P','G','F','E','P','P', | |
'E','P','E','E','E','E','F','P','G','P','P', | |
'F','E','P','D','P','D','D','D','E','P','F','P' | |
'E','D','P','C','C2','P','A','G','F','E','F','P','E','D','P','C','P', | |
'P','P','P','P','P','P' | |
] | |
showtune(joy) | |
def noel(): | |
# P is a pause | |
bpm = 190 | |
noel = [ | |
'E', 'D', 'C', 'P', 'D', 'E','F', 'G', 'P', | |
'C2', 'B', 'A', 'P', 'A', 'G', 'P', 'P', 'P', | |
'C2', 'P', 'B', 'P', 'A', 'P', 'G', 'P', | |
'A', 'P', 'B', 'P', 'C2', 'P', 'G', 'P', 'F', 'P', 'E', 'P', 'P', 'P', | |
'P','P','P','P','P','P' | |
] | |
showtune(noel) | |
def away(): | |
# P is a pause | |
awayinamanger = ['C2', 'P', | |
'C2', 'P', 'P', 'A#', 'A', 'P', | |
'A', 'P', 'G', 'P', 'F', 'P', | |
'F', 'P', 'E', 'P', 'D', 'P', | |
'C', 'P', 'P', 'P', 'C', 'P', | |
'C', 'P', 'P', 'D', 'C', 'P', | |
'C', 'P', 'G', 'P', 'E', 'P', | |
'D', 'P', 'C', 'P', 'F', 'P', | |
'A', 'P', 'P', 'P', 'C2', 'P', | |
'P','P','P','P','P','P'] | |
showtune(awayinamanger) | |
def showtune(tune, set_bpm=None): | |
''' | |
Shows a list of notes on the LEDs at a given BPM | |
''' | |
if set_bpm is not None: | |
period = 60.0/float(set_bpm) | |
update = False | |
else: | |
period = 60.0/float(bpm) | |
update = True | |
pianohat.auto_leds(False) | |
for note in tune: | |
if note in rev_keymap: | |
# If autoplay is on, play the note | |
if autoplay: | |
whack(note) | |
# Show Note on LEDs | |
i = rev_keymap[note] | |
pianohat.set_led(i, True) | |
time.sleep(0.75 * period) | |
pianohat.set_led(i, False) | |
time.sleep(0.25 * period) | |
if update: | |
period = 60.0/float(bpm) | |
else: | |
# Pause | |
time.sleep(period) | |
def whack(key): | |
''' | |
This function takes a Piano key, like C# | |
and tells the Marty to play that note! | |
''' | |
player = players[key] | |
if player is None: | |
return | |
player_name, arm = player | |
player = martys[player_name] | |
# `player` will now be a martypy.Marty instance | |
player.stop('clear queue') | |
player.enable_motors() | |
if arm == 'left': | |
player.arms(-10, 50, 100) | |
player.eyes(90) | |
player.arms(50, 50, 70) | |
player.eyes(random.randrange(-90, 50, 10)) | |
elif arm == 'right': | |
player.arms(50, -10, 100) | |
player.eyes(90) | |
player.arms(50, 50, 70) | |
player.eyes(random.randrange(-90, 50, 10)) | |
def handle_key(channel, pressed): | |
if pressed: | |
key = keymap[channel] | |
print(key) | |
whack(key) | |
else: | |
# We only want to play the not when first pressed | |
pass | |
def handle_opt(channel, pressed): | |
''' | |
handle the Instrument and Octave buttons | |
''' | |
global autoplay | |
global bpm | |
if pressed: | |
if channel == 15: # Instrument | |
autoplay = not autoplay | |
elif channel == 14: # Up Octave | |
if bpm < 300: | |
bpm += 10 | |
print("BPM is {}".format(bpm)) | |
elif channel == 13: # Down Octave | |
if bpm > 20: | |
bpm -= 10 | |
print("BPM is {}".format(bpm)) | |
def setup(): | |
''' | |
Called once when we start | |
''' | |
for i in range(0, 16): | |
# Turn all LEDs off | |
pianohat.set_led(i, False) | |
# Auto LEDs | |
pianohat.auto_leds(True) | |
# Smoother on/off ramp | |
#pianohat.set_led_ramp_rate(140, 140) | |
# Register handlers for the three different types of button | |
pianohat.on_note(handle_key) | |
pianohat.on_octave_up(handle_opt) | |
pianohat.on_octave_down(handle_opt) | |
pianohat.on_instrument(handle_opt) | |
# Now, connect to all the Martys: | |
for name, ip in martys.items(): | |
martys[name] = martypy.Marty('socket://{ip}'.format(ip=ip), default_lifelike=False) | |
martys[name].lifelike_behaviour(False) | |
martys[name].enable_motors(True) | |
martys[name].hello() | |
martys[name].arms(100, 100, 1000) | |
martys[name].arms(50, 50, 500) | |
time.sleep(2) | |
def main(): | |
''' | |
Main Event Loop | |
''' | |
joytoworld() | |
silentnight() | |
noel() | |
jingle() | |
ships() | |
away() | |
def cleanup(): | |
''' | |
Called once just before quitting | |
''' | |
pianohat.auto_leds(True) | |
if __name__ == '__main__': | |
try: | |
setup() | |
while True: | |
main() | |
except KeyboardInterrupt: | |
# Clean up and quit | |
cleanup() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment