孫の手MIDIバイオリン

先日、Arduino Uno R3でMIDIコントローラーを作るというページを見つけたので、100円ショップで孫の手を2本買ってきて、バイオリンのように弾けるMIDIコントローラーを作ってみた。

孫の手MIDIバイオリン

孫の手MIDIバイオリン

孫の手MIDIバイオリン

弓側のゴムバンドでロータリーエンコーダーを回す

片方がバイオリン本体でもう一方が弓。
弓は孫の手の指の間にゴムバンドを引っ掛けただけ。

音階を決めるネック部分は2cm毎に5mmのCdS(光センサ)を7つ埋め込んであって、指で隠すことで音階を決める。
弓でこする弦の代わりにロータリーエンコーダーを回すことで弾いていることを検出する。

ネック部分(CdSが埋め込まれている)

ネック部分(CdSが埋め込まれている)

ロータリーエンコーダー部分(演奏していることを検出)

ロータリーエンコーダー部分(演奏していることを検出)

ネック部分の裏

ネック部分の裏(CdSの裏からホットボンドを流しこんである)

ロータリーエンコーダーの裏

ロータリーエンコーダーの裏

Arduino Uno R3とプロトシールド

Arduino Uno R3とプロトシールド

Arduino Uno R3とプロトシールド

Arduino Uno R3とプロトシールド

CdSを7つとロータリーエンコーダーの3端子なので手持ちの10芯のフラットケーブルを使った。
黒がGND。ロータリーエンコーダーのGNDは種類によって違うらしいので注意!

スケッチはロータリーエンコーダーの処理を参考にしたページとMIDIコントローラーのページからコピペしてちょっと変えただけなので、無駄な変数も残っています。

#define NOTE_ON 144
#define NOTE_OFF 128
#define CONTROL_CHANGE 176
#define ALL_NOTE_OFF 120

volatile int state = 0;
volatile boolean Flag_A = true;
volatile boolean Flag_B = false;

#define BUTTON_MAX 7
int pin_no[] = {4,5,6,7,8,9,10}; //ピン番号を保存
int sw_state[] = {0,0,0,0,0,0,0}; //スイッチ状態を保存
int note_no[] = {60,61,62,63,64,65,66,67}; //スイッチ毎のノートナンバー
int curr_note = 0;
int prev_state = 0;

void setup()
{
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  attachInterrupt(0, Fall_A, FALLING);
  attachInterrupt(1, Change_B, CHANGE);
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  pinMode(6, INPUT);
  pinMode(7, INPUT);
  pinMode(8, INPUT);
  pinMode(9, INPUT);
  pinMode(10, INPUT);
  Serial.begin(31250);
  sendMidi(CONTROL_CHANGE, ALL_NOTE_OFF, 0);
}

void loop()
{
  int save_state = state;
  delay(1000);
  if (curr_note && (save_state == state)) {
    sendMidi(NOTE_ON, curr_note, 0);
    curr_note = 0;
  }
}

void Fall_A()
{
  if (!Flag_A) { return; }
  Flag_B = true;
  Flag_A = false;
}

void Change_B()
{
  if (!Flag_B) { return; }
  if (HIGH == digitalRead(2)) {
    if (HIGH == digitalRead(3)) {
      state--;
    } else {
      state++;
    }
    Flag_B = false;
    Flag_A = true;
    int new_note = 60;
    if (HIGH == digitalRead(4)) {
      new_note = 61;
    }
    if (HIGH == digitalRead(5)) {
      new_note = 62;
    }
    if (HIGH == digitalRead(6)) {
      new_note = 63;
    }
    if (HIGH == digitalRead(7)) {
      new_note = 64;
    }
    if (HIGH == digitalRead(8)) {
      new_note = 65;
    }
    if (HIGH == digitalRead(9)) {
      new_note = 66;
    }
    if (HIGH == digitalRead(10)) {
      new_note = 67;
    }
    if (curr_note != new_note) {
      if (curr_note != 0) {
        sendMidi(NOTE_ON, curr_note, 0);
      }
      curr_note = new_note;
      sendMidi(NOTE_ON, curr_note, 127);
    }
    prev_state = state;
  }
}

void sendMidi(int cmd, int pitch, int velocity)
{
  Serial.write(cmd);
  Serial.write(pitch);
  Serial.write(velocity);
}

見ての通り、Serial.writeで書き出すだけなので、最初のうちはprintにしておいてシリアルモニターでデバッグできるのが便利。
最終的にwriteにして、Arduino Uno R3上のAtmega16U2のプログラムを書き換えてUSB MIDIデバイスにすればOKという手軽さ。

しかし、このAtmega16U2のプログラムを書き換えるのに四苦八苦した。
この件は別に記す

参考にしたページ
ロータリーエンコーダーの処理:ロータリーエンコーダとArduinoを直結する
MIDIコントローラー:【DJ】Arduinoで自作MIDIコントローラーを作ってみる【VJ】
MIDI Firmware:Midi Firmware for Arduino Uno (Moco)

カテゴリー: Arduino, Magitalion, 作ったモノ タグ: , , , , パーマリンク

孫の手MIDIバイオリン への6件のフィードバック

  1. じゃじゃ のコメント:

    Cdsセルでデジタル入力させる時はどのようにしてHIGH、LOWの振り分けをしましたか?
    Cdsがある抵抗をもっている以上電圧がかかってしまいどうしてもデジタル入力が常にHIGHの状態になってしまいます。。。

  2. Yuji のコメント:

    じゃじゃさん

    回路図を描いてなかったので、どう接続していたのか忘れてしまいましたが、写真をよく見たら8素子の集合抵抗器(多分10kΩ)が見えたので抵抗分圧していると思います。

  3. じゃじゃ のコメント:

    返信ありがとうございます。アナログで読み込んで閾値で振り分けることにしました。

    さらに質問なのですが、ロータリーエンコーダの取り付けについてです。僕は発泡スチロールを加工して発泡スチロール中にロータリーエンコーダを埋めるという方法を用いようとしたのですがロータリーエンコーダを回す際にぐらぐらして固定できません。何か良い固定方法はありませんか。(Yujiさんのリンク先が消えていましたので)

  4. Yuji のコメント:

    じゃじゃさん

    グルーガンを使ったらいかがでしょう?
    接着してしまうので、基本的に一回限りになりますけど。
    (部品を溶かさないので、綺麗に剝がせれば何回でもやり直せますし。)

  5. じゃじゃ のコメント:

    グルーガンつかえますね!ありがとうございました。

  6. Yuji のコメント:

    じゃじゃさん

    頑張ってください!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA