見出し画像

『天国、それともラスベガス』のコーディング:PCDJ用MIDIコントローラーをArduinoで自作する(その②・プログラミングと設定編)

この記事は、別記事「PCDJ用MIDIコントローラーをArduinoで自作する(その①:立志編)」の姉妹記事です。お姉さんにあたる①では、今回のコントローラー製作の全体像がわかるので、ぜひそちらもご覧ください。

元記事でもちらっと書きましたが、僕自身、プログラミングの経験はほとんどありません。voidです。当然C言語の知識はほぼvoid。なので、今回Arduino MicroでMIDコントローラーを自作するにあたり、プログラミングの部分は検索とGitHubのサンプルコード、そして参考書「Arduinoをはじめよう」を駆使して、なんとかプログラムを書き上げました。

かなり苦労もしましたが、動いたときの感動はひとしおでした。なのでこの記事は、僕みたいな知識voidの方の参考になればと思い、なるべく丁寧に書いていきたいと思います。

1. MIDI信号を送って、PCDJソフトを制御する

僕が使っている、ドイツ・ベルリンに本社のあるのNative InstrumentのPCDJソフト「Traktor Pro 3」には、MIDI機器から送られるMIDI信号を受け取って、それを各種の操作にマッピング(割り当て)する機能がついています。

画像8

上の画像は、Traktor Pro 3の設定の中にある「Controller Manager」の画面です。右側の「Control」の中にあるTempo Adjustなどの機能が、Mapped toという形でMIDI信号(Ch06.CC.016など)にマッピングされている様子が分かるでしょうか? たぶん、RekordBoxやSeratoでも同じことができるはず。

この機能があるおかげで、世の中にあるMIDI信号を送信できるあらゆる機器が、Traktorの操作に使えるのです。そして「世の中にある」の範囲には、誰かが自作するMIDIコントローラーも含まれます。要は、MIDI信号を送信する機器を作れればいいのです。

そしてイタリア生まれのマイコン・Arduino Microは、「MIDIUSB」というライブラリを導入することで、MIDI信号を送受信できるようになります。

もともと、1981年にシンセサイザーやシーケンサーなどの音楽機器をつなぐ共通規格として策定されたMIDIですが、いまでは音楽機器だけでなく様々な分野の機器で制御用信号として広く使われています。

Arduino Microを使った自作コントローラーと、PCDJソフトTraktorは、そんなユニバーサルな制御信号、MIDIを通じてつながるのです。

2. Arduinoをプログラミングする環境を作る

イタリア生まれのマイコン、Arduinoにプログラムを流し込むには、Arduinoが公式に無料配信している開発ツール、Arduino IDEを使います。

安心してください。Win用、Mac用、そしてLinux用もあります。

使い方は超簡単。ArduinoをUSB端子でPCにつないだ後、Arduino IDEを立ち上げて、「ツール」から自分のArduinoを選ぶだけです。僕は以下のように、自分の使っているArduino(Artuino Micro)を選択しました。

画像2

続いて、このArduino IDEで、ArduinoにMIDI信号を読み書きさせるための外部ライブラリ「MIDIUSB」をインストールします。

読み込み方は、まずArduino IDEの「スケッチ」から「ライブラリをインクルード」>「ライブラリを管理」を選びます。

画像8

ライブラリマネージャのウィンドウが開くので、右上の検索欄に「midiusb」と入力して、MIDIUSBをインストールします。

画像8

このMIDIUSBというライブラリは、数多くあるArduinoシリーズの中でも、ATmega32U4というチップを搭載したArduino MicroやArduino Leonardといったモデルでしか動作しないので、ご注意ください。

さて、これで、ArduinoでMIDI信号を送り出すプログラムを書く準備が整いました。

3. Arduino Microにやらせたいこと。

今回僕が作るコントローラーでは、Arduino Microにつないだフェーダー(可変抵抗)や各種スイッチを使って、以下のようなMIDI信号を送り、PCDJソフトの制御をすることにしました。

・コントロールチェンジ16 → フェーダーの位置を指示
・3オクターブ目のド(C3) → デッキAを選ぶよう指示
・3オクターブ目のレ(D3) → デッキBを選ぶよう指示
・3オクターブ目のミ(E3) → ピッチベンド(ブレーキ側)を指示
・3オクターブ目のファ(F3)→ ピッチベンド(アクセル側)を指示

「コントロールチェンジ」とはMIDI信号の1種で、コントロールをチェンジするもの…ってこれじゃ何の説明にもなってないですね、えーと、たとえばフットペダルを踏み込んだ深さとか、ベンダーの傾きなどの可変量を、0-127の値で送る信号規格です。この信号を送ると、PCDJソフトTraktor側で、ピッチフェーダーの位置情報として受け取れるのです。

ここまで計画できたら、あとはこれを実行するプログラムを書くだけ。書くだけって、それが大変だったんですけど。なんたって知識ゼロだったし…。

4. いよいよプログラミングする。

ここからは、プログラミングソフト「Arduino IDE」を使って、Arduino用のプログラムを書いていきます。

その前に、僕もとても参考にした、Arduinoプログラミングの解説書、オライリーの『Arduinoをはじめよう 第3版』(Massimo Banzi、Michael Shiloh 著、船田 巧 訳)を紹介します。この本はとても分かりやすく、かつ巻末にはプログラミングで使える各種命令のリファレンスがついていてとても便利です。超絶オススメです。

画像9

さて、それではいよいよプログラムを書いていきましょう。

Arduinoの世界では、プログラムを「スケッチ」と呼びます。そして今回僕が書いたスケッチの全ソースを、この記事の一番下に付録としてつけました。全体像はそちらをご覧ください。

Arduino用のプログラムは大きく3部構成になっていて、①変数の設定パート、②セットアップパート、③ループでぐるぐる実行パート…に分かれているので、この流れにそって僕が書いたプログラムを(素人まるだしで恥ずかしいけど)説明していきます。

5. プログラミング①:変数の設定パート

#include "MIDIUSB.h"         // include MIDIUSB library

const int FADER = A0;        //  Pitch Fader pin
const int LED = 12;          // Center LED pin
const int SWITCH1 = 3;       //  Deck A selector pin
const int SWITCH2 = 5;       //  Deck B selector pin
const int BEND1 = 8;         //  Bend Down pin
const int BEND2 = 10;        //  Bend UP pin

int analogval =0;            // original fader val (0-1023)
float s0 = 0;                // Internal val for curve conversion
float s1 = 0;                // Internal val for curve conversion
float adjustval = 2.4287;    // Log((1023-833/1023), 0.5), "833" is original fader value of center position
int faderval = 0;            // Pitch Fader Val (0-127)
int faderval_old =0;         // Fader Val Old

int switchval_1 = 0;         // Switch 1 value
int switchval_1_old = 0;     // Switch 1 value old
int switchval_2 = 0;         // Switch 2 value
int switchval_2_old = 0;     // Switch 2 value old
int bendval_1 = 0;           // Bend 1 value
int bendval_2 = 0;           // Bend 2 value

int val0= 0;                 // Internal val for Fader
int val1= 0;                 // Internal val for Switch 1
int val2= 0;                 // Internal val for Switch 2

プログラムの最初のところで、ライブラリ(MIDIUSB)の読み込みと、プログラム内で使う各種変数を定義していきます。

まず最初の#includeで、MIDIUSBを読み込んでいます。

そのあとのconstは、プログラムの中でコンスタントな(値の変わらない)数字にラベルをつけているところです。フェーダーをつないだArduinoの入力端子A0番に「FADER」と名前をつけ、LEDを光らせる端子(12番)に「LED」という名前をつけたりしています。SWITCH1と2はトグルスイッチをつないだピンの名前、BEND1と2はベンドボタンをつないだピンの名前。

そのあとは、ひたすら0を代入(=)しながら、以後プログラムの中で使う変数を「これ使いますよー」と宣言しています。intは「この変数は整数ですよー」という意味、「float」は「この変数は小数点以下の値も持ちますよー」という意味らしいです。

6. プログラミング②:セットアップパート

変数を設定したら、次にArduinoのセットアップをするパートです。void setup()以下が、そのセットアップの内容です。僕が書いたコードは以下の通り。

void setup() 
{
 pinMode(LED, OUTPUT);
 pinMode(FADER, INPUT);           // Connecting Fader
 pinMode(SWITCH1, INPUT_PULLUP);  // Connecting Toggle Switch with pullup mode
 pinMode(SWITCH2, INPUT_PULLUP);  //
 pinMode(BEND1, INPUT_PULLUP);    // Connecting Bend Switch with pullup mode
 pinMode(BEND2, INPUT_PULLUP);    //
 Serial.begin(9600);
}

