Friday, August 29, 2014

Organ pedal for practicing at home - for a few bucks

If someone would like to play the organ, soon will be hit by the problem that he or she can only practice playing the pedal parts in a church, needs approval, needs money, needs traveling - wouldn't it be much simpler if one could practice at home. For that the easiest is probably to buy an organ or build one. But even in the latter case, just the pedal will cost thousands of dollars.

In 2013 I got an idea to make a USB MIDI pedalboard at home, just with simple electronic and household parts, costing around $40, including all electronic and mechanical parts. You might guess that there is some trade-off here, as just the wooden material should cost around $500 for a real pedalboard. Well, take a look at my first prototype:


The trick is capacitive sensing, driving the pedals just by touching. So you need to be in socks or bare feet, and clearly some stuff would be harder or different than on a normal pedalboard, but still is a great aid in learning hand-foot independence, sharing our attention, practice harder parts, the footing, or just to play the organ at home for fun. (Most of my interest goes anyway to casual music players, not for professionals.)

My (beginner) experience is that before performing in the church, one should practice 1-2 hours on site, to get accomodated to the differences. Though this is nothing special, there are virtually no two organs with the same sizes and controls, so unless you are quite experienced, you need that extra practice time anyway.

On the video above you can see, that the "mechanical" part consits of plain household aluminum foil.
So for the full project you'll need the following parts (some of these are best to order from some Chinese gadget shop, so you'll probably need 3-6 weeks to get everything).

From a household/diy shop:
aluminum foil
- paper glue
duct tape
- 20 A4/letter paper
- 150cm polyfoam or similar insulator

