From cbed6e326782149dcdef8b1411db0cf16b9adb61 Mon Sep 17 00:00:00 2001 From: John Park Date: Tue, 28 May 2024 19:57:56 -0700 Subject: [PATCH] first commit drum track sequencer --- Drum_Track_Sequencer/code.py | 77 ++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 Drum_Track_Sequencer/code.py diff --git a/Drum_Track_Sequencer/code.py b/Drum_Track_Sequencer/code.py new file mode 100644 index 000000000..ef9530ee2 --- /dev/null +++ b/Drum_Track_Sequencer/code.py @@ -0,0 +1,77 @@ +# SPDX-FileCopyrightText: 2024 John Park for Adafruit Industries +# +# SPDX-License-Identifier: MIT +""" +Drum Track Sequencer + Feather RP2040, Motor FeatherWing, stepper motor, + four reflection sensors, USB MIDI out +""" +import asyncio +import busio +import board +from adafruit_motorkit import MotorKit +from adafruit_motor import stepper +import keypad +import usb_midi + +# Tempo setup +BPM = 100 # user set value +tempo_table = { # motor speed seems non-linear, so we'll use a lookup table + 110: 0.0004, + 100: 0.001, + 90: 0.002, + 80: 0.003, + 75: 0.004, + 65: 0.005, + 60: 0.006, + 50: 0.008 +} +def get_nearest_tempo(given_bpm): + nearest_table_item = min(tempo_table.keys(), key=lambda k: abs(k - given_bpm)) + return tempo_table[nearest_table_item] +motor_pause = get_nearest_tempo(BPM) + +i2c=busio.I2C(board.SCL, board.SDA, frequency=400_000) + +# Motor setup +kit = MotorKit(i2c=i2c) +motor_run=True + +# Sensor setup +optical_pins = (board.D6, board.D9, board.D10, board.D12) +optical_sensors = keypad.Keys(optical_pins, value_when_pressed=False, pull=True) + +# MIDI setup +midi = usb_midi.ports[1] +midi_notes = (36, 37, 38, 39) # typical drum voice notes + +def play_drum(note): + midi_msg_on = bytearray([0x99, note, 120]) # 0x90 noteOn ch1, 0x99 noteOn ch10 + midi_msg_off = bytearray([0x89, note, 0]) + midi.write(midi_msg_on) + midi.write(midi_msg_off) + +async def check_sensors(): + while True: + optical_sensor = optical_sensors.events.get() + if optical_sensor: + if optical_sensor.pressed: + track_num = optical_sensor.key_number + # print("tripped", track_num) + play_drum(midi_notes[track_num]) + await asyncio.sleep(0.008) # don't check sensors constantly or motor speed reduced + +async def run_motor(): + while True: + kit.stepper1.onestep( + direction=stepper.BACKWARD, + style=stepper.DOUBLE + ) + await asyncio.sleep(motor_pause) # motor speed-- smaller numbers are faster + +async def main(): + motor_task = asyncio.create_task(run_motor()) + sensor_task = asyncio.create_task(check_sensors()) + await asyncio.gather(motor_task, sensor_task) + +asyncio.run(main())