void noteOn(byte channel, byte pitch, byte velocity) {
 midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
 MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
 midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
 MidiUSB.sendMIDI(noteOff);
}

void controlChange(byte channel, byte control, byte value) {
 midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
 MidiUSB.sendMIDI(event);
}

最初のカッコ( "{"から"}"まで )の間で、パーツをつないだArduinoの各種ピンの動作モードをセットアップします。

1行目「pinMode(LED, OUTPUT);」で、LED(①のパートで12番を代入した変数)に「OUTPUT(出力)」を定義しています。LEDを光らせる=信号を出力するので、アウトプットモードに設定するわけです。

同様に、FADER、SWITCH1と2、BEND1と2の各ピンに、それぞれの動作モードを入れていきます。これらはスイッチからは操作の信号を受け取るので、インプットモードを定義します。INPUTとINPUT_PULLUPの違いについては…説明が長くなるし僕も「なんとなく」でしか理解していないので省きます(ごめんなさい)。「スイッチ プルアップ」で検索すると、分かるかも。

その後の「Serial.begin(9600);」は、Arduino MicroがPCと通信するときの通信速度を設定しています。通信速度は最大11万5200bpsまで行けるのですが、PCDJにそんな速度は要らないので、9600bpsを設定しました。

続く「void noteOn」「void noteOff」「void controlChange」のパートは、GitHubにあったMIDIUSBライブラリのサンプルコードからコピペしたものです。字面からしてノートのOn/Offやコントロールチェンジ信号を送信する関数の定義をしているみたいですね。

7. プログラミング③:ループでぐるぐる実行パート(その1・ピッチフェーダー)

ここから、いよいよArduinoの動作を書くパートです。テンポを変化させるフェーダー、A/Bデッキを切り替えるためのトグルスイッチ、そしてピッチベンドさせるマイクロスイッチそれぞれに対して、どう信号を受け取り、どうMIDI信号に変換して出力するかを定義していきます。

画像10

