ArduinoベースのMIDIステッピングモーターシンセサイザー
必要な部品と材料
| 部品 | 数量 | 備考 |
|---|---|---|
| Arduino UNO | 1 | IO拡張のため類似ボードでも可 |
| A4988ステッピングモータードライバー | 4 | |
| Arduino CNC Shield V3 | 1 | オプション(手動配線も可能) |
| 12V 6A電源 | 1 | ステッピングモーター駆動用 |
| NEMA 17ステッピングモーター | 4 |
必要なツールと機器
- 3Dプリンター(完全にオプション)
プロジェクト概要
YouTubeでフロッピードライブ音楽の動画を見て、フロッピードライブがステッピングモーターで制御されていることを知り、自分でもステッピングモーターで音を出せないかと考えました。既存のプロジェクトはいくつかありましたが、コードが公開されていないか、機能が限定的で欠陥があるものばかりでした。
学校でC++を学んでいたので、そのスキルを活かしてシンプルで使いやすく、改造しやすいコードを作ることにしました。
全体の流れ
基本的には、MIDIデータを抽出し、ステッピングモーターが対応する音程を出せる速度に変換するだけです。
MIDIデータの抽出
MIDIライブラリを利用すれば簡単に実現できます。MIDIデータを解釈し、ステッピングモーターの速度制御関数に渡します。
ステッピングモーターの制御
A4988ドライバーには、モーター動作を直接制御するSTEPとDIRの2つのピンがあります。DIRは回転方向(CW/CCW)を制御し、STEPはパルスが入るたびに1ステップ動作します(マイクロステップ解像度による)。音程には方向が関係ないため、DIRはLOW固定(またはGND接続)にしています。あとはdigitalWriteでSTEPピンをパルス駆動するだけです。
課題:複数モーターの同時駆動
複数のステッピングモーターを同時に鳴らす必要があったため、delay()は使えません(モーターが同時動作できなくなるため)。代わりにmicros()を使ってパルス間隔を計算する方式を採用しました。
各モーターごとに異なる速度が必要なため、速度変数を配列化し、インデックスをモーター番号=MIDIチャネルに対応させました。当初はmillis()を使っていましたが、分解能が足りず音程が出せなかったためmicros()に変更しました。
配列化のおかげで、配列サイズを変えるだけで任意の数のモーターを制御できるようになりました。
速度計算と音程マッピング
テストでtone()命令を使って440Hzの矩形波をSTEPピンに入力したところ、ステッピングモーターからA4(440Hz)の音が出ることを確認しました。ステッピング関数に渡す速度値はマイクロ秒単位の周期なので、音程周波数を周期に変換すればよいことになります。
この値をpitchValues配列に格納し、インデックスをMIDIノート番号に対応させました。配列を使うことで、各音程の速度を完全に制御でき、演奏可能な音域を自由に設定できます。速度値0は「停止」として扱います。
また、ステッピングモーターには共振周波数付近で異音(ストール音)が出る問題があります。自分の環境ではF3付近が共振周波数だったため、E3・F3・F#3を1オクターブずらして対処しました(詳細は同梱の「Tune Stepper.ino」で確認可能)。
USB MIDIデバイス化
デバイスをMIDIデバイスとして認識させるため、ボード上のAVRチップ(ATmega16U2等)のファームウェアを書き換える方法を採用しました。HIDUINOまたはmocuLUFAが使えますが、デュアルブート対応のmocuLUFAを選択しました。ICSPヘッダーにジャンパーを挿すだけでUSB MIDIモードとUSBシリアルモードを切り替えられ、Arduinoの再書き込み時にAVRファームウェアを再書き込みする手間がありません。
ソースコード
完全なコードとインストール手順はGitHubリポジトリで公開しています:
https://github.com/jzkmath/Arduino-MIDI-Stepper-Motor-Instrument
カスタムパーツとエンクロージャ
- ステッピングモーター固定用パーツ
- モーター軸に取り付ける「指」パーツ(見た目用)
回路図
- CNC Shield V3使用時のジャンパー配置
- ブレッドボード配線図
- Fritzing回路図(ブレッドボード図にない部品値も含む)
- MIDI DINジャック使用時の配線図
各回路図は画像ファイルを参照してください。
製造プロセス