Arduino Keyboard polyphony help

Ok so I have a broken toy keyboard that I am using its key matrix for a project. the keyboard is 37 keys, 5x8 matrix. I am using the keypad library and some example code that has been modified to do produce some sort of sound when I press a key. all the notes are correct and such, but here is the problem.

If I hold one key down, and then press and hold another, then let go of the second keypress, they both stop. I would like it to be so the first key starts again when I drop the second key. another thing id like to implement is 5 key polyphony (a little overkill I know, but why not) which means I would maybe need to have 5 different output pins on the UNO, which I just have space for. if I did this, I would probably create an external mixer circuit to mix them all into one voice, which i could do easily.

#include <Keypad.h>

const byte ROWS = 5;
const byte COLS = 8;

char keys[ROWS][COLS] = {
    {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'},
    {'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'},
    {'q', 'r', 's', 't', 'u', 'v', 'w', 'x'},
    {'y', 'z', '0', '1', '2', '3', '4', '5'},
    {'6', '7', '8', '9', '+', '&', '@', '='},
};

byte rowPins[ROWS] = {A1, A2, A3, A4, A5};     //connect to the row pinouts of the kpd
byte colPins[COLS] = {2, 3, 4, 5, 6, 7, 8, 9}; //connect to the column pinouts of the kpd

Keypad kpd = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

unsigned long loopCount;
unsigned long startTime;
String msg;

void setup()
{
    Serial.begin(9600);
    loopCount = 0;
    startTime = millis();
    msg = "";
}

void loop()
{
    loopCount++;
    if ((millis() - startTime) > 5000)
    {
        //Serial.print("Average loops per second = ");
        // Serial.println(loopCount/5);
        startTime = millis();
        loopCount = 0;
    }

    // Fills kpd.key[ ] array with up-to 10 active keys.
    // Returns true if there are ANY active keys.
    if (kpd.getKeys())
    {

        for (int i = 0; i < LIST_MAX; i++)
        { // Scan the whole key list.

            if (kpd.key[i].stateChanged)
            { // Only find keys that have changed state.
                float note;
                switch (kpd.key[i].kstate)
                { // Report active key state : IDLE, PRESSED, HOLD, or RELEASED
                
                case PRESSED:
                    msg = " PRESSED.";

                  switch(kpd.key[i].kchar) {
                    case 'a':
                        note = 65.41;
                        break;

                    case 'b':
                        note = 69.30;
                        break;

                    case 'c':
                        note = 73.42;
                        break;

                    case 'd':
                        note = 77.78;
                        break;

                    case 'e':
                        note = 82.41;
                        break;

                    case 'f':
                        note = 87.31;
                        break;

                    case 'g':
                        note = 92.50;
                        break;

                    case 'h':
                        note = 98.00;
                        break;

                    case 'i':
                        note = 103.83;
                        break;

                    case 'j':
                        note = 110.00;
                        break;

                    case 'k':
                        note = 116.54;
                        break;

                    case 'l':
                        note = 123.47;
                        break;

                    case 'm':
                        note = 130.81;
                        break;

                    case 'n':
                        note = 138.59;
                        break;

                    case 'o':
                        note = 146.83;
                        break;

                    case 'p':
                        note = 155.56;
                        break;

                    case 'q':
                        note = 164.81;
                        break;

                    case 'r':
                        note = 174.61;
                        break;

                    case 's':
                        note = 185.00;
                        break;

                    case 't':
                        note = 196.00;
                        break;

                    case 'u':
                        note = 207.65;
                        break;

                    case 'v':
                        note = 220.00;
                        break;

                    case 'w':
                        note = 233.08;
                        break;

                    case 'x':
                        note = 246.94;
                        break;

                    case 'y':
                        note = 261.63;
                        break;

                    case 'z':
                        note = 277.18;
                        break;

                    case '0':
                        note = 293.66;
                        break;

                    case '1':
                        note = 311.13;
                        break;

                    case '2':
                        note = 329.63;
                        break;

                    case '3':
                        note = 349.23;
                        break;

                    case '4':
                        note = 369.99;
                        break;

                    case '5':
                        note = 392.00;
                        break;

                    case '6':
                        note = 415.30;
                        break;

                    case '7':
                        note = 440.00;
                        break;

                    case '8':
                        note = 466.16;
                        break;

                    case '9':
                        note = 493.88;
                        break;

                    case '+':
                        note = 523.25;
                        break;
                    }
                    
                    tone(12, note);
                    break;

                case RELEASED:
                    msg = " RELEASED.";

                    noTone(12);
                    break;
                    ;
                }

                Serial.print("Key ");
                Serial.print(kpd.key[i].kchar);
                Serial.println(msg);
            }
        }
    }
}

I need something like this ⇓ to go in place of the crazy switch statement with 37 cases lol

if(aKey == pressed) {
  if(anotherKey == pressed) {
    playTheCorrespondingNote(12); // on pin 12
  } else {
    playTheCorrespondingNote(12); // probably use tone()
  }
}
/* then vary the output pins from 9-13 in sequence */

thanks for the help in advance.

PD

Use the value returned by the keypad as an index to an array of values after adjusting its value into the range 0 to 36

Here's a project I did for 13 tones at once. Scale it down as needed for just 5, and reading a keypad vs discrete buttons.

@UKHeliBob
Put simply, i need help with the syntax. how would make what you said go in my code?

kpd.keys[i].kchar? as an index to loop through? would this still be able to do 5 key polyphony?

@CrossRoads

this is code for a 1248p, im using an uno, what are the in and output pins? not able to make much from the schematic in the code file

Thanks :woozy_face:

I did everything as arrays:

byte keyArray[]={
  2,3,30,8,9,31,4,5,6,7,10,11,12,13,}; //Ports D2,D3,D4,D5,D6,D7,B0,B1,B2,B3,B4,B5,B6, added b7 - notes 48, 47,46,45,44,43,42,41,40,39,38,37,36
byte outputArray[] = {
  14,15,16,17,18,19,22,23,24,25,26,27,28, 21,22,29}; // Ports A0,A1,A2,A3,A4,A5,C0,C1,C2,C3,C4,C5,C6, added a6, a7, c7

If you want to use an Uno with 5 outputs and use Keypad.h to determine the key(s) that are pressed instead of discrete pins, shouldn't be difficult to swap that in.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.