Project “MIDI ing up a Grand Piano” part 1

This is the start of a new project. I have always wanted to get a standard MIDI output from playing my acoustic Grand Piano. I hate playing an electronic piano and much prefer the touch and sound of the real thing. It is my primary composing tool and I would like to just to be able to record every time I play it so that I never miss that “lost chord”.

There are systems out there to do this and I have seen an open source project, but they are expensive. I want to produce a reliable system that is cheap to build.

Many years ago, I built an electronic piano from a kit. This had a standard spring loaded organ keyboard. Each key had a “plunger” that was used to operate an electric switch. The switches were created by soldering a gold plated springy wire to a PCB and arranging the plunger to move it between two parallel gold plated bus bars. There was some electronics that measured the discharge of a capacitor as the wire moved from the upper bus bar to the lower bus bar. The voltage pulse generated was related to the key velocity and so the piano was able to implement touch sensitivity. (each key circuit utilised a signal diode and I got the polarity wrong and soldered 76 of them into position. I then had to unsolder each one, turn it around and re-solder it. Oh happy days !)

I took this basic system and adapted it to a microcontroller. The two bus bars were connected to two output pins and the switch wire was connected to an input pin. The micro controller alternately switched the bus bars from low to high and so was able to determine whether the switch wire was touching a bus bar. The micro controller started a timer when the switch wire left the upper bus bar and stopped the timer when it touched the lower busbar. The micro controller was able to determine the key velocity from the timing and generated a pair of MIDI key on and key off commands.

I proved the concept using a PIC 16F628 micro controller. Each PIC could handle up to 12 keys. I planned to daisy chain 7 PICs to handle a full keyboard.

I had thought of using this type of system to MIDI up my Grand Piano, however there is the problem of getting the piano action mechanics to operate the switches. The switches themselves do not take much force to operate them, so they would not really affect the touch. I may use this concept to make a MIDI keyboard controller from an old scrap piano.

The alternative is to use some sort of opto sensing of the key operation, either digital or analog. For instance an analog system would observe the piano hammer distance by observing the amount of reflected light. A digital system would observe the key interrupting a light beam at two points and calculate the velocity using the interrupt time.

I am going with the digital system for my project. My first stab is to link up some opto components to my favourite PIC and do some experimentation.

I bought 2 Infra-Red LEDS (TSUS5400 940nm 5mm infrared emitter) costing 20p each, an Infra-Red photo transistor (LL-304PTC4B-1AD 3mm IR Detector 940nm) costing 31p and linked them up to a PIC 16F628 micro controller. The prototype was built on bread board as shown ….

 

 

The two IR LEDs are connected to pins A2 and A3. When these pins go low, current flows through the LED making it emit infra red. The photo transistor collector is connected to the input pin B0. This is normally held high by the pull up resistor. When light is detected, the transistor conducts and pulls the collector low. This transition of high to low can be detected by the micro controller.

The PIC output at A1  is connected to pin 2 and the 0v line is connected to pin 5 of a 9 way D type socket. This is connected to my PC serial comms port which allows me to see debug information on a terminal running at 9600 baud rate.

 

 

The prototype shows the photo transistor in the centre with a IR LED either side. They are all pointing vertically upwards so that minimal light reaches the photo transistor. When a reflective surface (such as a screwdriver blade) is held above one of the LEDs, light is reflected from the LED to the photo transistor, causing it to conduct.

As the reflector is moved horizontally from left to right there are two detections from each LED. The micro controller can determine which LED is causing the detection because it continually switches each LED on and off in sequence. The test software determines the time between detections, converts it to text and prints it out at the computer terminal.

So when I “swipe the reflector, I get a number indicating how fast the swipe is.

The infra red light emitted by the LEDs can not be seen by the naked eye, however the camera in a smartphone is able to “see” infra red as shown by the following photographs. The first is with both LEDs off and the second one is with both LEDs on.

      

The next stage of my project is as follows :-

1) mount the components on some vero board.

2) take out the piano action and investigate a suitable place to put the sensor.

3) fix the sensor into position at say middle C and bring out some temporary leads.

4) connect up to a terminal and investigate the range of velocities detected.

 

I wrote the test program using MikroElectronika PASCAL. I took advantage of its software library to output data to the RS232 PC Comms port. The program initially flashes the LEDs as a test which I can see using the smartphone camera, it then outputs the program version string and goes into the detection loop.

program MicroRtu;

{ Declarations section }
var
count : integer;
onState : boolean;
byte_read : byte;
error : byte;

procedure displayCount( p_count : integer );
var
dg : byte;
i : integer;
digits : array [0..5] of byte;
begin

if p_count > 0 then
begin
for i := 0 to 5 do digits[i] := '0';

i := 0;
while p_count > 0 do
begin
dg := p_count mod 10;
digits[i] := dg + '0';
inc(i);
p_count := p_count div 10;
end;

for i := 5 downto 0 do
Soft_UART_Write(digits[i]);

Soft_UART_Write(13);
Soft_UART_Write(10);
end;
end;

begin
{ Main program }
TRISA := $FF; //isolate
TRISB := $FF; // usart pins must be inputs exept B4
CMCON := $07; // disable comparators


//outputs A2..A3 connected to IR LEDs
TRISA := $F3;

PORTA := 0; //turn on LEDS
Delay_ms(1000);
PORTA := $FF; //turn off LEDS
Delay_ms(1000);
PORTA := 0; //turn on LEDS
Delay_ms(1000);
PORTA := $FF; //turn off LEDS

Soft_UART_Init(PORTA,0,1,9600,true);
Soft_UART_Write('O');
Soft_UART_Write('p');
Soft_UART_Write('t');
Soft_UART_Write('o');
Soft_UART_Write(' ');
Soft_UART_Write('1');
Soft_UART_Write('.');
Soft_UART_Write('0');
Soft_UART_Write(13);
Soft_UART_Write(10);

count := 0;
onState := false;
while true do
begin

// set IR led 1 ON led 2 off
ClearBit (PORTA, 2) ;
SetBit (PORTA, 3);
Delay_us(200);

// check sensor
if TestBit (PORTB, 0) = 0 then
begin
if not onState then
begin
count := 0;
onState := true;
end;
end;

// set IR led 2 ON led 1 off
ClearBit (PORTA, 3);
SetBit (PORTA, 2);
Delay_us(200);

// check sensor
if TestBit (PORTB, 0) = 0 then
begin
if onState then
DisplayCount(count);
onState := false;
end;

inc(count);
end;

end.

Leave a Reply