自作MIDIコントローラーの覚書

ツマミがたくさんあるMIDIコントローラーが欲しいけれど、Federfoxのは高いし、密かに狙っていたBASTL INSTRUMENTSの60Knobsは製造中止してしまった。

MIDIコンDIYについて調べてみたらArduinoを使えばそんなに難しくなさそうなので、自作することに。こちらの動画を参考にして5ツマミMIDIコンを作ってから、40ツマミMIDIコンを作った。

ちょっとした覚え書き。

𓃌𓃌𓃌𓃌𓃌𓃌𓃌𓃌𓃌𓃌 ←40ツマミ

使用材料

使用道具

  • はんだゴテ
  • はんだ(電子工作用)
  • 電動ドライバー
  • ドリルビット(ケースがプラスチックだったら竹用がよい)
  • はんだこて台
  • はんだ吸取線
  • コードストリッパー
  • ダイヤモンドやすり

𓃌𓃌𓃌𓃌𓃌𓃌𓃌𓃌𓃌𓃌

ケースの準備

試作というのもあってケースにはあんまりこだわりはなく、適当なA4の収納ボックスを使った。秋葉原にあるエスエス無線に行くと色々なケースが売ってるみたい。次作るときには行ってみよう。
ケース作りはほとんどこちらの動画と同じ要領で。ドリルビットは竹用だとプラスチックにヒビが入らない。つるんと穴が開けれて気持ちがよい𓃑
穴開け箇所を鉛筆で下書きしたけど、ドリルで穴開ける時に下書きからどうしてもずれてしまい、穴をちょっと大きくしないと固定できなかった。(可変抵抗器は7mmでぴったりだが8mmに、可変抵抗器にある小さいフックは2mmでぴったりだけど3mmにした)下穴用ドリルで下穴あけておけばよかったかも。

雑な下書き
とりあえず穴は開いた

可変抵抗とArduinoをケースに固定

こちらの動画だと、配線を先にしてから可変抵抗器をケースにつけてるけど、ケースに可変抵抗器を固定してから配線することにした。その方が後の半田付けが楽かと思い。

一旦達成感を得るがここからが長いよ

ArduinoにMuxつける

Arduino UNOのI/Oにピンヘッダ刺してMux シールドⅡを接続する。Arduino UNOだとI/Oが6つしかないけどMuxを使うと最大48に増やせる。これでたくさんのツマミが付けられる。(デザインを考慮してツマミは48じゃなくて40にした)

Arduino Megaを使えばマルチプレクサ要らなかったかも)

+5VとGNDのコードを半田付け

可変抵抗に+5VとGNDのコードを半田付けする。赤が+5Vで黒がGND。地道な作業。

間違えないように可変抵抗に0~39の番号を書いとく。電子回路の知識皆無なので番号順に繋げないといけないのかなと思って9から10、19から20、29から30を遠く斜めに繋いでるけど、縦に繋いであとは横でいいらしい。
修正後。かわいい

GNDも同じように繋げて、+5VとGNDをMuxにも繋げる。(どこから繋げてもいいみたいだけど、一番近い29番の可変抵抗器から繋げた)

可変抵抗上下逆に付けちゃってるので後でArduinoのプログラムで調整する。

信号線を半田付け

Mux シールドⅡのユーザーガイドに推奨するコネクターが載ってたけど、時間がなかったのでMuxに直接半田付けした。(時間がなかったっていうのは、2,3日後のライブに使いたかったから…)時間あったらコネクターとピン配列変換ケーブルを使った方がよいと思う。順番間違えちゃった時に抜き差しするだけなので楽なのと、半田劣化による接続不良のリスクが減るので。

何度も間違えて半田付けし直して大変だった。。可変抵抗に信号線半田付けしてから、Muxに刺して裏返して一気に半田付けするといいみたい。テスターを使って可変抵抗の各端子の抵抗が0に近いのを確認。(0に近いと正しく接続されてるってことらしい)

影が綺麗だね

Arduinoのpin 8を解放する

ここからはユーザーガイド見ながらの作業。Muxシールドの48 I/Oを使用するにはArduinoのpin8っていうのを解放しないといけないらしいので、Mux裏側のSJ1のパッド間のトレースをカットする(下図赤)
またシールドを全部入力で使用するのにSJ5の中央と左のパッドの間にはんだを置く(下図黄色)

トレースはカッターで切る。切れてるかどうかテスターを使って確認する。

Arduino IDEでの作業

ここからはパソコン使っての作業。Arduino IDEをインストールする。

ユーザーガイドからMuxShield.zipをダウンロードし、Arduino IDE立ち上げてツールバーからSketch>Include Library>Add .ZIP LibraryでMuxShield.zipをインストールする。

