Help programming an Arduino to work with a matrixed organ keyboard

I am trying to program my Arduino Mega to work as a Midi controller.

For Background, I have a digital Allen 225 RTC organ, that is in good working condition, but I wanted to add Midi. It has a 6x11 matrix encoding each keyboard (there are 2) and the pedalboard. With test sketches, I have figured out that the Allen pulls the columns low 4 times in 40 microseconds, then waits about 600 microseconds, then pulls the columns low again. If the key is pressed down when the column goes low, then the row goes low at the same time.

I will work on a schematic, but what I did is wire one pin of an Arduino Mega to each row or column of each keyboard and pedal. That means, there is a direct electrical connection from the keyboard row to the Arduino "row" pin, and from the keyboard column to the Arduino "column" pin.

In the below code, Pin2 is soldered to the wire from the first row of keyboard A, and Pin32 is soldered to the first column of keyboard A.

I have run some test sketches, which is how I know roughly how long between and how many times the Allen columns go low.

I have gotten it to work so that keys are recognized as on or off, and the appropriate midi message is sent, however I continuously get on/off/on/off... messages when I hold down the key (that stop when I let go of the key).

I have tried all manner of different ways of programming it, and I can't come up with what I am doing wrong.

The Allen circuits are undocumented, but they seem to be readable when you run a test sketch.

Any help would be appreciated!

// Name: Arduino Mega Midi Controller v16
// Created: Dec 23, 2020. 
// Author: Larason2

byte Pin2;
byte Pin32;

byte lastA[11][6];
byte lastB[11][6];
byte lastC[7][6];

const int noteOn1 = 144;
const int noteOff1 = 128;
const int velocity = 100;

void setup() {
  // Start Serial
  Serial.begin(31250);
  
  pinMode(2, INPUT);
  pinMode(32, INPUT);
}

void loop() {

  pinMode(2, INPUT_PULLUP);
  Pin2 = digitalRead(2);
  pinMode(2, INPUT);

  pinMode(32, INPUT_PULLUP);
  Pin32 = digitalRead(32);
  pinMode(32, INPUT);

  if((Pin32 == 0) and (Pin2 == 0) and (lastA[0][0] == 0)) {
    MidiSend(noteOn1, 36, velocity);
    lastA[0][0] = 1;
  }
  if((Pin32 == 0) and (Pin2 == 1) and (lastA[0][0] == 1)) {
    MidiSend(noteOff1, 36, velocity);
    lastA[0][0] = 0;
  }
}

void MidiSend(int cmd, int note, int vel) {
  Serial.write(cmd);
  Serial.write(note);
  Serial.write(vel);
}

in my code for scanning a keypad, the column pins are configured as inputs and the column pins are sequentially made LOW to pull the inputs low. when a row input is recognized as LOW, the corresponding column output is restored to HIGH.

i realize you you need to scan all your keys. i don't see where you pull either a row/column LOW

int
keyscan (
    byte*   row,
    byte*   col )
{
    for (unsigned int r = 0; r < _kpRowSize; r++)
    {
        digitalWrite (_kpRows [r], LOW);

        for (unsigned int c = 0; c < _kpColSize; c++)
        {
            if (! digitalRead (_kpCols [c]))
            {
                digitalWrite (_kpRows [r], HIGH);

                *row = r;
                *col = c;

#if DEBUG
                Serial.print ("keyscan: ");
                Serial.print (r);
                Serial.print (", ");
                Serial.println (c);
#endif

                int  res = (r << 4) | c;
                return res;
            }
        }

        digitalWrite (_kpRows [r], HIGH);
    }

    return NO_KEY;
}

Hi,
Welcome to the forum.
Sorry but I had to spread it out.

I am trying to program my Arduino Mega to work as a Midi controller.
I have an Allen organ that I soldered all of the keyboard connections to pins on the Arduino.
The Allen is a digital organ, and has a matrix arrangement for each keyboard that is 6 rows x 11 columns.
In the below code, Pin2 is soldered to a row, and Pin32 is soldered to a column.
I have run some test sketches, that show that when a key is pressed down, you get rows and columns going low at the same time, but usually only for one scan, with at least 10 microseconds between the columns going low.
I have gotten it to work so that keys are recognized as on or off, and the appropriate midi message is sent, however I continuously get on/off/on/off... messages when I hold down the key (that stop when I let go of the key).
I have tried all manner of different ways of programming it, and I can't come up with what I am doing wrong.
The Allen circuits are undocumented, but they seem to be readable when you run a test sketch.
Any help would be appreciated!

Thanks.. Tom.. :slight_smile:

Thanks to both of you for your input. Sorry Tom for the bad formatting, it was late at night and I was tired after trying for the past week to get the code to work! I will try to put more line breaks... I also edited what I posted to make it more clear.

Thanks gcjr. There is no need to have my Arduino code go low, since the organ's own circuits cause the columns to go low. What I'm basically trying to do is sense what state the existing circuits are in using the pins on the Arduino. I'll post my test sketch:

byte OutputA;
byte OutputB;
int Timer = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(2, INPUT_PULLUP);
  pinMode(32, INPUT_PULLUP);

  for(int x=0; x<1000; x++) {
  Timer = x;
  OutputA = digitalRead(2);
  OutputB = digitalRead(32);
  Serial.print("A:");
  Serial.print(OutputA);
  Serial.print(", ");
  Serial.print("B:");
  Serial.print(OutputB);
  Serial.print(", ");
  Serial.print('\n');
  }
}