void loop() 
{

//////// Pitch Fader

// Calculating fader value
 int analogval = analogRead(FADER);                  // Read fader value
 float s0 = (float)(1023 - analogval)/1023.0;        // Convert A curve to B curve
 float s1 = pow(s0,1.0/adjustval);                   
 int faderval = 127 - int(s1*127);                   // Set Fader value in B curve scale

// Light LED up when fader position is middle
 if ( faderval == 64 ) {
 digitalWrite( LED, HIGH );
 } else {
 digitalWrite( LED, LOW );
 }

// sending control change
 int val0 = faderval - faderval_old;
 if ( not( val0 == 0 )) {
     controlChange(5, 16, faderval);   // Channel 6, Control Change 016, Fader value
     MidiUSB.flush();
 }
 faderval_old = faderval;

こっからループパートですよ、という「void loop()」のあとに書いたのが、ピッチフェーダーの制御部分です。

まずint analogval == analogRead(FADER)で、フェーダーのピンからアナログの抵抗値を読み込み、analogvalという変数に整数値(int)として代入します。値は、0~1023の範囲で読み取られます。

で、縦フェーダーから読み取る値、下端が0で上端が1023なら、中央は512になりそうじゃないですか。でも実際に動作させて値をみてみたら、フェーダーの中央の値は833と上に偏っていました。

これは、僕が使ったSL1200のフェーダー(可変抵抗器)が、対数カーブを描くAカーブ型だったからです。でも、MIDI信号としては中央で0~1023の半分=512の値をとってくれないと困ります。これをなんとか変換したい!

画像12

数学(対数)の知識がある皆さんには余裕なのでしょうが、高校数学をすっかり忘れてしまった僕は、Facebook経由で以前勤務していたゲーム会社の大先輩プログラマさんに教えてもらって変換の方程式を実装しました。この部分です。

 float s0 = (float)(1023 - analogval)/1023.0;        // Convert A curve to B curve
 float s1 = pow(s0,1.0/adjustval);                   
 int faderval = 127 - int(s1*127);   

最終的にMIDIのコントロール信号としては0~127の値になって欲しいので、そのようにプログラムしています。

こうしてフェーダーから0~127の値を取得できたら、次はフェーダーが中央(0~123の半分=64)のときに緑色LEDを光らせる部分です。

// Light LED up when fader position is middle
 if ( faderval == 64 ) {
 digitalWrite( LED, HIGH );
 } else {
 digitalWrite( LED, LOW );
 }

もしフェーダーの値(変数「faderval」)が64だったら、ピンに信号を出力するdigitalWrite関数でLEDピンにHIGHを送り、それ以外ならLOWを送ることで、LEDを光らせたり消したりしています。

そのあと、いよいよ取得したフェーダーの値(faderval)をMIDIの6ch(プログラム上では0はじまりの「5」)のコントロールチェンジ(16番)として送り出す…というところを以下の部分で定義しています。

// sending control change
 int val0 = faderval - faderval_old;
 if ( not( val0 == 0 )) {
     controlChange(5, 16, faderval);   // Channel 6, Control Change 016, Fader value
     MidiUSB.flush();
 }
 faderval_old = faderval;

フェーダーの値は常にArduinoに出力されているので、何も工夫しないと9600bps=1秒間に9600回くらい常時信号が送られてしまいます。フェーダーを動かさなくても送信します。それってもったいないというか、受け取る側も負担になりそうなので、送り出した値は「fedarval_old」に入れて過去と現在を比較し、値に変化があったときだけ信号を送り出すようにしました。

8. プログラミング③:ループでぐるぐる実行パート(その2・デッキ切り替えトグルスイッチ)

続いては、操作対象のデッキ(AとB)を切り替えるためのトグルスイッチの動作を書いていきます。

画像11

トグルスイッチを左に倒すと、SWITCH1のピンに「1」が入るので、それをdigitalRead(SWITCH1)で読み取り、switchval_1に代入します。

同様に右に倒すと、SWITCH2のピンに「1」が入るので、それをdigitalRead(SWITCH2)で読み取り、switchval_2に代入します。

/////// Deck Selector

// Reading Switch Value
 int switchval_1 = digitalRead(SWITCH1);
 int switchval_2 = digitalRead(SWITCH2);

値を読み取ったら、その値に沿ってMIDI信号を出力する部分を書きます。ここでも、oldで過去の値と比較しながら、値が変化したときだけ・しかも値が「1(on)」になったときだけ、信号を出すようにしています。

SWITCH1が1のときは、チャンネル6にC3(3オクターブ目のド)のノートonを送り、delay(500)で0.5秒送ったら、ノートoffで音を切ります。

SWITCH2が1のときは、チャンネル6にD3(3オクターブ目のレ)のノートonを送り、delay(500)で0.5秒送ったら、ノートoffで音を切ります。

// Sending note by Switch 1
 int val1 = switchval_1 - switchval_1_old;
 if ( not(val1 == 0) ) {
   if ( switchval_1 == 1 ) {  
         noteOn(5, 48, 64);   // Channel 6, C3, normal velocity
         MidiUSB.flush();
         delay(500);
         noteOff(5, 48, 64);  // Channel 6, C3, normal velocity
         MidiUSB.flush();
    }
 switchval_1_old = switchval_1;
 }

// Sending note by Switch 2
 int val2 = switchval_2 - switchval_2_old;
 if ( not(val2 == 0) ) {
   if ( switchval_2 == 1 ) {  
         noteOn(5, 50, 64);   // Channel 6, D3, normal velocity
         MidiUSB.flush();
         delay(500);
         noteOff(5, 50, 64);  // Channel 6, D3, normal velocity
         MidiUSB.flush();
    }
 switchval_2_old = switchval_2;
 }

PCDJソフト側では、この「ド」と「レ」の音を受け取って、デッキA、デッキBを切り替えるようにあとで設定します。

9. プログラミング③:ループでぐるぐる実行パート(その3・ピッチベンドのマイクロスイッチ)

さあ最後のパートです。マイクロスイッチの入力を読み取って、PCDJソフトにピッチベンドの信号(ミとファ)を送る部分を書いて行きます。この写真の左側を押したらピッチアップ、右側を押したらダウンさせたい。

画像12

まずは読み取りから。

/////// Pitch Bender

// Reading Switch Value
 int bendval_1 = digitalRead(BEND1);    //  On=0, Off=1
 int bendval_2 = digitalRead(BEND2);    //  On=0, Off=1

トグルスイッチと同じです。digitalReadで「BEND1」「BEND2」のそれぞれのスイッチのピンから信号を読み取って、それぞれbendval_1、bendval_2に代入します。このマイクロスイッチでは、Onが0、Offが1になります。

// Sending note by Bend 1 (down)
 
  if ( bendval_1 == 0 ) {  
         noteOn(5, 52, 64);   // Channel 6, E3, normal velocity
         MidiUSB.flush();
         delay(50);
         noteOff(5, 52, 64);  // Channel 6, E3, normal velocity
         MidiUSB.flush();
 }

// Sending note by Bend 2 (up)
  if ( bendval_2 == 0 ) {  
         noteOn(5, 53, 64);   // Channel 6, F3, normal velocity
         MidiUSB.flush();
         delay(50);
         noteOff(5, 53, 64);  // Channel 6, F3, normal velocity
         MidiUSB.flush();
 }
}

