The MIDI communication protocol has two main options: MIDI in and MIDI out. MIDI in refers to receiving MIDI messages as an input. MIDI out refers to sending MIDI messages as an output.
Each type requires a different circuit to send or receive the messages properly. MIDI controllers will have the ports labeled as such. For homemade devices, you will define your device as either being an input or an output.
MIDI messages are sent via channels. There are 16 available channels, numbered 1-16. The channels allow for devices to know what and who to listen to, similar to setting up a remote to control a specific television.
For example, a MIDI controller could send a C3 note and CC messages via channel 1 to a synthesizer setup to receive messages on channel 1. At the same time, that MIDI controller could send the same or different messages on channel 8 to a drum machine setup to receive messages on channel 8.
In code, these channels are numbered
15 because you are counting with zero-based numbering. For example, real-world channel 1 is coded as channel
0, real-world channel 2 is coded as channel
In CircuitPython, your MIDI device's channel that it is listening to or sending messages on is defined at the beginning of your code. It looks like this:
midi = adafruit_midi.MIDI(
midi_in=usb_midi.ports, in_channel=0, midi_out=usb_midi.ports, out_channel=0
out_channel are holding the channel values.
In Arduino, it's a little different. In the
begin() function is called with
MIDI_CHANNEL_OMNI means that the code is able to listen for any of the 16 MIDI channels. it looks like this:
More discrete MIDI channel definitions can be defined when sending individual MIDI messages. Examples for this syntax are available on the MIDI Messages page of this guide.
The original MIDI connector is a MIDI jack, or DIN-5 connector. These are chunky, hearty connectors. Though they are becoming less common on newer devices, they are reliable and provide a straight forward connection to transmit MIDI data.
A newer MIDI connection standard that has been implemented is TRS-A, which utilizes a TRS audio jack to transmit MIDI data over UART. When this first began appearing, the connection was not standardized so older devices may require specialized cables for full compatibility.
The standardized pinout for TRS-A is as follows:
- MIDI Sink to TRS Tip
- MIDI Source to TRS Ring
- MIDI Shield to TRS Sleeve
This new standard allows for the reliability of a DIN-5 connector, but in a smaller and more common form factor.
MIDI over UART
When you see a connection with a DIN-5 or TRS-A connector, the device is using MIDI over UART. MIDI over UART transmits MIDI messages over the TX and RX serial connections at a baud rate of 31250.
You can use MIDI over UART to create MIDI devices using older boards with microcontrollers that do not have support for direct USB communication, such as the Atmega328. Additionally, you can have boards communicate with each other over MIDI directly using UART.
USB MIDI has become more common for MIDI controllers. These devices have a configuration descriptor allowing them to be plug and play. These do not have direct compatibility with MIDI over UART devices, and, as a result, would require a converter to communicate directly.
For MIDI over USB devices, you can use them with your computer to interface with music tech software. You can also use them with a USB MIDI Host, which allows for USB devices to interface with each other. There are aftermarket USB MIDI hosts available, as well as DIY options (you can even use a Raspberry Pi).
Many current microcontrollers have the ability to be used for DIY USB MIDI projects, including boards that are based on the ATSAMD21 (M0 Express), ATSAMD51 (M4 Express) and RP2040. All of these boards have support for both CircuitPython and Arduino.
One of the more unique ways to transmit MIDI is over Bluetooth with BLE MIDI. BLE MIDI allows for wireless MIDI communication over Bluetooth. It can be the perfect choice for some projects that benefit from not being tethered by cables.
If you want to build a BLE MIDI project, you'll want to use an nRF52840 Express-based board, which has support for BLE.