Key Matrix

edited June 28 in Repetier-Firmware
I have been trying to add more buttons to my 3d printer (both RAMPS and RADDS) . I like to think I have a pretty good understanding of how to setup my uiconfig.h to get the LCDs working and I have been able to setup standard buttons and map them to UI_ACTIONS with success. I am definitely using FEATURE_CONTROLLER 1, and my LCD/SD are using the settings in there to work.

But it is never enough buttons, so I am trying a 4x4 matrix, starting on the RAMPS. Well first I tried it on just a MEGA 2560 using this tutorial to make sure my key matrix was understood and working:
using this 4x4 matrix

Once I go that working, this is what I did:

Aux4 and Aux3 are taken up by the LCD/SD connector
D11 is used by zprobe servo
XMIN is used for zprobe button
XMAX YMAX ZMAX are used for endstops

This leaves All of AUX1, AUX2 free
D6, D5, D4 in the servo area free
and YMIN and ZMIN are free

I am using the default  UI_MATRIX_ACTIONS in the sample uiconfig.h file 

first I tried using the digital pins in AUX2, but this not only doesn't use thekey matrix, but it kills the encoder wheel.
void uiInitKeys() {
//init -> UI_KEYS_INIT_MATRIX(r1,r2,r3,r4,c1,c2,c3,c4);

void uiCheckSlowKeys(uint16_t &action) {

When using the Keypad Tutorial ( I found that that if I used pin 13 for the 4th column, it didn't work but it worked when I used pin5. I'm not sure why, but I thought maybe using different pins might help so I tried:

but had no more success. I wanted to try the same pins free on RAMPS using the keypad tutorial but I don't see any pins over 53 on the Mega2560 so they must be doing something to the analog pins to use them....maybe this is "no bueno" for keypad?

I think I am either underconfiging something, or using the wrong pins.


  • From the code side it looks good. The way it works is by setting teh rows one by one to output and checking if one of the columns gets power. To be on the safe side I even added some resistors on the row lines. Anyway, what I want to say is how the keyboard has to function so it makes sense and can work. So please check if the combination of your rows and fucntion is really a mesh that connects row when pressed.
  • A simple test would be one switch with 1 row and 1 column for testing.
  • edited July 6
    I used the example in to make sure I had a working matrix and which were rows and columns and what their number was. So assuming the r1-4 and c1-4 in (r1,r2,r3,r4,c1,c2,c3,c4)  are for rows 1-4 and cols 1-4, I will have the correct pin numbers mapped to the correct pins on the key matrix.

    I don't have the resistors yet, but I have been careful to not push more than 1 pin at a time to avoid possible short.

    I will attempt to try a smaller  1 row 1 col matrix and see if that helps. 
  • Getting closer: 


    I get:
    exit status 1
    macro "UI_KEYS_INIT_MATRIX" requires 8 arguments, but only 2 given

    so I tried :

    and changed actions to:
                               UI_ACTION_IDENT05,   UI_ACTION_IDENT06,      UI_ACTION_IDENT07,        UI_ACTION_IDENT08,\
                               UI_ACTION_IDENT09,   UI_ACTION_IDENT10,  UI_ACTION_IDENT11,     UI_ACTION_IDENT12,\
                               UI_ACTION_IDENT13,   UI_ACTION_IDENT14,  UI_ACTION_IDENT15, UI_ACTION_IDENT16}

    const int matrixActions[] PROGMEM = UI_MATRIX_ACTIONS;

    made the proper mods to ui.cpp like:
               case UI_ACTION_IDENT16:
               Com::printFLN(PSTR("This is 16"));

    Some of the keys worked like this so I know I'm getting close, It looks like only lower numbers seem to work. I tried different combo of pins until this:


    Every key works now except R1C1 which should trigger UI_ACTION_IDENT01, I am not sure why. I tried switiching it to UI_ACTION_HOME_ALL but it didn't work.

    Why can't I use any of the pins in the AUX2 area?  with servo and zprobe, I am a pin short unless I can get AUX2 pins to work in matrix.

    Also, any idea's how only 1 button could be not working?
  • Any pin not assigned to any other function should do. Years ago I noticed that some pin numbers were wrong, not sure if that has been fixed.

    In ui.h you see how keys get queried:

    #define UI_KEYS_INIT_MATRIX(r1,r2,r3,r4,c1,c2,c3,c4) if(c1>=0){SET_INPUT(c1);WRITE(c1,HIGH);}if(c2>=0){SET_INPUT(c2);WRITE(c2,HIGH);}if(c3>=0){SET_INPUT(c3);WRITE(c3,HIGH);}\
      if(c4>=0) {SET_INPUT(c4);WRITE(c4,HIGH);}if(r1>=0)SET_OUTPUT(r1);if(r2>=0)SET_OUTPUT(r2);if(r3>=0)SET_OUTPUT(r3);if(r4>=0)SET_OUTPUT(r4);\
      if(r1>=0)WRITE(r1,LOW);if(r2>=0)WRITE(r2,LOW);if(r3>=0)WRITE(r3,LOW);if(r4>=0)WRITE(r4,LOW);#define UI_KEYS_MATRIX(r1,r2,r3,r4,c1,c2,c3,c4) {uint8_t r = (c1>=0?READ(c1):0) && (c2>=0?READ(c2):0) && (c3>=0?READ(c3):0) && (c4>=0?READ(c4):0);\
        if(!r) {\
          r = 255;\
          if(r1>=0) {\
            asm volatile ("nop\nnop\nnop\nnop\nnop");\
            if(!((c1>=0?READ(c1):1) && (c2>=0?READ(c2):1) && (c3>=0?READ(c3):1) && (c4>=0?READ(c4):1))) r = 0;\
            else WRITE(r1,HIGH);\
          if(r==255 && r2>=0) {\
            WRITE(r2,LOW);asm volatile ("nop\nnop\nnop\nnop\nnop");\
            if(!((c1>=0?READ(c1):1) && (c2>=0?READ(c2):1) && (c3>=0?READ(c3):1) && (c4>=0?READ(c4):1))) r = 4;\
            else WRITE(r2,HIGH);\
          if(r==255 && r3>=0) {\
            WRITE(r3,LOW);asm volatile ("nop\nnop\nnop\nnop\nnop");\
            if(!((c1>=0?READ(c1):0) && (c2>=0?READ(c2):1) && (c3>=0?READ(c3):1) && (c4>=0?READ(c4):1))) r = 8;\
            else WRITE(r3,HIGH);\
          if(r==255 && r4>=0) {\
            WRITE(r4,LOW);asm volatile ("nop\nnop\nnop\nnop\nnop");\
            if(!((c1>=0?READ(c1):1) && (c2>=0?READ(c2):1) && (c3>=0?READ(c3):1) && (c4>=0?READ(c4):1))) r = 12;\
            else WRITE(r4,HIGH);\
          if(c2>=0 && !READ(c2)) r+=1;\
          else if(c3>=0 && !READ(c3)) r+=2;\
          else if(c4>=0 && !READ(c4)) r+=3;\
          if(r<16) {action = pgm_read_word(&(matrixActions[r]));}\

    As you see a row or column pin id of -1 would disable that part so you can have any matrix up to 4x4.
    Columns are inputs with pullup and rows are outputs with outputs to gnd.
    First it gets tested if any button is pressed at all by querying columns. If a button is pressed gnd pulls at least one column to low, so if one of them is low the condition fails and keys get tested.

    Next we try to determine the row. All rows except the tested row get put high. So colums get high from pullup but the column with gnd will be low. Since all other are high having one low column means that is the row. We set r to 0/4/8/12 depending on row. If the line is not hit it is set high and we test next one.

    Now that we know the row, we test columns 2-4 of they are low and add 1-3 to r. So depending on combination we have r = 0..15.

    So since every row and column was detected at least in 3 cases it should also work for R1C1. For testing add a write command inside this condition
     if(r<16) {action = pgm_read_word(&(matrixActions[r]));}\
     if(r<16) {Com::printFLN(PSTR("key:"),(int)r);action = pgm_read_word(&(matrixActions[r]));}\
    that should write the detected id. You could also use it to write the assigned action instead if you put after action computation.

    One error I see is that first row should be

    #define UI_KEYS_MATRIX(r1,r2,r3,r4,c1,c2,c3,c4) {uint8_t r = (c1>=0?READ(c1):1) && (c2>=0?READ(c2):1) && (c3>=0?READ(c3):1) && (c4>=0?READ(c4):1);\

    but in your case with 4 columns it makes no difference.

  • I'm not sure I understood what you said exactly, but after much trial and error, this is what I found that works, using all available pins:

    D11 for servo
    X_MIN for zprobe button

    matrix pins, this part was very picky, as not all pins worked for each role (row, col)

    All the other pins seem to work for yet more buttons, except 1 if you init pin1 it breaks the matrix (glitch in the matrix?)


    Now I need to do the same thing for my RADDS
  • You mean complete row 1 (pin 18) is broken and you do not init it as output?
  • nope these pins work all 16 buttons

    using pin1 anywhere in there could cause either a row or col to not work. Also though, if you try to:
    then not only does that button not work, but it also kills the matrix. All the other free pins still worked as regular buttons, even if they didn't work as part of the key matrix.
Sign In or Register to comment.