読み取ったら、信号を送ります。

フェーダーやトグルスイッチと違い、このマイクロスイッチで行うピッチベンド操作では、「ボタンを押し続ける」=「値を送り続ける」必要があるので、oldとの値の比較は行いません。

読み取ったbendval_1がOn(0)なら、3オクターブ目のミ(52)を、bendval_2がOn(0)なら、3オクターブ目のファ(54)を、それぞれ送り出しています。

おつかれさまでした。これでArduino側のプログラミングは終了です。続いては、こうした信号を受け取るPCDJソフト、Traktor側の設定をします。

10. Traktorの設定(Controller Manager)

Traktorの設定でController  Managerを開き、右側のメニューでDeviceを「General MIDI」、In-Portに「Arduino Micro」を選んだら、その下のAssugbnebt Tableのところに、Arduinoから送られたMIDI信号それぞれの動作を書いていきます。

画像6

デッキA/Bを切り替えるトグルスイッチからの信号(ドとレ)は、Modifierに書き込みます。Modifierとは、Traktorに何かさせるときの条件設定に使う装置。Modifierには0番から8番まであるのですが、僕はトグルスイッチからドを受け取ったらModifierの8番に「1」を、レを受け取ったらModifierの8番に「2」を代入するようにしています。

上の画像は、Ch06.Note.C3(ド)を受け取ったら、Modifier #8に「2」をセットしているところです。この設定が、後に効いてきます。

画像6

続いて、ピッチフェーダーの動作を設定します。Traktor側ではピッチフェーダーを「Tempo Adjust」と呼んでいるので、そこにCh.06.CC.016(コントロールチェンジ16番)の値を紐付けます。

上の画像で、Tempo Adjustが2つあるのが分りますよね? これは、デッキA用とデッキB用で2つあるのです。

1本のフェーダーでA/Bデッキを操作させるために、先ほどのModifierを使います。中央のMapping Detailsのところにある「Modifier Conditions」のところで、M8(Modifier 8番)がDeckAなら1、DeckBなら2というように2回に分けて定義を書きます。

画像7

ピッチベンドも同じです。フェーダーは値が1つでしたが、ピッチベンドは「ミ」と「ファ」の2つの値を持つので、A/Bデッキ×ミとファで4回に分けて定義を書いて行きます。

これでTraktor側の設定も完了です。

11. 完了!

自作のコントローラーができて、うきうきでプレイする筆者の様子をご覧ください。


12. 記事末付録:Arduino micro用「SL1200 USBMIDI Fader MK2」全ソース

GitHubのリポジトリはこちら。僕の記念すべき初めてのリポジトリです。

//
// SL1200 USBMIDI Fader mk2
// by spinn.teramoto (Akihabara Housing, Ltd.) 2021
//
// note: Pitch fader of SL-1200 mkII is "A Curve" potentiometer.
//       So it need to be converted to "B Curve"
//
//       0                 833                 1023
//       |------------------+-------------------|     :Original Scale (A curve(Log))
//                           
//       0                 64                  127
//       |------------------+-------------------|     :Converted Scale (B curve(Linear))
//

#include "MIDIUSB.h"         // include MIDIUSB library

const int FADER = A0;        //  Pitch Fader pin
const int LED = 12;          // Center LED pin
const int SWITCH1 = 3;       //  Deck A selector pin
const int SWITCH2 = 5;       //  Deck B selector pin
const int BEND1 = 8;         //  Bend Down pin
const int BEND2 = 10;        //  Bend UP pin

int analogval =0;            // original fader val (0-1023)
float s0 = 0;                // Internal val for curve conversion
float s1 = 0;                // Internal val for curve conversion
float adjustval = 2.4287;    // Log((1023-833/1023), 0.5), "833" is original fader value of center position
int faderval = 0;            // Pitch Fader Val (0-127)
int faderval_old =0;         // Fader Val Old

int switchval_1 = 0;         // Switch 1 value
int switchval_1_old = 0;     // Switch 1 value old
int switchval_2 = 0;         // Switch 2 value
int switchval_2_old = 0;     // Switch 2 value old
int bendval_1 = 0;           // Bend 1 value
int bendval_2 = 0;           // Bend 2 value

int val0= 0;                 // Internal val for Fader
int val1= 0;                 // Internal val for Switch 1
int val2= 0;                 // Internal val for Switch 2


void setup() 
{
 pinMode(LED, OUTPUT);
 pinMode(SWITCH1, INPUT_PULLUP);  // Connecting Toggle Switch with pullup mode
 pinMode(SWITCH2, INPUT_PULLUP);  //
 pinMode(BEND1, INPUT_PULLUP);    // Connecting Bend Switch with pullup mode
 pinMode(BEND2, INPUT_PULLUP);    //
 Serial.begin(9600);
}

void noteOn(byte channel, byte pitch, byte velocity) {
 midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
 MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
 midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
 MidiUSB.sendMIDI(noteOff);
}

void controlChange(byte channel, byte control, byte value) {
 midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
 MidiUSB.sendMIDI(event);
}


void loop() 
{

//////// Pitch Fader

// Calculating fader value
 int analogval = analogRead(FADER);                  // Read fader value
 float s0 = (float)(1023 - analogval)/1023.0;        // Convert A curve to B curve
 float s1 = pow(s0,1.0/adjustval);                   
 int faderval = 127 - int(s1*127);                   // Set Fader value in B curve scale

// Light LED up when fader position is middle
 if ( faderval == 64 ) {
 digitalWrite( LED, HIGH );
 } else {
 digitalWrite( LED, LOW );
 }

// sending control change
 int val0 = faderval - faderval_old;
 if ( not( val0 == 0 )) {
     controlChange(5, 16, faderval);   // Channel 6, Control Change 016, Fader value
     MidiUSB.flush();
 }
 faderval_old = faderval;
 

/////// Deck Selector

// Reading Switch Value
 int switchval_1 = digitalRead(SWITCH1);
 int switchval_2 = digitalRead(SWITCH2);

// Sending note by Switch 1
 int val1 = switchval_1 - switchval_1_old;
 if ( not(val1 == 0) ) {
   if ( switchval_1 == 1 ) {  
         noteOn(5, 48, 64);   // Channel 6, C3, normal velocity
         MidiUSB.flush();
         delay(500);
         noteOff(5, 48, 64);  // Channel 6, C3, normal velocity
         MidiUSB.flush();
    }
 switchval_1_old = switchval_1;
 }

// Sending note by Switch 2
 int val2 = switchval_2 - switchval_2_old;
 if ( not(val2 == 0) ) {
   if ( switchval_2 == 1 ) {  
         noteOn(5, 50, 64);   // Channel 6, D3, normal velocity
         MidiUSB.flush();
         delay(500);
         noteOff(5, 50, 64);  // Channel 6, D3, normal velocity
         MidiUSB.flush();
    }
 switchval_2_old = switchval_2;
 }


/////// Pitch Bender

// Reading Switch Value
 int bendval_1 = digitalRead(BEND1);    //  On=0, Off=1
 int bendval_2 = digitalRead(BEND2);    //  On=0, Off=1

// Sending note by Bend 1 (down)
 
  if ( bendval_1 == 0 ) {  
         noteOn(5, 52, 64);   // Channel 6, E3, normal velocity
         MidiUSB.flush();
         delay(50);
         noteOff(5, 52, 64);  // Channel 6, E3, normal velocity
         MidiUSB.flush();
 }

// Sending note by Bend 2 (up)
  if ( bendval_2 == 0 ) {  
         noteOn(5, 53, 64);   // Channel 6, F3, normal velocity
         MidiUSB.flush();
         delay(50);
         noteOff(5, 53, 64);  // Channel 6, F3, normal velocity
         MidiUSB.flush();
 }
}

良かったら、100円サポートおねがいします!