Skip to main content

Key Matrix

Wiring a CDU, FMC or GPS keypad as a row-and-column key matrix on an ESP32, with diodes against ghosting, so 60 keys need only 16 pins.

Why a Matrix?

A CDU or FMC keypad has 40–70 keys. Wired one pin per key that is more pins than any ESP32 has. A key matrix puts the keys at the crossings of row and column wires: each key connects one row to one column. Scanning the rows one at a time tells which keys are closed, so a matrix of R rows and C columns reads R × C keys from R + C pins.

KeypadMatrixKeysPins
Phone-style keypad4 × 3127
GPS / radio keypad4 × 62410
737 CDU6 × 106016
Largest matrix10 × 1010020
Wiring
GPIO 13 R0 GPIO 14 R1 GPIO 27 R2 C0 GPIO 32 C1 GPIO 33 C2 GPIO 25 R0 C0 R0 C1 R0 C2 R1 C1 R2 C1 Rows: driven LOW one at a time Columns: INPUT_PULLUP LOW = key closed Box = key + 1N4148 (cathode to row)

The rows are driven : the ESP32 pulls one row LOW at a time, so row pins must be output-capable (not the input-only GPIO 34–39). The columns are read with the internal pull-up enabled; a column reads LOW while a key on the selected row is closed. A matrix has 2–10 rows and 2–10 columns.

LineConnect toColour
Row 0…nOne output-capable GPIO per rowOrange
Column 0…n One GPIO per column with an internal pull-up (not the input-only GPIO 34–39, which have none) Green
Each keyBetween its row and its column, through a 1N4148 diode (cathode to row)Yellow
Ghosting and Diodes
R0 R1 C0 C1 ● held ○ ghost

Without diodes, holding three keys at the corners of a rectangle closes a path through them, and the fourth corner reads as pressed even though nobody touched it. This ghost key is indistinguishable from a real press.

A 1N4148 diode in series with every key blocks the reverse path, so every key is read independently, however many are held. On a hand-wired keypad solder the diode straight onto the key's leg, cathode (the band) towards the row.

MatrixSeveral keys at onceUse when
With diodesEvery key reported independentlyHand-wired panels; keys that are held while another is pressed
Without diodesKeys in an ambiguous rectangle are held at their last stateReady-made membrane keypads, pressed one key at a time
Arduino Code — Scanning

Select each row in turn by pulling it LOW, read every column, then release the row. Compare with the previous scan to report presses and releases.

// 3 × 3 key matrix scan — rows driven, columns read with pull-ups
const int ROW_PINS[] = { 13, 14, 27 };
const int COL_PINS[] = { 32, 33, 25 };
const int ROWS = 3;
const int COLS = 3;

bool keyState[ROWS][COLS];

void setup() {
    Serial.begin(115200);
    for (int r = 0; r < ROWS; r++) {
        pinMode(ROW_PINS[r], OUTPUT);
        digitalWrite(ROW_PINS[r], HIGH);         // idle rows HIGH
    }
    for (int c = 0; c < COLS; c++) {
        pinMode(COL_PINS[c], INPUT_PULLUP);
    }
}

void loop() {
    for (int r = 0; r < ROWS; r++) {
        digitalWrite(ROW_PINS[r], LOW);          // select one row
        delayMicroseconds(5);                    // let the lines settle
        for (int c = 0; c < COLS; c++) {
            bool pressed = digitalRead(COL_PINS[c]) == LOW;
            if (pressed != keyState[r][c]) {
                keyState[r][c] = pressed;
                Serial.printf("R%d C%d %s\n", r, c, pressed ? "pressed" : "released");
            }
        }
        digitalWrite(ROW_PINS[r], HIGH);         // deselect
    }
    delay(5);                                    // ~200 scans a second; add debounce for real panels
}

On a CockpitConnect controller you don't write this. Add a Key Matrix to the controller in the Flow Builder with its row and column pins and whether the keys have diodes; the first row pin names the matrix. Every key is then an ordinary Button on the matrix, shown as "R2 C3", with debounce, long-press gestures and its own Mappings. "Add all keys" places a Button node for every crossing at once. Without diodes the controller never reports a key it can't be sure of: keys in an ambiguous rectangle stay at their last state until the rectangle breaks.

Cockpit Applications
ApplicationMatrixNotes
737 CDU / Airbus MCDU6 × 10 or 7 × 10Diodes recommended; CLR is often held, so a long press clears the scratchpad
GPS keypad (GNS 430/530, G1000)4 × 6Soft keys and FMS buttons; encoders stay on their own pins
Radio / transponder keypad4 × 3Ready-made membrane keypad works, one key at a time
Overhead push-button rowsUp to 10 × 10Fewer wires through the panel; one harness per row