Project in progress
Bluetooth MIDI-Operated Antique Reed Organ

Bluetooth MIDI-Operated Antique Reed Organ © GPL3+

Antique reed organ + solenoids + custom driver boards + 3 Arduino Megas + Bluetooth = MIDI-driven reed organ

  • 5,755 views
  • 3 comments
  • 21 respects

Components and supplies

Ardgen mega
Arduino Mega 2560 & Genuino Mega 2560
×3
ZYE1-0530 Solenoid
×88
Custom Solenoid Driver Board
Design files attached. I manufactured 15@ FirstPCB.com for a total cost of $50 shipped.
×1
IRLZ-44N MOSFET
×1
4415447 jg5sklyzsj
Resistor 220 ohm
×1
HC-06 Bluetooth Module
×1

Apps and online services

Hairless MIDI < - > Serial Bridge
This software allows us to send MIDI data from any application on your computer to a serial port, in this case the Bluetooth reciever, which the Arduinos then respond to.

About this project

This page was used for a brief description of the project before I published it on Instructables.com. Please view the much more detailed Instructable here: https://www.instructables.com/id/MIDI-Controlled-88-Key-Reed-Organ/

For my high-school senior project, I was going to convert an upright piano to be a MIDI-controlled player piano. However, I by chance ran across a reed organ, and knowing nothing about them became very interested in their sound and history. So I instead converted an Estey Reed organ to be MIDI operated. This is the result.

For now, just the keys are MIDI controlled. I plan on adding a vacuum motor so it doesn't have to be foot pumped, as well as control of the stops on the cheekblocks.

I am currently writing a very detailed Instructable. For now, here are some photos and some demo videos.

Demo playlist here: https://www.youtube.com/watch?v=36Er-6ZRR6Q&list=PLbli1gTIi5kp9_iqoVi0sN5cbYPDn0naH

Suggest a song or upload a MIDI file for it to play here: http://bit.ly/2wR3QUE

Code

Arduino #1Arduino
For the left-most Arduino
byte incomingByte;
byte note;
byte velocity;

int statusLed = 13;   // select the pin for the LED

int action = 2; //0 =note off ; 1=note on ; 2= nada

//setup: declaring iputs and outputs and begin serial
void setup() {
  pinMode(statusLed, OUTPUT);  // declare the LED's pin as output

  int inMin = 22; // Lowest input pin
  int inMax = 53; // Highest input pin
  for (int i = inMin; i <= inMax; i++) {
    pinMode(i, OUTPUT);
  }

  Serial1.begin(38400);
  digitalWrite(statusLed, HIGH);
}

//loop: wait for serial data, and interpret the message
void loop () {
  if (Serial1.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial1.read();

    // wait for as status-byte, channel 1, note on or off
    if (incomingByte == 144) { // note on message starting starting
      action = 1;
    } else if (incomingByte == 128) { // note off message starting
      action = 0;
    } else if (incomingByte == 208) { // aftertouch message starting
      //not implemented yet
    } else if (incomingByte == 160) { // polypressure message starting
      //not implemented yet
    } else if ( (action == 0) && (note == 0) ) { // if we received a "note off", we wait for which note (databyte)
      note = incomingByte;
      playNote(note, 0);
      note = 0;
      velocity = 0;
      action = 2;
    } else if ( (action == 1) && (note == 0) ) { // if we received a "note on", we wait for the note (databyte)
      note = incomingByte;
    } else if ( (action == 1) && (note != 0) ) { // ...and then the velocity
      velocity = incomingByte;
      playNote(note, velocity);
      note = 0;
      velocity = 0;
      action = 0;
    } else {
      //nada
    }
  }
}

void blink() {
  digitalWrite(statusLed, HIGH);
  delay(100);
  digitalWrite(statusLed, LOW);
  delay(100);
}


void playNote(byte note, byte velocity) {
  int value = LOW;
  if (velocity > 10) {
    value = HIGH;
  } else {
    value = LOW;
  }

  if (note > 20 && note < 55) {
    digitalWrite((note + 1), value);
  }
}
Arduino #2Arduino
Center Arduino code. All Arduinos are running essentially the same code, they just respond to different MIDI note ranges.
byte incomingByte;
byte note;
byte velocity;

int statusLed = 13;   // select the pin for the LED

int action = 2; //0 =note off ; 1=note on ; 2= nada

//setup: declaring iputs and outputs and begin serial
void setup() {
  pinMode(statusLed, OUTPUT);  // declare the LED's pin as output

  int inMin = 22; // Lowest input pin
  int inMax = 53; // Highest input pin
  for (int i = inMin; i <= inMax; i++) {
    pinMode(i, OUTPUT);
  }

  Serial1.begin(38400);
  digitalWrite(statusLed, HIGH);
}

