ドラムマシーンを足で演奏することを目指しています。
手で演奏するプロトタイプを作成しました。
・arduino uno
・SparkFun midiシールド
・leapmotion
・node.js
・CASIO キーボード CTK-530
leapmotionとarduinoでシリアル通信
参考サイト: ArduinoとNode.jsでシリアル通信で文字列を送受信するスクリプト ArduinoとLeapmotionのシリアル接続まずはleapmotion側(node.js)
準備物は↑を参照願います。
leap-arduino.js
"use strict"
const serialport = require('serialport');
// arduinoポート名指定(arduino IDEから取得)
var portName = '/dev/cu.usbmodem1421';
/* jsライブラリ読込 */
var Leap = require("leapjs");
var five = require('johnny-five');
var yPosi = 0; //座標
var G_KICK_TIME = new Date();//センサーキック時刻
var C_WAITE_TIME = 100; //ミリ秒
//Leap Motionコントローラー作成
var controller = new Leap.Controller();
//leapmotionと接続開始
controller.connect();
//手を認識
controller.on('hand', function (gesture,e) {
//y軸取得
yPosi = gesture.palmPosition[1];
yPosi = parseInt(yPosi);
var ss = new Date();
//前回のarduino送信からの時間比較
if(ss.getTime() - G_KICK_TIME.getTime() >= C_WAITE_TIME ){
//C_WAITE_TIME経過した場合
//arduino通信発生時刻
G_KICK_TIME = new Date();
console.log("ON");
//arduinoへ送信する関数
write(yPosi);
}
});
const Readline = serialport.parsers.Readline;
const parser = new Readline();
const spp = new serialport(portName,{
baudRate: 31250,//midiのボーレートが31250
dataBits: 8,
parity: 'none',
stopBits: 1,
flowControl: false,
parser: parser
});
//シリアル通信開始
spp.on('open', function () {
console.log('Serial open.');
});
//arduinoから受信した場合の処理(今回は未使用)
//spp.on('data', function (data) {
// //console.log('spp.on-data:' + data);
//});
//arduinoへ送信
function write(data) {
//y軸座標の範囲で値を設定;
var sendData;
if (data > 0 && data <= 160){
//スネアドラム
sendData = 'a';
} else if (data > 160 && data <= 200){
//ハイハットclose
sendData = 'b';
} else if (data > 200 && data <= 250){
//ハイハットopen
sendData = 'c';
} else {
//上記以外
sendData = '0';
}
data = sendData;
//送信データ表示
console.log('Mac:' + data);
//arduinoへ値送信!
spp.write(new Buffer.from(data), function(err, results) {
if(err) {
//エラーメッセージ表示
console.log('Err: ' + err);
}
});
}
続いてarduino側です。
参考サイト
Arduino MIDI Library の使い方
手をかざすとC_WAITE_TIMEの間隔でCASIOキーボードのドラムを鳴らします。
//MIDIライブラリ使用のためのヘッダファイル読み込み
#include <MIDI.h>
// MIDIクラスのインスタンスとして"MIDI"を生成する。
MIDI_CREATE_DEFAULT_INSTANCE();
#define LED 13
int recieveByte = 0;
String bufferStr = "";
String okStr = "OK";
//送信ONフラグ
const bool C_ON = true;
const bool C_OFF = false;
//ノート情報
const int C_NOTE_VEROCITY = 40;
const int C_NOTE_CHANNEL = 1;
bool bLedState = false; //受信状態 true:on false:off
int pitchNo = 0;
void setup() {
Serial.begin(31250); //midiのボーレートが31250
MIDI.begin(); // MIDIインスタンスの初期化
}
void loop() {
bufferStr = "";
while (Serial.available() > 0) {
recieveByte = Serial.read();
if (recieveByte == (int)'\n') break;
bufferStr.concat((char)recieveByte);
}
//受信信号実行中の場合無視して次へ
if(bLedState == C_OFF){
//受信データによりCASIOキーボードへMIDI送信
if (bufferStr.length() > 0) {
if (bufferStr == "a") {
bLedState = C_ON;
pitchNo = 38;//スネア
} else if (String(bufferStr) == "b") {
bLedState = C_ON;
pitchNo = 44;//ハイハットclose
} else if (String(bufferStr) == "c") {
bLedState = C_ON;
pitchNo = 46;//ハイハットopen
} else {
bLedState = C_OFF;
pitchNo = 36;//バスドラ
}
//ノートオン(pitch, velocity, channel)
MIDI.sendNoteOn(pitchNo, C_NOTE_VEROCITY, C_NOTE_CHANNEL);
//待機後信号受付状態にする
bLedState = C_OFF;
MIDI.sendNoteOff(pitchNo, C_NOTE_VEROCITY, C_NOTE_CHANNEL);
}
}
}
MIDIのボーレートの既定値が31250のため、シリアル通信もそれに合わせています。
そうしないとarduino側で受信データが文字化けしてしまいます。
これでハマりました。
スイッチサイエンスで距離計測センサーを購入したので、届き次第leapmotionからこのセンサーに変更します。
記事は着手次第アップします。