MIDI drawbar controller for Numa Organ (or any MIDI organ module)

Hi,

My first Arduino project: a MIDI controller for a Numa Organ.

I am planning to build a lower manual for the organ with a seperate set of Drawbars. I’ve started with the Drawbare controller, using an Arduino Mega to read the analog drawbars and send this by MIDI to the organ.

The code can be used for other organ modules as well, but you may need to change the MIDI channel and Control Numbers.

The code is working, quite happy with that. But since it is my first code, any tips and tricks would be very welcome. So: What do you think of this piece of coding? Any tips to improve this, or rookie mistakes I should prevent in my next project?

Attached a picture of the temporary hardware setup.

/* 
MIDI drawbar and rotary controller for Numa Organ 2
Written by Bas Jongenburger

Hardware setup:

Inputs:
  9 10K Slider potentiometers on A0 - A8 inputs
  3-way selector switch on Digital input 34 and 40
    Slow: I34 HIGH
    Fast: I40 HIGH
    Stop: I34 & I 40 HIGH
    10k Pull-down resistors installed

Output:
5-pins MIDI connector
  Pin 2: GND
  Pin 4: +5V via 220 Ohm resistor
  Pin 5: TX1 via 220 Ohm resistor
*/

#include <MIDI.h>

MIDI_CREATE_INSTANCE(HardwareSerial,Serial, midiOut); // create a MIDI object called midiOut

int const DBChannel = 2; // define DB channel
int const RChannel = 1; // define rotary channel
int const RCN = 68; // define rotary control number

