Skip to content

Commit 21123b6

Browse files
authored
Merge pull request #2823 from jedgarpark/drum-track-sequencer
first commit drum track sequencer
2 parents 583969f + cbed6e3 commit 21123b6

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed

Drum_Track_Sequencer/code.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# SPDX-FileCopyrightText: 2024 John Park for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
"""
5+
Drum Track Sequencer
6+
Feather RP2040, Motor FeatherWing, stepper motor,
7+
four reflection sensors, USB MIDI out
8+
"""
9+
import asyncio
10+
import busio
11+
import board
12+
from adafruit_motorkit import MotorKit
13+
from adafruit_motor import stepper
14+
import keypad
15+
import usb_midi
16+
17+
# Tempo setup
18+
BPM = 100 # user set value
19+
tempo_table = { # motor speed seems non-linear, so we'll use a lookup table
20+
110: 0.0004,
21+
100: 0.001,
22+
90: 0.002,
23+
80: 0.003,
24+
75: 0.004,
25+
65: 0.005,
26+
60: 0.006,
27+
50: 0.008
28+
}
29+
def get_nearest_tempo(given_bpm):
30+
nearest_table_item = min(tempo_table.keys(), key=lambda k: abs(k - given_bpm))
31+
return tempo_table[nearest_table_item]
32+
motor_pause = get_nearest_tempo(BPM)
33+
34+
i2c=busio.I2C(board.SCL, board.SDA, frequency=400_000)
35+
36+
# Motor setup
37+
kit = MotorKit(i2c=i2c)
38+
motor_run=True
39+
40+
# Sensor setup
41+
optical_pins = (board.D6, board.D9, board.D10, board.D12)
42+
optical_sensors = keypad.Keys(optical_pins, value_when_pressed=False, pull=True)
43+
44+
# MIDI setup
45+
midi = usb_midi.ports[1]
46+
midi_notes = (36, 37, 38, 39) # typical drum voice notes
47+
48+
def play_drum(note):
49+
midi_msg_on = bytearray([0x99, note, 120]) # 0x90 noteOn ch1, 0x99 noteOn ch10
50+
midi_msg_off = bytearray([0x89, note, 0])
51+
midi.write(midi_msg_on)
52+
midi.write(midi_msg_off)
53+
54+
async def check_sensors():
55+
while True:
56+
optical_sensor = optical_sensors.events.get()
57+
if optical_sensor:
58+
if optical_sensor.pressed:
59+
track_num = optical_sensor.key_number
60+
# print("tripped", track_num)
61+
play_drum(midi_notes[track_num])
62+
await asyncio.sleep(0.008) # don't check sensors constantly or motor speed reduced
63+
64+
async def run_motor():
65+
while True:
66+
kit.stepper1.onestep(
67+
direction=stepper.BACKWARD,
68+
style=stepper.DOUBLE
69+
)
70+
await asyncio.sleep(motor_pause) # motor speed-- smaller numbers are faster
71+
72+
async def main():
73+
motor_task = asyncio.create_task(run_motor())
74+
sensor_task = asyncio.create_task(check_sensors())
75+
await asyncio.gather(motor_task, sensor_task)
76+
77+
asyncio.run(main())

0 commit comments

Comments
 (0)