void loop() {
  // put your main code here, to run repeatedly:
}

When I run this sketch, I get an output similar to this if the key is not held down (abbreviated for time, also, there are more one's between the zero's):

A:1, B:1,
A:1, B:1,
A:1, B:0,
A:1, B:1,
A:1, B:1,
A:1, B:0,
A:1, B:1,
A:1, B:1,

And when the key is held down, I get this:

A:1, B:1,
A:1, B:1,
A:0, B:0,
A:1, B:1,
A:1, B:1,
A:0, B:0,
A:1, B:1,
A:1, B:1,

When I run the sketch, I also get the odd 1 or 0 where it is not supposed to be, which I suppose is noise in the pins.

Hopefully this makes sense. I think the problem is that even though the majority of returns are A:0, B:0, when the key is held down, sometimes there is an A:1, B:0, even when the key is held down, which causes the note to retrigger. I have tried the following solution:

// Name: Arduino Mega Midi Controller v16
// Created: Dec 23, 2020. 
// Modified: Dec 24, 2020.
// Author: Larason2

byte Pin2;
byte Pin32;

byte lastA[11][6];
byte lastB[11][6];
byte lastC[7][6];

const int noteOn1 = 144;
const int noteOff1 = 128;
const int velocity = 100;

int timer = 0;
int count = 0;

void setup() {
  // Start Serial
  Serial.begin(31250);
  
  pinMode(2, INPUT);
  pinMode(32, INPUT);
}

void loop() {

  pinMode(2, INPUT_PULLUP);
  Pin2 = digitalRead(2);
  pinMode(2, INPUT);

  pinMode(32, INPUT_PULLUP);
  Pin32 = digitalRead(32);
  pinMode(32, INPUT);

  if((Pin32 == 0) and (Pin2 == 0) and (lastA[0][0] == 0)) {
    MidiSend(noteOn1, 36, velocity);
    lastA[0][0] = 1;
  }
  if((Pin32 == 0) and (Pin2 == 0) and (lastA[0][0] == 1)) {
    timer++;
  }
  if((Pin32 == 0) and (Pin2 == 1) and (lastA[0][0] == 1)) {
    timer++;
    count++;
  }
  if((timer == 3) and (count >= 2)) {
    MidiSend(noteOff1, 36, velocity);
    timer = 0;
    count = 0;
    lastA[0][0] = 0;
  }
  if((timer == 4) and (count <= 1)) {
    timer = 0;
    count = 0;
  }

}

void MidiSend(int cmd, int note, int vel) {
  Serial.write(cmd);
  Serial.write(note);
  Serial.write(vel);
}

However, when I try this, when I push down the key, it registers the note on, but when I let go, the note doesn't trigger off. Furthermore, any further key press doesn't trigger the note on again, and I have to reset the Arduino to get a note on again. However, sometimes after a few minutes leaving the key in off, then the note triggers off. Any thoughts about what I'm doing wrong with this corrected code? Thanks!

I'll work on also putting together a schematic in case it helps.

Larason2:
I have figured out that the Allen pulls the columns low 4 times in 40 microseconds,

I can't figure out what this means. Do you mean each of four columns low for 10 microseconds in turn?!?

Larason2:
then waits about 600 microseconds, then pulls the columns low again.

Does this mean that each column is pulled low for 40 microseconds out of every 640 microseconds?

Larason2:
In the below code, Pin2 is soldered to the wire from the first row of keyboard A, and Pin32 is soldered to the first column of keyboard A.

I have gotten it to work so that keys are recognized as on or off, and the appropriate midi message is sent, however I continuously get on/off/on/off... messages when I hold down the key (that stop when I let go of the key).

My guess would be that the loop isn't fast enough to catch the leading edge of each column pulse and the row pulse might end before the row line is sampled. That could cause the key to read as 'released'.

Thanks John. Sorry, I wasn't sure how to describe what I saw. When I run the test sketch shown above, the columns read a long row of 1's, then you get a 0, then ten 1's, then a 0, then ten 1's, then a 0, then ten 1's, then a 0. After that, you get a long row of one's again, for at least 60 1's (not sure about the exact numbers). I would like to try to figure out the exact timing, but I don't have an oscilloscope, so the best I can do is try test sketches. If makes me think that there are about 10 microseconds between low pulses, and about 4 low pulses per column, but I'm not 100% sure, because I don't know how long the Arduino operations take to process. I have tried some benchmarking code, but I haven't been able to get it to work right, since I don't understand fully how benchmarking works yet.

I was thinking along the same lines, that maybe the "if()" operators I'm using are slowing down the code too much. Is there a way you can think that the code will still work without using "if()"?

Thanks again for your help!

can you explain what you mean by matrix?

Thanks gcjr. By "matrix," I meant the way the keyboard is wired. The allen keyboards are wired in a matrix configuration, with 6 rows, and 11 columns. The columns go low sequentially, then the IC reads the rows, and in this way you can read all the keyboard keys while minimizing the number of pins used on the Arduino.

I also just wanted to update you all on my progress. I finally just gave up and purchased a commercial board from Harrison Labs to do the same thing! I think John Wasser was very close in that my problem had something to do with the timing. The nail in the coffin was when I tried to add some resistors to the circuit so I could use the Allen sounds and MIDI at the same time, and I had a very difficult time getting it to work. This is definitely not my last Arduino project, however! I plan to use the Arduino Mega I have for another, simpler midi conversion. I'll post the results on the Organ Forum under the same Alias Larason2 under the pump organ section. Thanks again everyone!