int const AInput[9] = {A0, A1, A2, A3, A4, A5, A6, A7, A8}; // define array for Analog input channels
int const DBCN[9] = {12, 13, 14, 15, 16, 17, 18, 19, 20}; // define array for MIDI Drawbar control number
int DBl[9] = {128, 128, 128, 128, 128, 128, 128, 128, 128}; // define Drawbar last array
int DBs[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; // define Drawbar state array

// rotary switch input pins
int const RIslow = 34;
int const RIfast = 40;
int RSslow;
int RSfast;

// Rotary state and rotary int
int Rotarystate = 0;
int Rotary = 128;

unsigned long timer;
int LedTime;
int i;

void setup() {
  // setup input pins for rotary inputs.
  // input pins have a pulldown resistor installed
  pinMode(RSslow,INPUT);
  pinMode(RSfast,INPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  
  Serial.begin(31250); // setup MIDI output
}

void loop() {

  for (i = 0; i < 9; i++){
    DBs[i] = analogRead(AInput[i]) / 8; // read analog input, divide  by 8 to scale value to 0-127
    if ((DBs[i]-DBl[i]) > 1 || (DBs[i]-DBl[i]) < -1) {
      // value changed?
      if (DBs[i] != DBl[i]) {
        // send serial value (ControlNumber DBCN, ControlValue = DBs, Channel DBchannel)
        // more info: http://arduinomidilib.sourceforge.net/a00001.html
        midiOut.sendControlChange(DBCN[i], DBs[i], DBChannel);
        DBl[i] = DBs[i]; // update DBl
        digitalWrite(LED_BUILTIN, HIGH); // Turn on Builtin LED for set duration
        timer = millis();
        LedTime = 200;
      }
    }
  }
    
  // Read rotary inputs
  RSslow = digitalRead(RIslow);
  RSfast = digitalRead(RIfast);

  // calculate Rotarystate value
  // 0 for stop, 
  // 64 for slow
  // 127 for fast
  Rotarystate = (RSslow ^ RSfast) * ((RSslow * 64) + (RSfast * 127));

  // Check change in Rotary and send MIDI CC
  if ((Rotarystate != Rotary) && (RSslow + RSfast > 0)) { // No Midi output when value is the same or both inputs are low
    midiOut.sendControlChange(RCN, Rotarystate, RChannel);
    Rotary = Rotarystate; // update Rotary value
    digitalWrite(LED_BUILTIN, HIGH); // Turn on builtin LED for set duration
    timer = millis();
    LedTime = 1000;
  }
  
  // turn off Builtin LED when Ledtime value is reached.
  if (millis() - timer > LedTime){
    digitalWrite(LED_BUILTIN, LOW);
  }
}

2 minor updates:
6s delay in setup Loop will start running when organ has started up.
DBl array is now defined at 130. Therefore the condition in the IF loop is alway true and the value is overwritten with the actual Drawbar value

if ((DBs[i]-DBl[i]) > 1 || (DBs[i]-DBl[i]) < -1) {
      // value changed?
      if (DBs[i] != DBl[i]) {
        // send serial value (ControlNumber DBCN, ControlValue = DBs, Channel DBchannel)
        // more info: http://arduinomidilib.sourceforge.net/a00001.html
        midiOut.sendControlChange(DBCN[i], DBs[i], DBChannel);
        DBl[i] = DBs[i]; // update DBl
        digitalWrite(LED_BUILTIN, HIGH); // Turn on Builtin LED for set duration
        timer = millis();
        LedTime = 200;
      }
    }

The complete code is now:

/* 
MIDI drawbar and rotary controller for Numa Organ 2
Written by Bas Jongenburger

Hardware setup:

Inputs:
  9 10K Slider potentiometers on A0 - A8 inputs
  3-way selector switch on Digital input 34 and 40
    Slow: I34 HIGH
    Fast: I40 HIGH
    Stop: I34 & I 40 HIGH
    10k Pull-down resistors installed

Output:
5-pins MIDI connector
  Pin 2: GND
  Pin 4: +5V via 220 Ohm resistor
  Pin 5: TX1 via 220 Ohm resistor
*/

#include <MIDI.h>

MIDI_CREATE_INSTANCE(HardwareSerial,Serial, midiOut); // create a MIDI object called midiOut

int const DBChannel = 2; // define DB channel
int const RChannel = 1; // define rotary channel
int const RCN = 68; // define rotary control number

int const AInput[9] = {A0, A1, A2, A3, A4, A5, A6, A7, A8}; // define array for Analog input channels
int const DBCN[9] = {12, 13, 14, 15, 16, 17, 18, 19, 20}; // define array for MIDI Drawbar control number
int DBl[9] = {130, 130, 130, 130, 130, 130, 130, 130, 130}; // define Drawbar last array
int DBs[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; // define Drawbar state array

// rotary switch input pins
int const RIslow = 34;
int const RIfast = 40;
int RSslow;
int RSfast;

// Rotary state and rotary int
int Rotarystate = 0;
int Rotary = 128;

unsigned long timer;
int LedTime;
int i;

void setup() {
  // setup input pins for rotary inputs.
  // input pins have a pulldown resistor installed
  pinMode(RSslow,INPUT);
  pinMode(RSfast,INPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  
  delay(6000); // wait for Numa Organ to startup
  
  Serial.begin(31250); // setup MIDI output
}

void loop() {

  for (i = 0; i < 9; i++){
    DBs[i] = analogRead(AInput[i]) / 8; // read analog input, divide  by 8 to scale value to 0-127
    if ((DBs[i]-DBl[i]) > 1 || (DBs[i]-DBl[i]) < -1) {
      // value changed?
      if (DBs[i] != DBl[i]) {
        // send serial value (ControlNumber DBCN, ControlValue = DBs, Channel DBchannel)
        // more info: http://arduinomidilib.sourceforge.net/a00001.html
        midiOut.sendControlChange(DBCN[i], DBs[i], DBChannel);
        DBl[i] = DBs[i]; // update DBl
        digitalWrite(LED_BUILTIN, HIGH); // Turn on Builtin LED for set duration
        timer = millis();
        LedTime = 200;
      }
    }
  }
    
  // Read rotary inputs
  RSslow = digitalRead(RIslow);
  RSfast = digitalRead(RIfast);

  // calculate Rotarystate value
  // 0 for stop, 
  // 64 for slow
  // 127 for fast
  Rotarystate = (RSslow ^ RSfast) * ((RSslow * 64) + (RSfast * 127));

  // Check change in Rotary and send MIDI CC
  if ((Rotarystate != Rotary) && (RSslow + RSfast > 0)) { // No Midi output when value is the same or both inputs are low
    midiOut.sendControlChange(RCN, Rotarystate, RChannel);
    Rotary = Rotarystate; // update Rotary value
    digitalWrite(LED_BUILTIN, HIGH); // Turn on builtin LED for set duration
    timer = millis();
    LedTime = 1000;
  }
  
  // turn off Builtin LED when Ledtime value is reached.
  if (millis() - timer > LedTime){
    digitalWrite(LED_BUILTIN, LOW);
  }
}

Thanks for sharing this! I hope to try this after the holidays. :slight_smile:

Hi Antman,

Your welcome. What organ or module do you use?
Please share your project when you've started, always nice to see what others make of their projects.

In the near future my focus will shift towards fabricating a lower manual prototype. I plan to use the fabricators keyboard scanner for that. The drawbars will be integrated in the keyboard and the breadboard will be replaced by permanent connections.

If I have space for some buttons I may add some drawbar presets to the sketch, but that's for later.

Bjongenburger, I have a PropB3 organ emulator that I made from a Parallax Propeller. I see the creator’s link is no longer working, but I still have the schematics and source code. Up until recently, I’ve been controlling it from an M-Audio Radium keyboard with the sliders for drawbars, but it died.

My plan is to use an old, unused Doepfer MKE board I have with the old Radium keybed and your drawbar controller on the midi merge input. The PropB3 has switch inputs for rotary speaker control, (or you can use the mod wheel), but I’ve been considering getting an external pedal.

Drawbar presets would be awesome, but not necessary, as I no longer gig. I strictly play for enjoyment or recording at home. :slight_smile:

I’ll post what I come up with, but it may take some time as I always have multiple DIY electronic music projects going on. :wink: