Last active
August 22, 2024 20:07
-
-
Save nucklearproject/92a3adb833af4071562824381bd9d100 to your computer and use it in GitHub Desktop.
Send notes, clock sync, start, stop, etc from midi USB to UART seriall pins on Raspberry pico /// Circuitpython
This file contains hidden or 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
import board, time | |
import busio | |
import usb_midi | |
from simpleio import map_range | |
from analogio import AnalogIn | |
import adafruit_midi | |
from adafruit_midi.note_off import NoteOff | |
from adafruit_midi.note_on import NoteOn | |
from adafruit_midi.polyphonic_key_pressure import PolyphonicKeyPressure | |
from adafruit_midi.control_change import ControlChange | |
from adafruit_midi.program_change import ProgramChange | |
from adafruit_midi.channel_pressure import ChannelPressure | |
from adafruit_midi.pitch_bend import PitchBend | |
from adafruit_midi.midi_message import MIDIUnknownEvent | |
from adafruit_midi.timing_clock import TimingClock | |
from adafruit_midi.start import Start | |
from adafruit_midi.stop import Stop | |
# Configuración UART para MIDI | |
uart = busio.UART(tx=board.GP0, rx=board.GP1, baudrate=31250, timeout=0.001) # Asegúrate de usar los pines correctos | |
sermidi = adafruit_midi.MIDI(midi_in=uart, midi_out=uart, in_channel = (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)) | |
usbmidi = adafruit_midi.MIDI(midi_in=usb_midi.ports[0], midi_out=usb_midi.ports[1], in_channel = (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)) | |
is_debug = False | |
# Lista para almacenar los potenciómetros (puedes agregar más) | |
knobs_pins = [board.GP27, board.GP28] # Aquí agregas los pines de los potenciómetros | |
knobs = [AnalogIn(pin) for pin in knobs_pins] | |
# Inicializa las variables de histeresis y últimos valores enviados para cada potenciómetro | |
offsets = [0] * len(knobs) | |
last_sent_values = [0] * len(knobs) | |
threshold = 1 # Puedes ajustar este valor según sea necesario, evita el movimiento de ruido de los potes, aumenta para evitar | |
# Función de histeresis | |
def range_index(ctl, ctrl_max, old_value, offset): | |
if (ctl + offset > 65535) or (ctl + offset < 0): | |
offset = 0 | |
# Mapea el valor del potenciómetro a 0-127 y aplica histeresis | |
new_value = int(map_range((ctl + offset) & 0xFF00, 1200, 65500, 0, ctrl_max)) | |
if new_value != old_value: | |
offset = int(0.25 * sign(new_value - old_value) * (65535 / ctrl_max)) | |
return new_value, offset | |
def sign(x): | |
return 1 if x >= 0 else -1 | |
# Función que mapea el valor del knob, filtra y detecta movimiento con umbral | |
def mapping(knob, last_sent_value, offset, threshold): | |
raw_value = knob.value | |
filtered_value, offset = range_index(raw_value, 128, last_sent_value, offset) | |
# Solo considera un cambio si la diferencia es mayor que el umbral | |
if abs(filtered_value - last_sent_value) >= threshold: | |
return filtered_value, offset | |
return None, offset # Si no hay cambio significativo, devuelve None | |
while True: | |
msg = usbmidi.receive() | |
uartmsg = sermidi.receive() | |
for i, knob in enumerate(knobs): | |
# Llama a la función mapping para cada potenciómetro | |
filtered_value, offsets[i] = mapping(knob, last_sent_values[i], offsets[i], threshold) | |
if filtered_value is not None: | |
if is_debug: print(f"Knob {i+1} - Sending Filtered Value: {filtered_value}") | |
usbmidi.send(ControlChange(i+1, filtered_value)) | |
last_sent_values[i] = filtered_value # Actualiza el último valor enviado | |
if msg: | |
if (isinstance(msg, MIDIUnknownEvent)): | |
if is_debug: print(msg) | |
# Ignore unknown MIDI events | |
# This filters out the ActiveSensing from my UMT-ONE for example! | |
pass | |
elif isinstance(msg, (NoteOn, NoteOff, ControlChange, PitchBend)): | |
sermidi.out_channel = msg.channel | |
sermidi.send(msg) | |
if is_debug: print(f"Mensaje enviado por USB: {msg}") | |
elif isinstance(msg, (TimingClock, Start, Stop)): | |
#Se evita envia el canal por que se rompe todo... | |
sermidi.send(msg) #NOenviar el canal | |
else: | |
pass | |
if uartmsg: | |
if isinstance(uartmsg, (NoteOn, NoteOff, ControlChange, PitchBend)): | |
usbmidi.out_channel = uartmsg.channel | |
usbmidi.send(uartmsg) | |
if is_debug: print(f"Mensaje enviado por UART: {uartmsg}") | |
elif isinstance(msg, (TimingClock, Start, Stop)): | |
#Se evita envia el canal por ser innecesario | |
usbmidi.send(uartmsg) | |
else: | |
pass | |
time.sleep(0.01) | |
FRitzing project download https://tecnovita.com/uploads/midiboard.fzz
Tenga en cuenta que es soy un total novato en electronica, funciona para mi de manera correcta en un raspberry pico, no he tenido fallos, pero antes de hacer pruebas le recomiendo usar aparatos que no sean costosos... 😞
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Voy a reemplazar el level shifter por un 74hct14, ya que el que tiene puesto ahora no es capaz de manejar mucha información.
Voy a usar Arduino y la librería Control Surface que es más completo ya que el proyecto se está poniendo gordo y tedioso.