From an electronics shop:
60m cheap insulated wire
- 32 pieces of alligator clips
- 4 pieces of CD4021 IC 
- 32 pieces of 680kOhm resistor
- Terminal block for 32 points (spring or screw based, doesn't matter)
- 10kOhm linear potentiometer

Electroincs shop or China (e.g. dx.com):
breadboard (either 1260 point solderless or a cca. 10x20 cm solderable)
- jumper cables for the breadboard

Tools:
- scissors
- soldering station (with a solderless breadboard you don't necessarily need it)
- multimeter (not a big deal, if you don't have one, just without it harder to find possible errors in building.)

You will need a computer, which can run http://www.hauptwerk.com/ organ sampler (but I guess you have one anyway, as this is only the pedal, and you'll probably need 2 more MIDI keyboards as manuals). Also the computer is needed for programming the Arduino.

Let's see what to do.

Electronics

Arduino is the most popular "brain" in DIY hobby electronics - it is a microcontroller, ie. something like a very small computer, which is cheap, small and directly can handle electronics components. There is an official store for officially produced Arduinos, but you can find some cheaper clones as well - mostly they do as well (though I have one clone failed from the 3. The original official one still works perfectly.)

Arduino UNO R3 version is usable for our goals, with some extra electronics we can connect 32 capacitive touch sensors and then upload a program which will turn the Arduino UNO R3 into a MIDI pedalboard with USB output.

When you're building the electronics, it's quite important to do it step by step and always check your work, check the solderings, whether every connection is looking good, there are no shortcuts etc.

When you buy an Arduion the software inside it blinks the small LED. As a first step I recommend uploading our pedalboard software to let us check its working during build.

Programming

Programming our microcontroller take two parts. First, you need to upload a program to the central unit (the atmega328 microntroller), then upload the USB-controller program (changing the firmware in the atmega16u2 chip on the Arduino board) - this will transform the Arduino from a programmable device into a USB musical instrument.

Programming the central unit

Download the microcontroller software from here: organ_pedal.cpp.hex
Using http://www.hobbytronics.co.uk/arduino-xloader you can upload it onto the Arduino (assuming you've already got the drivers, for Windows you can download it from  http://arduino.cc/en/guide/windows#toc4).

Programming the USB controller

Somewhat complicated, and I recommend doing this when building the electronics is mostly done, to let us check that the central unit's programming is already done correctly. We'll use HIDUINIO: https://github.com/ddiakopoulos/hiduino/blob/master/Compiled%20Firmwares/HIDUINO_MIDI.hex
For details see: http://bartruffle.blogspot.hu/2013/09/dfu-programming-atmega16u2-on-arduino.html

Circuit

I'm not going to show you a big schematic here, but instead a breadboard view for 8 keys. For 32 keys it is straightforward to expand.
Not the most beautiful drawing, the point is to show every connection points. Indeed, this is a very simple circuit, just having quite a lot of wires. In real life you don't need so much place (as you can get the resistors standing e.g.), you should not need more than 2 big or 4 small breadboards.

You can see the following in the picture:
- CD4021 IC, having 16 pins. 8 pins are connected to the pedal notes themselves, the purple wires show that going to the terminal then to the notes (the foils) themselves.
- Upper left pin (no. 16) goes to 5V input (+), a lower right (8) goes to the ground (-)
- The IC pins assigned as the following:
  1. Highest note (G, on 2nd IC D#, on 3rd B, on the 4th G again)
  2. not connected
  3. Goes back to the Arduino - lowest notes to pin 7, then 6, 5 and 4 respectively.
  4. Lowest note (C)
  5. C#
  6. D
  7. D#
  8. Ground
  9. Control signal from Arduino pin 8
  10. Clock signal from Arduino pin 9
  11. Ground
  12. not connected
  13. E
  14. F
  15. F# 
- Resistors: every IC pin connected to a note must also be connected to its own 680kOhm resistor and then through the resistor to Arduino pin 10.
- Variable resistor (aka potentiometer): 3 pins, side pins go to 5V and ground, middle pin goes to A0 of Arduino. This resistor will set the sensitivity of the capacitive sensors.
- Arduino 5V, GND etc. is connected according to the picture
- While you have only one CD4021, testing the first 8 notes, the inactive inputs, pins 6,5 and 4 on Arduino should be connected to the high signal level, ie. 5V

When everything is connected we can power up the Arduino using the USB cable from the computer. The computer should be connected to the wall socket (to provide some consistent grounding, otherwise there could be problems with sensitivity).

After some blinking the "ON" LED should light up on Arduino, but the L LED should not.
If everything is correct by this time, we can try the electronics with some metal (a piece of wire, a knife etc.) - touch the terminals and the L LED should light up while touching. (Make sure your body, your skin is connected to the terminal via the wire, as you body will act as the capacitor.)


Soldered on a breadboard.


Testing MIDI output


When also the USB programming is done, our computer should recognize the electronics as "HIDUINO". Starting Hauptwerk you should be able to make real sound using by touching the terminals.
The hard part is done, now let's do the "paperwork". 

The physical pedalboard

Pedalboard template

I've created a template that you can print on simple A4/letter papers. Then you just print it glue it with duct tape and can just glue the aluminium foil strips.  HERE you can download it. Two white pedals should be 63.5 mm (2.5 inches) from each other (measure at the bottom of the black keys).



My original pedalboard was linear, not curved, but you can do whatever you like. I think because of playing without shoes and just touching, not pressing, the radial pedalboard template is more practical.
You don't have to be very very very precise, your feet will be quite big relative to the pedal size, and also every pedalboards differ a bit in size anyway.

Keys (pedals)

Unfortunately aluminium foil tears easily, but hard to cut with scissors, my recommendation is to cut a sized paper template, draw the border line on the aluminium foil, and then you can easily fold and cut it. You'll need 19 pieces of long and 13 pieces of short keys.

During preparation. In the middle of the picture the key template and the cutting appliance.

Pedalboard base

2 more layers needed, the first is a polyfoam layer which will make the paper more stable and give some sense of pressure.

Wiring the keys 

Take appropriate length of wires, solder onto the alligator clips, and connect them to the respective notes - white notes will have the clip at the bottom, black notes at the top. Lead the wires under the polyfoam. (Don't lead neighboring wires very close to each other, otherwise they will sound together in some cases).

Grounding

To make the electronics work really stable, under the polyfoam or under yourself (that is you should sit on it) take a big aluminium foil plane and connect it to the GND of the Arduino.



After this you can start playing, given you can sit comfortably. A little help for this: 

Extra: organ bench 

Just for some inspiration:


The respective Sketchup model can be downloaded here, you can see the measurements there. This bench is special, because you can change the bench height. 

When you're ready, you can have something like this (or something much more beautiful):

The 1st keyboard is a 25 years old Yamaha, that's why it's yellowish.

If you create this, and want to discuss, just comment!

Extra 2: MIDI electronics for a normal pedalboard

The same electronics and microcontroller software can be used for normal MIDI pedalboard electronics as well. Just use switches that connect CD4021 to the ground at the note pins. Parallel to the switch you need a 10kOhm pullup resistor (connecting to 5V). Pushing the switch will push the note's voltage to 0 (ground) and that will mean the pushed state.

Source code of pedal program:


#include <MIDI.h>
#include "pitches.h"
#include <wiring_digital.c>

#define _DEBUG 0

/** The time to wait after putting a LOW level on the input lines. In us. */
const int SIGNAL_CHANGE_DELAY = 500;

/** the level of the shift registers normally, when there is no test signal, no input etc. */
int clearLevel = LOW;

/** the level of the test signal - we are waiting for this to appear on the shift registers. */
int testSignalLevel = 1-clearLevel;

const byte LED = 13;
const byte BUZZER = 12;

/** This is the signal which is input to the shift register P pins through a resistor and a capacitor. */
const byte TEST_SIGNAL_OUT = 10;

volatile uint8_t *testSignalOutReg;
uint8_t testSignalOutBitMask;

/** Connected to pin 10 of the shift registers. */
const byte SHIFT_CLOCK = 9;

/** Connected to pin 9 of the shift registers. */
const byte SHIFT_CONTROL = 8;

/** MIDI Output pin */
const byte TX = 1;

const byte THRESHOLD_SETTING = A0;

/** Number of shift registers */
const byte nOfRegs = 4;

/** These are the inputs where the shift registers writes the values serially. 
 These should be connected to Q8 of the shift registers. */
byte fromShiftReg[] = { 
  7, 6, 5, 4 };

byte incoming[nOfRegs];

int noOfSamples = 100;
int maxWait = 1;

const int DEFAULT_THRESHOLD = 0;
int capacityThreshold = DEFAULT_THRESHOLD;


/** The frequencies of sounds played on the buzzer when pressed the keys. */
int freqs[] = {
  NOTE_C2, NOTE_CS2, NOTE_D2, NOTE_DS2, NOTE_E2, NOTE_F2, NOTE_FS2, NOTE_G2, 
  NOTE_GS2, NOTE_A2, NOTE_AS2, NOTE_B2, NOTE_C3, NOTE_CS3, NOTE_D3, NOTE_DS3,
  NOTE_E3, NOTE_F3, NOTE_FS3, NOTE_G3, NOTE_GS3, NOTE_A3, NOTE_AS3, NOTE_B3,
  NOTE_C4, NOTE_CS4, NOTE_D4, NOTE_DS4, NOTE_E4, NOTE_F4, NOTE_FS4, NOTE_G4 
};

const byte lowestMidiNote = 36;
byte velocity = 127;
byte midiChannel = 1;

/** This array stores which keys are pressed. The value corresponds to the capacity measured at the given key. */
int keys[8 * nOfRegs];
boolean soundingNotes[8 * nOfRegs];

void initMidi() {
  MIDI.begin();
}

void initDebug() {
  Serial.begin(9600);
}

void initPins() {
  for (int i = 0; i < nOfRegs; i++) {
    pinMode(fromShiftReg[i], INPUT);
    uint8_t timer = digitalPinToTimer(fromShiftReg[i]);
    if (timer != NOT_ON_TIMER) turnOffPWM(timer);

  }
  pinMode(TEST_SIGNAL_OUT, OUTPUT);
  pinMode(SHIFT_CLOCK, OUTPUT);
  pinMode(SHIFT_CONTROL, OUTPUT);
  pinMode(BUZZER, OUTPUT);  
  pinMode(THRESHOLD_SETTING, INPUT);
  pinMode(LED, OUTPUT);
  pinMode(TX, OUTPUT);

}

void setup() {
#if _DEBUG
  initDebug();
#else
  initMidi();
#endif
  initPins();
  digitalWrite(LED, LOW);
}

void dw(int pin, int val) {
  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);
  volatile uint8_t *out = portOutputRegister(port);
uint8_t oldSREG = SREG;
  
  cli();
  if (val == LOW) {
    *out &= ~bit;
  } else {
    *out |= bit;
  }
SREG = oldSREG;
}

int dr(uint8_t pin) {
  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);
  if (*portInputRegister(port) & bit) return HIGH;
  return LOW;
}

void loadShiftRegisters(int level) {
  dw(TEST_SIGNAL_OUT, level);  
  dw(SHIFT_CONTROL, HIGH);  
}

void zeroKeyCapacities() {
  for (int i = 0; i < sizeof(keys)/sizeof(int); i++) {
    keys[i] = 0;
  }  
}

void parallelShiftIn() {
  for (int reg = 0; reg < nOfRegs; reg++) {
    incoming[reg] = 0;    
  }
  for (int i = 0; i < 8; ++i) {
    dw(SHIFT_CLOCK, HIGH);
    for (int reg = 0; reg < nOfRegs; reg++) {
      incoming[reg] |= dr(fromShiftReg[reg]) << i;
    }
    dw(SHIFT_CLOCK, LOW);
  }

}

void measureTime() {
  int total = 0;
  while (total < maxWait) {
    dw(SHIFT_CONTROL, HIGH); // try to jam in the test signal
    dw(SHIFT_CLOCK, HIGH);    
    dw(SHIFT_CONTROL, LOW); // it seems that with this P8 is already at Q8, so clock must be already high at this point

    parallelShiftIn();
    // at this point incoming contains the values from the shift registers
    // if one value is still at the clear level, we increase the corresponding "key" count
    for (byte reg = 0; reg < nOfRegs; reg++) {
      for (byte i = 0; i < 8; i++) {
        if ((incoming[reg] & (1 << i)) == clearLevel) {
          keys[8 * reg + i] ++;
        }
      }
    }
    total ++;
  }


}

void doMidiNotes() {
  boolean hasNote = false;
  for (int i = 0; i<sizeof(keys)/sizeof(int); i++) {
    int note = lowestMidiNote + i;
    if (keys[i] > capacityThreshold) {
      #if _DEBUG
        Serial.println(String("Capacity of note ")+i+": "+keys[i]);
      #endif
      if (!soundingNotes[i]) {
        soundingNotes[i] = true;
      #if !_DEBUG
          MIDI.sendNoteOn(note, velocity, midiChannel);
      #else
          Serial.print(0b1000, HEX);
          Serial.print(midiChannel, HEX);          
          Serial.print(note, HEX);
          
          tone(BUZZER, freqs[note-lowestMidiNote]);                  
      #endif        
      }
        hasNote = true;
    } 
    else {
      if (soundingNotes[i]) {
      // todo might need to filter fast note off after a note on, e.g. by checking the time of the last note on
        #if !_DEBUG
          // for compatibility with Ebay-cheap MIDI-USB gear send note on with zero velocity
          MIDI.sendNoteOn(note, 0, midiChannel);
        #else  
          Serial.print("NoteOff ");
          Serial.println(note, DEC);        
        #endif
        soundingNotes[i] = false;
      }
    }
  }
  if (hasNote) {
    dw(LED, HIGH);
  } else {
        #if _DEBUG
    
    noTone(BUZZER);
      #endif
    dw(LED, LOW);
  }
}

void updateThresholdSetting() {
  int newValue = constrain(map(analogRead(THRESHOLD_SETTING), 100, 1023, 0, 100), 0, 100);
  
  #if _DEBUG
    if (newValue != capacityThreshold) {
      Serial.print("new capacity threshold: ");
      Serial.println(newValue, DEC);
    }
  #endif
  capacityThreshold = newValue;
  
}

void loop() {
  zeroKeyCapacities();
  updateThresholdSetting();
  for (byte sample = 0; sample < noOfSamples; sample++) {
    // clear the shift registers
    loadShiftRegisters(clearLevel);
    delayMicroseconds(SIGNAL_CHANGE_DELAY);
    // try to jam the test signal level in the shift registers
    loadShiftRegisters(testSignalLevel);
    measureTime();
  }
  doMidiNotes();

}

pitches.h



/*************************************************
 * Public Constants
 *************************************************/

#define NOTE_B0  31
#define NOTE_C1  33
#define NOTE_CS1 35
#define NOTE_D1  37
#define NOTE_DS1 39
#define NOTE_E1  41
#define NOTE_F1  44
#define NOTE_FS1 46
#define NOTE_G1  49
#define NOTE_GS1 52
#define NOTE_A1  55
#define NOTE_AS1 58
#define NOTE_B1  62
#define NOTE_C2  65
#define NOTE_CS2 69
#define NOTE_D2  73
#define NOTE_DS2 78
#define NOTE_E2  82
#define NOTE_F2  87
#define NOTE_FS2 93
#define NOTE_G2  98
#define NOTE_GS2 104
#define NOTE_A2  110
#define NOTE_AS2 117
#define NOTE_B2  123
#define NOTE_C3  131
#define NOTE_CS3 139
#define NOTE_D3  147
#define NOTE_DS3 156
#define NOTE_E3  165
#define NOTE_F3  175
#define NOTE_FS3 185
#define NOTE_G3  196
#define NOTE_GS3 208
#define NOTE_A3  220
#define NOTE_AS3 233
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294
#define NOTE_DS4 311
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_FS4 370
#define NOTE_G4  392
#define NOTE_GS4 415
#define NOTE_A4  440
#define NOTE_AS4 466
#define NOTE_B4  494
#define NOTE_C5  523
#define NOTE_CS5 554
#define NOTE_D5  587
#define NOTE_DS5 622
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_FS5 740
#define NOTE_G5  784
#define NOTE_GS5 831
#define NOTE_A5  880
#define NOTE_AS5 932
#define NOTE_B5  988
#define NOTE_C6  1047
#define NOTE_CS6 1109
#define NOTE_D6  1175
#define NOTE_DS6 1245
#define NOTE_E6  1319
#define NOTE_F6  1397
#define NOTE_FS6 1480
#define NOTE_G6  1568
#define NOTE_GS6 1661
#define NOTE_A6  1760
#define NOTE_AS6 1865
#define NOTE_B6  1976
#define NOTE_C7  2093
#define NOTE_CS7 2217
#define NOTE_D7  2349
#define NOTE_DS7 2489
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_FS7 2960
#define NOTE_G7  3136
#define NOTE_GS7 3322
#define NOTE_A7  3520
#define NOTE_AS7 3729
#define NOTE_B7  3951
#define NOTE_C8  4186
#define NOTE_CS8 4435
#define NOTE_D8  4699
#define NOTE_DS8 4978

(c) Bertalan Fodor, 2014, All rights reserved