Skip to content

Commit 1155411

Browse files
authored
Merge pull request #3036 from adafruit/toy_xylo
adding code and midi files
2 parents 7765812 + 531c15c commit 1155411

File tree

5 files changed

+97
-0
lines changed

5 files changed

+97
-0
lines changed

Toy_Robot_Xylophone/code.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# SPDX-FileCopyrightText: 2025 Liz Clark for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
import os
6+
from random import randint
7+
import board
8+
import usb_midi
9+
import keypad
10+
from adafruit_mcp230xx.mcp23017 import MCP23017
11+
import adafruit_midi
12+
from adafruit_midi.note_on import NoteOn
13+
from adafruit_midi.note_off import NoteOff
14+
import adafruit_midi_parser
15+
16+
# music_box plays back MIDI files on CP drive
17+
# set to false for live MIDI over USB control
18+
music_box = True
19+
# define the notes that correspond to each solenoid
20+
notes = [48, 50, 52, 53, 55, 57, 59, 60]
21+
22+
key = keypad.Keys((board.BUTTON,), value_when_pressed=False, pull=True)
23+
24+
i2c = board.STEMMA_I2C()
25+
mcp = MCP23017(i2c)
26+
noids = []
27+
for i in range(8):
28+
noid = mcp.get_pin(i)
29+
noid.switch_to_output(value=False)
30+
noids.append(noid)
31+
# pylint: disable=used-before-assignment, unused-argument, global-statement, no-self-use
32+
if not music_box:
33+
midi = adafruit_midi.MIDI(
34+
midi_in=usb_midi.ports[0], in_channel=0, midi_out=usb_midi.ports[1], out_channel=0
35+
)
36+
else:
37+
midi_files = []
38+
for filename in os.listdir('/'):
39+
if filename.lower().endswith('.mid') and not filename.startswith('.'):
40+
midi_files.append("/"+filename)
41+
print(midi_files)
42+
43+
class Custom_Player(adafruit_midi_parser.MIDIPlayer):
44+
def on_note_on(self, note, velocity, channel): # noqa: PLR6301
45+
for z in range(len(notes)):
46+
if notes[z] == note:
47+
print(f"Playing note: {note}")
48+
noids[z].value = True
49+
50+
def on_note_off(self, note, velocity, channel): # noqa: PLR6301
51+
for z in range(len(notes)):
52+
if notes[z] == note:
53+
noids[z].value = False
54+
55+
def on_end_of_track(self, track): # noqa: PLR6301
56+
print(f"End of track {track}")
57+
for z in range(8):
58+
noids[z].value = False
59+
60+
def on_playback_complete(self): # noqa: PLR6301
61+
global now_playing
62+
now_playing = False
63+
for z in range(8):
64+
noids[z].value = False
65+
parser = adafruit_midi_parser.MIDIParser()
66+
parser.parse(midi_files[randint(0, (len(midi_files) - 1))])
67+
player = Custom_Player(parser)
68+
new_file = False
69+
now_playing = False
70+
71+
while True:
72+
if music_box:
73+
event = key.events.get()
74+
if event:
75+
if event.pressed:
76+
now_playing = not now_playing
77+
if now_playing:
78+
new_file = True
79+
if new_file:
80+
parser.parse(midi_files[randint(0, (len(midi_files) - 1))])
81+
print(f"Successfully parsed! Found {len(parser.events)} events.")
82+
print(f"BPM: {parser.bpm:.1f}")
83+
print(f"Note Count: {parser.note_count}")
84+
new_file = False
85+
if now_playing:
86+
player.play(loop=False)
87+
88+
else:
89+
msg = midi.receive()
90+
if msg is not None:
91+
for i in range(8):
92+
noid_output = noids[i]
93+
notes_played = notes[i]
94+
if isinstance(msg, NoteOn) and msg.note == notes_played:
95+
noid_output.value = True
96+
elif isinstance(msg, NoteOff) and msg.note == notes_played:
97+
noid_output.value = False

Toy_Robot_Xylophone/song_1.mid

313 Bytes
Binary file not shown.

Toy_Robot_Xylophone/song_2.mid

277 Bytes
Binary file not shown.

Toy_Robot_Xylophone/song_3.mid

367 Bytes
Binary file not shown.

Toy_Robot_Xylophone/song_4.mid

473 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)