Willem Hillier
Published © GPL3+

Bluetooth MIDI-Operated Antique Reed Organ

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

AdvancedWork in progressOver 12 days9,699
Bluetooth MIDI-Operated Antique Reed Organ

Things used in this project

Hardware components

Arduino Mega 2560
Arduino 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
Resistor 220 ohm
Resistor 220 ohm
×1
HC-06 Bluetooth Module
×1

Software 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.

Story

Read more

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.

Code

Arduino #1

Arduino
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 #2

Arduino
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 #3

Arduino
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);
  }
}

Credits

Willem Hillier

Willem Hillier

0 projects • 7 followers
Musician and maker.
Thanks to leKuk.

Comments