概要
この記事に続き、Arduino nano 33 IoTのBLEとIMUを使ってMIDIコントローラーを作ってみます。
今回のデモの音源も、iOSアプリの KORG Gadget 2 で、制御するのは、"Phenix"のPitch(Pitch)とVolume(CC7)です。
ボードをX軸に倒すとPitchが変わり、Y軸に倒すとVolumeが変わる、というものになります。
KORG Gadget2のシンセの中で、"Phonix"だけPitchBendのレンジ変えられるので、このシンセを選びました。
このボードにはユーザーボタンがないので、音を出すのは、"Phonix"のキーボードを押すか、シーケンスを組むかで音を出してください。
開発環境準備
Arduino IDEで下記をインストールしてください。
ボードマネージャー
ライブラリ
- WiFiNINA (今回は使いませんが。)
- ArduinoBLE
- Arduino_LSM6DS3
昔に比べて、ArduinoのWebページ、かなり分かりやすくなってますね。
ソース
#include <ArduinoBLE.h>
#include <Arduino_LSM6DS3.h>
// BLE MIDI Service
BLEService midiService("03B80E5A-EDE8-4B33-A751-6CE34EC4C700");
// BLE MIDI OUT Characteristic
BLECharacteristic midiOutChar("7772E5DB-3868-4112-A1A9-F2669D106BF3",
BLERead | BLENotify, 5);
//MIDI Buff
uint8_t midiPayload[] = {0x80, 0x80, 0xB0, 0x01, 0x64};
//CC Buff
int i;
uint8_t cc[128];
//Pitch Buff
uint16_t pitch;
//IMU Buff
float x, y, z;
uint16_t midiX, midiY;
void setup() {
// initialize serial communication
Serial.begin(9600);
// initialize the built-in LED pin to indicate when a central is connected
pinMode(LED_BUILTIN, OUTPUT);
//Buff initialize
for(i = 0; i < 128; i++)
{
cc[128] = 64;
}
pitch = 8192;
// begin initialization
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (1);
}
if (!IMU.begin()) {
Serial.println("Failed to initialize IMU!");
while (1);
}
//BLE Initialize
BLE.setLocalName("AN33IoT");
BLE.setAdvertisedService(midiService);
midiService.addCharacteristic(midiOutChar);
BLE.addService(midiService);
// start advertising
Serial.println("Bluetooth device active, waiting for connections...");
BLE.advertise();
}
void loop() {
// wait for a BLE central
BLEDevice central = BLE.central();
if (central) {
Serial.print("Connected to central: ");
Serial.println(central.address());
digitalWrite(LED_BUILTIN, HIGH);
while (central.connected()) {
if (IMU.accelerationAvailable()) {
IMU.readAcceleration(x, y, z);
midiX = mapAndLimit((int)(x * 16384.0), -8192, 8191, 0, 16383);
midiY = mapAndLimit((int)(y * 1000.0), 500, -500, 0, 127);
notifyPitch(midiX, 1);
notifyCC(7, (uint8_t)midiY, 1);
delay(1);
}
}
// when the central disconnects, turn off the LED:
digitalWrite(LED_BUILTIN, LOW);
Serial.print("Disconnected from central: ");
Serial.println(central.address());
}
}
//NotifyCC
void notifyCC(uint8_t ccNum, uint8_t midiValue, uint8_t sensitivity)
{
if(abs(cc[ccNum] - midiValue) > sensitivity)
{
cc[ccNum] = midiValue;
//Send Note
midiPayload[2] = 0xb0;
midiPayload[3] = ccNum;
midiPayload[4] = midiValue;
Serial.print("CC");
Serial.print(ccNum);
Serial.print(":");
Serial.println(midiValue);
//Notify MIDI Data
midiOutChar.writeValue(midiPayload, 5);
}
}
//NotifyPitch
void notifyPitch(int value, int sensitivity)
{
if(abs(pitch - value) > sensitivity)
{
//元情報にデータを入れておく
pitch = value;
//valueをCC(ccNum)のデータにする
midiPayload[2] = 0xe0;
midiPayload[3] = value & 127;
midiPayload[4] = value >> 7;
Serial.print("Pitch");
Serial.print(":");
Serial.println(value);
//Notify MIDI Data
midiOutChar.writeValue(midiPayload, 5);
}
}
//Map and Limit
uint16_t mapAndLimit(int inputValue, int fromLow, int fromHigh, int toLow, int toHigh)
{
int tmp, minValue, maxValue;
if(toLow < toHigh)
{
minValue = toLow;
maxValue = toHigh;
}
else
{
minValue = toHigh;
maxValue = toLow;
}
tmp = inputValue - fromLow;
tmp = (int)((double)tmp * (double)(toHigh - toLow) / (double)(fromHigh - fromLow));
tmp += toLow;
tmp = tmp < minValue ? minValue : tmp;
tmp = tmp > maxValue ? maxValue : tmp;
return (uint16_t)tmp;
}
動作所感
相変わらずPitchはガタガタですが、ESP32のBLEでも綺麗に動いてくれました。
M5StickCとの違い
1. コンパイル、アップロードが速い
M5StickCも大分速度上がってましたが、このボードは、もうワンランク、コンパイル、アップロードが速かったですね。流石、純正ですね。
2.アナログ入力が8つある
今、自分が作りたいのは、 KORG Gadget 2 の"Chicago"のTB-303の上の6つのノブに当たるCCを可変抵抗で操作するものです。このボードには、アナログ入力が8端子あるので、簡単に作成できます(できたら、また記事上げます。)。
IMUで新しい音作りが出来るか期待したんですが、303系の音作りはやっぱりノブですね。
Wavetable系は、まだIMUで面白いことできる気もしますが...
まとめ
ようやく日本の技適の通ったArduino nano 33 IoTを使えば、簡単にBLE MIDIコントローラーを作れることが分かりました。皆さんも、お気に入りのMIDIコントローラを作ってみてはいかがでしょうか?
ノブ6つのコントローラでいいなら、nanoKEY Studio買った方が速いんですけどね...
これならWinでも動くし...
ただ、コンパクトなのが欲しいんですよね...