Raspberry Pi のUARTとMIDIシールドのUARTを接続して、5pin DINのMIDIを送受信します。リンク先はスイッチサイエンスさのカタログページです。私の持っているMIDIシールドは一世代前のものです。

Raspberry Piでシリアル通信を扱えるように設定します。Raspberry PiのConfigurationを開きます。5. Interface Optionsを選択します。
> pi@raspberrypi:~ $ sudo /usr/bin/raspi-config
I6 Serial Poartを選択します。
Would you like a login shell to be accessible over serial?と聞かれますので、 いいえとします。
次にWould you like the serial port hardware to be enabled? と聞かれます。シリアルポートのハードウェアを使いますので、はいを選びます。
「了解」「Finish」でウィンドウを閉じます。rebootします。
> pi@raspberrypi:~ $ sudo reboot
Raspberry PiとMIDIシールドを接続します。ここで考慮しないといけないのは、Raspnerry Piのシリアル入出力(TXD, TRD)が3.3Vであるのに対して、MIDIの入出力は5Vなので変換をしないとなりません。以下手持ちの部品で作成しました。Raspberry PiのTXDを、MIDIシールドのTXDに接続するためにNPNトランジスタで電圧を上げています。また、MIDIシールドの出力をRaspberry Piで受けるには電圧を下げれば良いので、ここではツェナーダイオードで変換しています。
USB-MIDIインターフェースとしてRoland UM-ONEを使っています。UM-ONEのコネクタの刻印でINを、シールドのMIDI INに接続、コネクタのOUTをシールドのMIDI OUTに接続します。インターフェースに寄っては逆の場合もあります。
python3を使った、MIDI送信と受信のプログラムを書いておきます。
送信 - Note Onを1回出力します。
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()
受信 - MIDIのイベントを受信します。
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()
上ではPythonのサンプルプログラムを提示しましたが、ここからはC言語を使います。C言語からシリアルポートを扱うには、ファイルにアクセスするのと同等で、ファイルをオープンする、ファイルに対して書き込む、ファイルから読み込むようなプログラムを書きます
(1) gpioを扱うためにWiringPiをインストールします。他にもライブラリがあるようなのですが、情報が多かったのでこちらを使うこととしました。 「Wiring Piのインストール&設定」を参照いたしました。
> git clone https://github.com/WiringPi/WiringPi.git > cd WiringPi > ./build
(2) /boot/config.txt を編集して以下の3行を書き加えます。その後、rebootします。 いくつかのサイトを参考にさせていただきました。
> sudo vim /boot/config.txt # uart baud rate for MIDI enable_uart=1 dtoverlay=pi3-miniuart-bt dtoverlay=midi-uart0 > sudo reboot
いろいろ読んでみて、私の理解は次のようなものです。Raspberry Piにはシリアル通信できるポートがいくつかあります。 その中で、UART0(/dev/ttyAMA0)が、GPIOピン(8ピンと10ピン)につながっています。 ところが、通常はこのポートがBluetoothでつかわれてしまっています。 ですので、他のポートMini UART(/dev/ttyS0)を起こして、Bluetoothを移動し、 /dev/ttyAMA0を空けて使えるようにする、ということをやらないとなりません。
enable_uart=1はMini UARTを起こして、GPIO14,15に設定すします。
dtoverlay=pi3-miniuart-btは、BluetoothをMini UARTに設定します。これで、UART0が空く)
dtoverlay=midi-uart0はシリアル通信の設定で通信速度を38kbpsとすると、MIDIの通信速度31.25kbpsに設定してくれます。
この設定をすると、上のPythonでの入手力もBaudrateの設定を38400に変更しないとなりません。
// serialmidisend.c
#include <stdio.h>
#include <wiringPi.h>
#include <wiringSerial.h>
int main()
{
/* シリアルポートオープン */
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()
{
/* シリアルポートオープン */
int fd = serialOpen("/dev/ttyAMA0",38400);
int n, i;
unsigned char cc;
if(fd<0){
printf("can not open serialport");
}
while(1){
/* 受信処理 */
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