Connect the UART of the Raspberry Pi to the UART of the MIDI shield to send and receive MIDI on the 5-pin DIN. The link is to SparkFun catalog page. The MIDI shield I have is one generation older.
Configure the Raspberry Pi to handle serial communication. Open the Raspberry Pi Configuration page, 5. Select Interface Options.
> pi@raspberrypi:~ $ sudo /usr/bin/raspi-config
Select I6 Serial Poart menu.
Ask "Would you like a login shell to be accessible over serial?", select "No".
Next, ask "Would you like the serial port hardware to be enabled?", as using serial port, so select "Yes".
Click "Finish" and reboot
> pi@raspberrypi:~ $ sudo reboot
Connect the Raspberry Pi to the MIDI shield. One thing to take into account here is that the Raspnerry Pi's serial inputs and outputs (TXD, TRD) are 3.3V, while the MIDI inputs and outputs are 5V. You have to convert the voltage. I made the following circuit using parts I had on hand. An NPN transistor is used to boost the voltage to connect the Raspberry Pi's TXD to the MIDI shield's TXD. Also, to receive the output of the MIDI shield on the Raspberry Pi, the voltage needs to be lowered, so here it is converted using a Zener diode.
I use a Roland UM-ONE as a USB-MIDI interface. Connect the IN marking on the UM-ONE connector to the MIDI IN of the shield, and connect the OUT of the connector to the MIDI OUT of the shield. Depending on the interface, it may be the other way around.
The following is a MIDI sending and receiving program using python.
Sending a Note On message
import serial ser = serial.Serial('/dev/ttyAMA0', '31250', timeout=0.1) ser.write(chr(0x90).encode()) ser.write(chr(0x60).encode()) ser.write(chr(0x7F).encode()) ser.close()
Receiving MIDI message
import serial ser = serial.Serial('/dev/ttyAMA0', '31250', timeout=0.1) mcnt=0 message=[0,0,0] while True: a=ser.read() if(a!=b''): for x in a: if(x&0x80): message[0]=x message[1]=0 message[2]=0 mcnt=1 else: if(mcnt==1 or mcnt==2): message[mcnt]=x mcnt=mcnt+1 if(mcnt==3): for i in range(3): print(hex(message[i])," ",end="") print("") mcnt=0 ser.close()
Accessing a serial port from C is the same as accessing a file. You write a program to open a file, write to the file, and read from the file.
(1)Install WiringPi to handle the gpio.
> git clone https://github.com/WiringPi/WiringPi.git > cd WiringPi > ./build
(2)Edit /boot/config.txt and add the following three lines. Then reboot.
> sudo vim /boot/config.txt # uart baud rate for MIDI enable_uart=1 dtoverlay=pi3-miniuart-bt dtoverlay=midi-uart0 > sudo reboot
The Raspberry Pi has several ports for serial communication. Among them, UART0 (/dev/ttyAMA0) is connected to the GPIO pins (pins 8 and 10). However, this port is usually used for Bluetooth. So we will wake up the other port, Mini UART (/dev/ttyS0), and move Bluetooth over to it. As a result, /dev/ttyAMA0 will be available for serial communication.
In the above program, enable_uart=1 enables the Mini UART and sets it to GPIO14,15. dtoverlay=pi3-miniuart-bt sets Bluetooth to Mini UART.This leaves UART0 free.
dtoverlay=midi-uart0 is the serial communication setting and sets the baud rate to 38kbps. It sets the MIDI communication speed to 31.25kbps.
It's a bit confusing. The baud rate in Python must be 38400.
// serialmidisend.c #include <stdio.h> #include <wiringPi.h> #include <wiringSerial.h> int main() { /* Open Serial Port */ int fd = serialOpen("/dev/ttyAMA0",38400); if(fd<0){ printf("can not open serialport"); } serialPutchar(fd,0x90); serialPutchar(fd,0x40); serialPutchar(fd,0x7F); delay(1000); //1sec待つ serialPutchar(fd,0x80); serialPutchar(fd,0x40); serialPutchar(fd,0x00); return 1; }
>gcc serialmidisend.c -lwiringPi
//serialmidireceive.c #include <stdio.h> #include <wiringPi.h> #include <wiringSerial.h> int main() { /* Open Serial Port */ int fd = serialOpen("/dev/ttyAMA0",38400); int n, i; unsigned char cc; if(fd<0){ printf("can not open serialport"); } while(1){ /* Recieving message */ n=serialDataAvail(fd); if(n!=0){ for(i=0; i<n; i++){ cc=serialGetchar(fd); printf("%02x:",cc); } printf("\n"); serialFlush(fd); } } return 1; }
>gcc serialmidireceive.c -lwiringPi