Skip to content

Instantly share code, notes, and snippets.

@nucklearproject
Last active August 22, 2024 20:07
Show Gist options
  • Save nucklearproject/92a3adb833af4071562824381bd9d100 to your computer and use it in GitHub Desktop.
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
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)
@nucklearproject
Copy link
Author

nucklearproject commented Aug 15, 2024

image
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.

@nucklearproject
Copy link
Author

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