//loop: wait for serial data, and interpret the message
void loop () {
  if (Serial1.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial1.read();

    // wait for as status-byte, channel 1, note on or off
    if (incomingByte == 144) { // note on message starting starting
      action = 1;
    } else if (incomingByte == 128) { // note off message starting
      action = 0;
    } else if (incomingByte == 208) { // aftertouch message starting
      //not implemented yet
    } else if (incomingByte == 160) { // polypressure message starting
      //not implemented yet
    } else if ( (action == 0) && (note == 0) ) { // if we received a "note off", we wait for which note (databyte)
      note = incomingByte;
      playNote(note, 0);
      note = 0;
      velocity = 0;
      action = 2;
    } else if ( (action == 1) && (note == 0) ) { // if we received a "note on", we wait for the note (databyte)
      note = incomingByte;
    } else if ( (action == 1) && (note != 0) ) { // ...and then the velocity
      velocity = incomingByte;
      playNote(note, velocity);
      note = 0;
      velocity = 0;
      action = 0;
    } else {
      //nada
    }
  }
}

void blink() {
  digitalWrite(statusLed, HIGH);
  delay(100);
  digitalWrite(statusLed, LOW);
  delay(100);
}


void playNote(byte note, byte velocity) {
  int value = LOW;
  if (velocity > 10) {
    value = HIGH;
  } else {
    value = LOW;
  }

  if (note > 52 && note < 85) {
    digitalWrite((note - 31), value);
  }
}
Arduino #3Arduino
Right Arduino. All Arduinos are running essentially the same code, they just respond to different MIDI note ranges.
byte incomingByte;
byte note;
byte velocity;

int statusLed = 13;   // select the pin for the LED

int action = 2; //0 =note off ; 1=note on ; 2= nada

//setup: declaring iputs and outputs and begin serial
void setup() {
  pinMode(statusLed, OUTPUT);  // declare the LED's pin as output

  int inMin = 22; // Lowest input pin
  int inMax = 53; // Highest input pin
  for (int i = inMin; i <= inMax; i++) {
    pinMode(i, OUTPUT);
  }

  Serial1.begin(38400);
  digitalWrite(statusLed, LOW);
}

//loop: wait for serial data, and interpret the message
void loop () {
  if (Serial1.available() > 0) {
    digitalWrite(statusLed, HIGH);
    // read the incoming byte:
    incomingByte = Serial1.read();

    // wait for as status-byte, channel 1, note on or off
    if (incomingByte == 144) { // note on message starting starting
      action = 1;
    } else if (incomingByte == 128) { // note off message starting
      action = 0;
    } else if (incomingByte == 208) { // aftertouch message starting
      //not implemented yet
    } else if (incomingByte == 160) { // polypressure message starting
      //not implemented yet
    } else if ( (action == 0) && (note == 0) ) { // if we received a "note off", we wait for which note (databyte)
      note = incomingByte;
      playNote(note, 0);
      note = 0;
      velocity = 0;
      action = 2;
    } else if ( (action == 1) && (note == 0) ) { // if we received a "note on", we wait for the note (databyte)
      note = incomingByte;
    } else if ( (action == 1) && (note != 0) ) { // ...and then the velocity
      velocity = incomingByte;
      playNote(note, velocity);
      note = 0;
      velocity = 0;
      action = 0;
    } else {
      //nada
    }
  }
}

void blink() {
  digitalWrite(statusLed, HIGH);
  delay(100);
  digitalWrite(statusLed, LOW);
  delay(100);
}


void playNote(byte note, byte velocity) {
  int value = LOW;
  if (velocity > 10) {
    value = HIGH;
  } else {
    value = LOW;
  }

  if (note > 84 && note < 109) {
    digitalWrite((note - 63), value);
  }
}

Schematics

16-Channel MOSFET Solenoid Driver Board
Please note that using this file you can't actually solder in the MOSFETs; the holes are just big enough to jam them in. This makes them easier to replace.
solenoid_driver_board_v4_LbLvMU6CF4.fzz

Comments

Similar projects you might like

ClearWalker Bluetooth Control

Project showcase by Jeremy S. Cook

  • 2,371 views
  • 4 comments
  • 11 respects

Connecting "stuff" via Bluetooth / Android / Arduino

Project tutorial by MJRoBot

  • 12,681 views
  • 20 comments
  • 32 respects

Bluetooth Controlled & Obstacle Avoiding Arduino Robot

Project showcase by KureBas Robotics

  • 8,435 views
  • 11 comments
  • 20 respects

Make an Enhanced R2-D2 to Be Controlled by an Android App

Project tutorial by Kutluhan Aktar

  • 1,426 views
  • 0 comments
  • 2 respects

Otto DIY+ Arduino Bluetooth Robot Easy to 3D Print

Project tutorial by Team Otto builders

  • 48,193 views
  • 117 comments
  • 162 respects

Arduino/Android - BLUETOOTH Multi Servo Motor Control

Project tutorial by Danny van den Brande

  • 13,925 views
  • 8 comments
  • 19 respects
Add projectSign up / Login