0

My goal:

I want to write a script on my Raspberry Pi Zero W, that sends MIDI to my computer whenever I make a specific connection on the GPIO board.

The problem:

The hardware stuff is already taken care of, it can recognize unique button presses. But it won't seem to send any data to my computer. I've tried multiple python modules (like rtmidi-python, python-rtmidi, mido), but none of them work as I would want them to.

Trying to solve this issue, I've set up my Raspberry to power from the power port, so the USB port remains empty, and when it boots up, I connect the cable to my PC. I even wrote a script, that perpetually shouts the same note (note off included) over and over, since I couldn't find any "setup protocol". While browsing various forms, I noticed that all of them were pretty old. The newest is rtmidi-python on GitHub, but that doesn't seem to have any setup stuff.

It very well could be, that i just looked the wrong way all along, or that the signal doesnt even come through the USB cable, or it doesn't need a setup either. If so, would you mind letting me know, or showing me how to do it correctly.

Update

I made my Raspberry into a "MIDI function" (this is how). My PC, and FL studio recognizes it as well. However, still no action, when I try to play a note. This port probing scripts

import rtmidi_python as rtmidi

midi_out = rtmidi.MidiOut()
for port_name in midi_out.ports:
    print port_name

returns

Midi Through:0
f_midi:0

I can't decide wehter it says that no MIDI messages went through, or that my Raspberry is talking on Port0

Solution:

First, You've got to make sure, that your Raspberry Pi is actually recognized as (in this case) a MIDI gadget. Then, don't confuse Python with Python3, as they are different, and pip3 install midopip install mido. Also, a good practice, to keep your SD crad clean, and delete any unnecessary modules. If You're system gets really messy, and you loose track even with pip list and apt list (which lists all your installed modules), You can always start anew. Meaning wipe clean your SD card, and with the experience you've learned, it should be easier this time.

Also, you should obviously check out the given answer.

Hopefully at least one other person sees this, and I'm able to help them :)

Thanks

Community
  • 1
  • 1
qawes
  • 3
  • 6
  • https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=262168 – tttapa Apr 26 '20 at 09:15
  • 2
    Show us your code. We can't help you identify the problem if you don't show us what you've tried. How have you configured your Pi Zero as a USB device? Does your host computer see it on the USB bus? What does your code look like? – larsks Apr 26 '20 at 13:15
  • Since I'm as a beginner as one can possibly be, I just shamelessly copy-pasted the setup / test examples after staring at a C++ script for a while. Links to pages i've visited: https://pypi.org/project/python-rtmidi/ https://github.com/superquadratic/rtmidi-python For the perpetually shouting script, i just basically wrote an endless while loop with sleep between NOTE_ON and NOTE_OFF. (also just noticed and corrected, that i have a Zero W, if that makes any difference) – qawes Apr 26 '20 at 13:39
  • 1
    We really need more information. Can you please update your question to show (a) how are you configuring your Pi as a USB midi device? (b) What does your Python code on the Pi look like? (c) How are you verifying on the host that it's working or not? If you can provide that information in the question I'd be happy to help out. – larsks Apr 26 '20 at 18:41
  • Hopefully it's a bit clearer now. – qawes Apr 27 '20 at 11:39

1 Answers1

1

In this code...

midi_out = rtmidi.MidiOut()
for port_name in midi_out.ports:
    print port_name

...you're asking for a list of available ports, and rtmidi is providing you with that information. There are two midi ports available:

Midi Through:0
f_midi:0

Of these two ports, the second one (f_midi:0) is the port created by the USB gadget feature. If you send MIDI messages on this port, it should work just fine. For example, I replicated your setup on my Pi Zero and I was able to use the following code to send a MIDI message to my desktop. I'm using mido, which is a high-level wrapper around rtmidi (I prefer it because it makes sending/receiving MIDI messages much easier):

>>> import mido
>>> mido.get_output_names()
['Midi Through:Midi Through Port-0 14:0', 'f_midi:f_midi 20:0']
>>> out = mido.open_output('f_midi:f_midi 20:0')
>>> out.send(mido.Message('control_change', channel=0, control=0, value=123))

On my host, I see the Pi Zero show up as a MIDI port:

$ aseqdump -l
 Port    Client name                      Port name
  0:0    System                           Timer
  0:1    System                           Announce
 14:0    Midi Through                     Midi Through Port-0
 28:0    nanoKONTROL2                     nanoKONTROL2 MIDI 1
 36:0    Pi Zero Gadget                   Pi Zero Gadget MIDI 1

And I see the control change message I sent:

$ aseqdump --port 36:0
Waiting for data. Press Ctrl+C to end.
Source  Event                  Ch  Data
 36:0   Control change          0, controller 0, value 123

In answer to your last comment, you could do something like this:

import rtmidi
import sys

out = rtmidi.MidiOut()
for i, port in enumerate(out.get_ports()):
    if port.startswith('f_midi'):
        out.open_port(i)
        break
else:
  print('ERROR: failed to find a port')
  sys.exit(1)

out.send_message([176, 0, 123])

I'm using Python 3 (which I recommend, given that Python 2 is EOL as of about now), and I'm using the rtmidi module you get if you apt install python3-rtmidi.

Using the mido module, which I prefer, that looks like:

import mido
import sys

for port in mido.get_output_names():
    if port.startswith('f_midi'):
        out = mido.open_output(port)
        break
else:
  print('ERROR: failed to find a port')
  sys.exit(1)

out.send(mido.Message('control_change', channel=0, control=0, value=123))
larsks
  • 277,717
  • 41
  • 399
  • 399
  • Does it make a difference, if I use python, or python3 in the above example? Beacuse with python it just does nothing, whilst with python3, it actually gives me an error. The first the it gace me, it said smt like "expected bytes, str found", so i reinstalled rtmidi-python, but it still gives me this error. Or how can I find the " 'f_midi:f_midi 20:0' " part with script? (I don't want to type it every time it boots) – qawes Apr 27 '20 at 16:58
  • Clearly I'm just being dumb at this point, but that's exactly why I'm asking for advice/help. – qawes Apr 27 '20 at 16:59
  • Well, you can do what I did here and use `mido.get_output_names()`, or do what you did and use the `ports` attribute of the object returned by `rtmidi.MidiOut()`. In either case, just pick the port that beings with `f_midi` and use that one. – larsks Apr 27 '20 at 17:32
  • I've added an example to the answer. – larsks Apr 27 '20 at 17:47
  • Wow. It works. I can actually see my message being sent. Well, isn't that a surprise? Anyway, thank you so much for helping me out, I really appreciate it. – qawes Apr 27 '20 at 20:46