ひとまずは、パソコン上のDAWを使ってMIDI信号を出力し、CV/GATE信号に変換する、MIDI-CVコンバーターを作ってみることにしました。
作戦
ArduinoとmbedのMIDI Libraryを簡単に試したことがありますが(https://dad8893.blogspot.com/search/label/MIDI%20Library)、サイズの小さいNucleo F303K8を使ってmbedでやってみると、どうもMIDIメッセージを読みこぼすようです。
Nucleo-F303K8は12bit DACが3系統内蔵されていて、性能もCortex-M4でそこそこ高スペックなので使ってみたかったのですが、まずはArduinoでやってみることにしました。
Arduino NANOかArduino Pro Miniを使うつもりです。
想定している使用例
ArduinoにSPI/DACのMCP4922を接続し、アナログ値を出力してCVとします。MCP4922は2ch DACなのでうまく行けば2ch分CVを出力できます。
Nucleo_DCOは3.3V系(5Vトレラント)なのでCVの信号レベルは0V~3.3Vとします。
「DASS01」(「ASS01」という名前にしようと思ってましたが、「DASS01」に変更します)はアナログ系でCV信号にもう少し振幅が欲しいので「DASS01」内の「Amp」で増幅します。増幅率は「Mod Level」POTで可変します。
GATE信号はGPIOから出力します。「Arduino_EG」のプロセッサーは5V駆動のArduino Pro Miniなので入力するGATE信号レベルは5VでOKです。「KIK01」はNucleo-F446RE、「BSM02」はNucleo-F401REでSyncIn(GATEの立ち上がりで評価)は3.3V系ですが5Vトレラントなのでこれも5VでOKです。
開発環境
ArduinoでMIDI Libraryを使うとデフォルトではハードウェアUART(D0, D1)を使うので、デバッグ用にArduinoのSerialクラスが使えません。簡単なメッセージの表示しかできませんが、I2C接続のキャラクタLCD(秋月のAE-AQM1602A)を使うことにしました。
ブレッドボード配線図
※Arduinoで書き込むときは、RXの配線を抜く。
※MCP4922はまだ接続していません。
Arduinoのスケッチ
AE-AQM1602Aのライブラリは「I2CLiquidCrystal-1.5 https://n.mtng.org/ele/arduino/i2c.html」を使いました。
<MIDI_Display_Message_I2C_LCD_Gate.ino>
#include <Wire.h> #include <I2CLiquidCrystal.h> #include <MIDI.h> #define LCD_TRACE (0) #define PIN_CHECK (1) #define TITLE_STR1 ("MIDI to GATE ") #define TITLE_STR2 ("20181204 ") // Pin assign const int GateOutPin1 = 2; const int GateOutPin2 = 3; const int GateOutPin3 = 4; const int GateOutPin4 = 5; const int GateOutPin5 = 6; const int GateOutPin6 = 7; const int CheckPin1 = 8; // MIDI MIDI_CREATE_DEFAULT_INSTANCE(); // I2C LCD #if (LCD_TRACE) I2CLiquidCrystal lcd(32, (bool)true); #endif // MIDI ------------------------------------------------------------------------- #if (LCD_TRACE) void printNoteOnOff(const char* type, byte inChannel, byte inNote, byte inVelocity) { lcd.setCursor(0, 1); lcd.print(" "); lcd.setCursor(0, 1); lcd.print(type); lcd.print(' '); lcd.print(inChannel); lcd.print(' '); lcd.print(inNote); lcd.print(' '); lcd.print(inVelocity); } #endif void handleNoteOn(byte inChannel, byte inNote, byte inVelocity) { digitalWrite(GateOutPin1, HIGH); #if (LCD_TRACE) printNoteOnOff("On", inChannel, inNote, inVelocity); #endif } void handleNoteOff(byte inChannel, byte inNote, byte inVelocity) { digitalWrite(GateOutPin1, LOW); #if (LCD_TRACE) printNoteOnOff("Off", inChannel, inNote, inVelocity); #endif } // ----------------------------------------------------------------------------- void setup() { pinMode(GateOutPin1, OUTPUT); pinMode(GateOutPin2, OUTPUT); pinMode(GateOutPin3, OUTPUT); pinMode(GateOutPin4, OUTPUT); pinMode(GateOutPin5, OUTPUT); pinMode(GateOutPin6, OUTPUT); pinMode(CheckPin1, OUTPUT); MIDI.setHandleNoteOn(handleNoteOn); MIDI.setHandleNoteOff(handleNoteOff); MIDI.begin(MIDI_CHANNEL_OMNI); #if (LCD_TRACE) lcd.begin(16, 2); lcd.print(TITLE_STR1); lcd.setCursor(0, 1); lcd.print(TITLE_STR2); delay(2000); #endif } void loop() { #if (PIN_CHECK) digitalWrite(CheckPin1, HIGH); #endif if (MIDI.read()) { // Display Raw Midi Message byte type = MIDI.getType(); byte channel = MIDI.getChannel(); byte data1 = MIDI.getData1(); byte data2 = MIDI.getData2(); #if (LCD_TRACE) lcd.setCursor(0, 0); lcd.print(" "); lcd.setCursor(0, 0); lcd.print(type, HEX); lcd.print(' '); lcd.print(channel, HEX); lcd.print(' '); lcd.print(data1, HEX); lcd.print(' '); lcd.print(data2, HEX); #endif } #if (PIN_CHECK) digitalWrite(CheckPin1, LOW); #endif }
メモ:
LCD_TRACEを有効化(1)するとMIDIメッセージを読みこぼす。
中華製のArduino NANOはプロセッサでATMega328P(Old bootloder)を指定する必要がある場合がある。
メインループの処理時間は92kHzぐらいで変わらない?
DACからの出力にはLPFを入れる。Nucleo_DCOはADCにCV信号を入力するので注意。
厳密にするならDACやGPIOからの信号はデジタル回路でラッチをかけて同期させたいけど、そこまでは必要ないか・・・
0 件のコメント:
コメントを投稿