またArduinoでMIDI通信を扱うためにArduino MIDI Libraryを上記と同じようにインストールする。

MuxShiledライブラリのサンプルMuxShieldAnalogInとMIDI LibraryのサンプルBasic_IOを掛け合わせて、いい感じになるようにChat GPTにプログラムを書いてもらう。(プログラムはこの記事の最後に載せる)

ArduinoをPCに接続し、Arduino IDEでArduinoが挿さってるポートを選び、Chat GPTに書いてもらったプログラムをArduinoにアップロードする。

仮想MIDIバスの作成

Macのアプリケーション>ユーティリティ>Audio MIDI設定で仮想MIDIバスを作成する。
ツールバーからウィンドウ>MIDIスタジオを表示、アイコン[IAC ドライバ]をダブルクリックして、[装置はオンライン]のチェックボックスにチェックを入れると有効になる。MIDI入力と出力はそれぞれ1。
(私のMIDIスタジオではIACドライバが他のMIDIコンに埋もれてて「あれ、どこ?」ってなった)

シリアル通信からMIDI通信へ変換

Arduino UNOはシリアル通信のため、Serial Midi Bridgeなどのツールを使用してMIDI通信ができるようにする。
Serial Midi Bridgeはアプリだと正常に動作しなかったので、ターミナルでPythonファイルを実行した。

Serial portはArduinoが挿さってるポート、baudrateは一般的な115200、Serial to MIDIとMIDI to Serialはさっき有効にしたIAC Driver Bus 1を選択してStart

(今調べてみたらファームウェアの書き換えをすればArduino UNOをMIDIデバイスにできるみたい。こうすればいちいちシリアル↔︎MIDI変換ツール使う必要なさそう。)

(Arduino LeonardoやArduino Micro、Arduino Pro Microを使えばデフォルトでMIDI通信を送受信できるみたいなので変換ツールやファームウェの書き換えは不要みたい。参考動画

Ableton Liveでマッピング

Ableton Liveを立ち上げて、メニューのファイル>設定>Link, Tempo & MIDIでコントロールサーフェスをNone、入力と出力をIAC Driver (Bus1)にし、トラックとリモートにチェックを入れる。

あとは好きなようにマッピング。40ツマミあるとたくさんのエフェクターのパラメータにマッピングできる。

マッピング後

Arduinoスケッチ

Mux ShieldライブラリのサンプルMuxShieldAnalogInとMIDI LibraryのサンプルBasic_IOを参考にChat GPTにプログラムを書いてもらって、使いながら不具合があるたびに問題解決するように修正してもらった。

可変抵抗逆につけちゃったので、0-1023が1023-0になるようにしてもらったのと、ツマミを一番左まで回してもMIDIの方は2%くらい残っちゃったので、980以上になったら1023になるようにした(逆だから紛らわしい…)。

あとちょっと遅れがあったのでconst float alpha = 0.2; で変化を滑らかにしたのと、delay(10); を消した。Serial.beginはさっきの変換ツールのbaudrateと同じ115200にする必要あり。あとはよくわかりません。

最終的にこんな感じ。


#include <MIDI.h>
#include <MuxShield.h>

MIDI_CREATE_DEFAULT_INSTANCE();
MuxShield muxShield;

const int numKnobs = 40;
int lastValues[numKnobs] = {0};
float smoothedValues[numKnobs] = {0};
const float alpha = 0.2;  // Adjust the response speed

void setup() {
    for (int i = 0; i < numKnobs; i++) {
        lastValues[i] = -1;
        smoothedValues[i] = 0;
    }
    
    for (int i = 0; i < numKnobs; i++) {
        muxShield.setMode((i / 16) + 1, ANALOG_IN);
    }
    
    MIDI.begin(MIDI_CHANNEL_OMNI);
    Serial.begin(115200);
}

void loop() {
    for (int i = 0; i < numKnobs; i++) {
        int reading = muxShield.analogReadMS((i / 16) + 1, i % 16);
        smoothedValues[i] = alpha * reading + (1 - alpha) * smoothedValues[i];
        
        // Adjusted the threshold for the high-value dead zone
        if ((int)smoothedValues[i] > 980) {
            smoothedValues[i] = 1023;  // Force value to 1023 if above 980
        }

        int midiValue = map((int)smoothedValues[i], 0, 1023, 127, 0);  // Regular map range

        if (abs(midiValue - lastValues[i]) > 5) {
            sendMIDIControlChange(i, midiValue, 1);
            lastValues[i] = midiValue;
        }
    }
    // delay(10);  // Optional delay adjustment or removal
}

void sendMIDIControlChange(int controlNumber, int value, int channel) {
    MIDI.sendControlChange(controlNumber, value, channel);
}

投稿日

カテゴリー: