4x4 Keypad connected with 1 wire

I am using the follwoing 4x4 keypad with 8-wire connector:

and found the following schema

to connect the keypad with only 1 wire to an ARDUINO.

I tried this out because saving pins is cool - but the whole Enchilada didnt work 100% correct:

String keys="123A456B789C*0#D";
int key;
boolean key_lockout=false;

void setup(){
   Serial.begin(9600); 
}

void loop(){
  key=getKeypad();
  if(key!=-1)
      Serial.println(keys[key]);
   delay(10);
}

int getKeypad(){
  int ret=-1;
  boolean reset_lockout=false;
  if(analogRead(A0)==0)
    key_lockout=false;
  else if(!key_lockout){
    delay(20);
    ret=15-(log((analogRead(A0)-183.9)/58.24)/0.1623)+0.5;
    key_lockout=true;
  }
  return ret;
}

Only 2,3,5,6 and 7 returns the pressed values, when pressing A the 1 is shown, by pressing 0 the D appears.

I double checked all wiring and soldering and all seems to be OK - but didnt work either.

Here is a video, too:

Do the math, see if those resistor values result in data values that are seperated enoough to be recognized:

Vanalog = (5V-Vdiode)*1500/(R1 +R2 + 1500)

So for 0 key, bottom middle, you'd have
Vanalog = (5V - 0.7V)*1500/(3300 + 480 + 1500) = 1.22159V
analogRead result ~1.22159/5 * 1023 = ~250

D key
Vanalog = (5V - 0.7V)*1500/(3300 + 680 + 1500) =1.17700V
analogRead result ~1.17700/5 * 1023 = ~240

How does that compare to what you see here?
ret=15-(log((analogRead(A0)-183.9)/58.24)/0.1623)+0.5;

The diode drop of the diode will have an impact also.

How does that compare to what you see here?
ret=15-(log((analogRead(A0)-183.9)/58.24)/0.1623)+0.5;

i have no idea :blush:

A.R.Ty:

How does that compare to what you see here?
ret=15-(log((analogRead(A0)-183.9)/58.24)/0.1623)+0.5;

i have no idea :blush:

I'll give you a clue, it bears no relation to it.
Why on earth do you have a log function in there?

Yo Guys,

as written the code is from the DIYer 8)

A.R.Ty:
Yo Guys,

as written the code is from the DIYer 8)

Dosn't stop it from being crap though does it?

i've got the same problem did you found the solution??

not really, some keys dont work and one has the D instead of the *

But i can live with this so far, because for my LCD-Menu i need only some of them.
Sometime, somehow, someone will find a solution - i stopped trying around because without understanding what happens it's like a roulette

The output voltages and analogRead()s should be something like this
Key Vin R1a R1b R2
5V Rcol Rrow Rgnd Vout ~Analog Read
1 5 0 0 1500 5 1023
2 5 0 220 1500 4.360465116 892
3 5 0 480 1500 3.787878788 775
a 5 0 680 1500 3.440366972 704
4 5 1000 0 1500 3 614
5 5 1000 220 1500 2.757352941 564
6 5 1000 480 1500 2.516778523 515
b 5 1000 680 1500 2.358490566 483
7 5 2200 0 1500 2.027027027 415
8 5 2200 220 1500 1.913265306 391
9 5 2200 480 1500 1.794258373 367
c 5 2200 680 1500 1.712328767 350

  • 5 3300 0 1500 1.5625 320
    0 5 3300 220 1500 1.494023904 306

5 3300 480 1500 1.420454545 291

D 5 3300 680 1500 1.368613139 280

Vout = Vin * R2/(R1a +R1b+R2)
or Vout = 5*Rgnd/(Rcol+Rrow+Rgnd)

AnalogRead = Vout/5V * 1023

so if you did a series of if statements with some range around the numbers, or better yet printed out the actual analogReads for the resistors used and tweak around those, you would likely get better results:

if (analogInput <=285){
keyPressed = 'D';
}
if ( (analogInput >285) & (analogInput <= 298) ){
keyPressed = '#';
}
if ( (analogInput >299) & (analogInput <= 313) ){
keyPressed = '0';
}

etc.

Might have to adjust the math for the diode drop as well:
Vout = (5-Vf)*Rgnd/(Rcol+Rrow+Rgnd)
with Vf = to 0.3V to 0.7V depending on the diode used.

I will try out your parameter.

so far i am using this working sketch within the LCDmenu.lib (found here (german): Projekt: LCDMenuLib / LCDMenuLib2 ( LCDML ) - Menü mit mehreren Ebenen - Deutsch - Arduino Forum):

void LCDMenuLib_control_KeyPaddy()
{
  int key = getKeypad();
  if(key == 2) {
     LCDML.Button_up_down_left_right(_LCDMenuLib_button_up);}
  else if(key == 4) {
    LCDML.Button_up_down_left_right(_LCDMenuLib_button_left);}
  else if(key == 8) {        
    LCDML.Button_up_down_left_right(_LCDMenuLib_button_down);}
  else if(key == 6) { 
    LCDML.Button_up_down_left_right(_LCDMenuLib_button_right);}
  else if(key == 9) { 
    LCDML.Button_quit();}
  else if(key == 5) { 
    LCDML.Button_enter();}
}

This part didnt work in case of what you wrote: only an array of values work, not an array containg only 1 :

/* analog menu control */
void LCDMenuLib_control_analog()
{
  uint16_t value = analogRead(0);  // analogpin for keypad

  #define _BUTTON_analog_enter_min     1 //850     // Button Enter                   E
  #define _BUTTON_analog_enter_max     1 //920  
  #define _BUTTON_analog_up_min        2     // Button Up                      W
  #define _BUTTON_analog_up_max        2   
  #define _BUTTON_analog_down_min      8 //700     // Button Down                    S
  #define _BUTTON_analog_down_max      8   
  //optional if menu element "back" exists, look at FUNC_back in functions tab 
  #define _BUTTON_analog_enable_quit   5
  #define _BUTTON_analog_back_min      7 //950     // Button Back                    Q
  #define _BUTTON_analog_back_max      7 //1020   
  //optional if needed
  #define _BUTTON_analog_enable_lr     5
  #define _BUTTON_analog_left_min      4 //430     // Button Left                    A
  #define _BUTTON_analog_left_max      4 //500   
  #define _BUTTON_analog_right_min     6 //610     // Button Right                   D
  #define _BUTTON_analog_right_max     6 //680   
      
  if(LCDML.Timer(g_LCDMenuLib_press_time, _LCDMenuLib_cfg_press_time)) {
    if(value >= _BUTTON_analog_enter_min && value <= _BUTTON_analog_enter_max) {        // control enter
      LCDML.Button_enter();
    }  
    else if(value >= _BUTTON_analog_up_min && value <= _BUTTON_analog_up_max) {      // control up
      LCDML.Button_up_down_left_right(_LCDMenuLib_button_up);
    } 
    else if(value >= _BUTTON_analog_down_min && value <= _BUTTON_analog_down_max) {   // control down
      LCDML.Button_up_down_left_right(_LCDMenuLib_button_down);
    }    
    else if(value >= _BUTTON_analog_left_min && value <= _BUTTON_analog_left_max && _BUTTON_analog_enable_lr == 1) {   // control left
      LCDML.Button_up_down_left_right(_LCDMenuLib_button_left);
    } 
    else if(value >= _BUTTON_analog_right_min && value <= _BUTTON_analog_right_max && _BUTTON_analog_enable_lr == 1) { // control right
      LCDML.Button_up_down_left_right(_LCDMenuLib_button_right);
    }
        
    if(value >= _BUTTON_analog_back_min && value <= _BUTTON_analog_back_max && _BUTTON_analog_enable_quit == 1) {          // control quit
      LCDML.Button_quit();
    }
  }
}

This looks similar to your given code and after trying out i'll back with the results.

Paraphrasing some:

so far i am using this working (mostly, some keys dont work and one has the D instead of the *) sketch

Reminds me of a Steven Wright routine. He bought he a second hand phone, or he dropped it, and not all the buttons worked. A friend asked why he never called? "I can't call you, my phone doesn't have a 5". Friend: "You're weird".
Later on he sees his friend again, tells him someone stole all his stuff and replaced it with exact duplicates. Friend: "Do I know you?"

i got the same problem did you found the solution ?

Did you try reversing the rows and columns? This works fine for me when you use 1-4 as columns and 5-8 as rows.

So far most of all are working, only B,C,D and 0 not.

It worked for me, just changed the values of resisters a lit'l bit.. But getting garbage output as '1' if no key is pressed after some interval of times....

String keys = "123A456B789C*0#D";
boolean key_lockout = false;

void setup()
{
 Serial.begin(9600);
}

void loop()
{
 char c = getKey();
 Serial.println(c);
}

char getKey()
{
 int key = getKeypad();
 if (key != -1)
   return (keys[key]);
 else
   return ('E');
 delay(10);
}

int getKeypad()
{
 int ret = -1;

 if (analogRead(A0) == 0)
 {
   delay(50);
   if (analogRead(A0) == 0)
     key_lockout = false;
 }

 else if (!key_lockout && analogRead(A0) > 183.9)
 {
   delay(50);
   if (analogRead(A0) > 183.9)
   {
   ret = 15 - (log((analogRead(A0) - 183.9) / 58.24) / 0.1623) + 0.5;
   key_lockout = true;
   }
 }
 return ret;
}

Sorry for jumping into this thread, but I have also struggled a lot with this and I have now managed to make it work. I have extended it to 5X5 which works as well.

But before I came so far to make it work with Arduino, I have made another solution by modifying an X-KEYS, XK-24.
However, this is an expensive solution, but it is working perfectly. I now have 18 X 18 buttoms spread over 2 layers and because of the two layers, I can reduce the physical size of my foot pedal board.

Well, I did purchased this Arduino Micro Pro for the above purpose and want to make it work anyway.
I would like to make an MIDI pedal with it.
My next challenge would then be, to figure out, how to use the data from the button matrix to use for MIDI.

Please be aware, that I am definitely not any geek into programming! There is probably a much better solution for this, so please take it or leave it. :wink:

The code I have put together, is from reading several forum threads: (Have left out some of the code due to maxium allowed characters)

/*


*/


int j = 1; // integer used in scanning the array designating column number
//2-dimensional array for assigning the buttons and there high and low values
int Button[25][3] = {{1, 876, 880}, // button 1  *1
                    {2, 764, 768}, // button 2  *2
                    {3, 668, 672}, // button 3  *3
                    {4, 604, 608}, // button 4  *4
                    {5, 568, 572}, // button 5  *5
                    {6, 527, 531}, // button 6  *6
                    {7, 484, 488}, // button 7  *7
                    {8, 444, 448}, // button 8  *8
                    {9, 415, 419}, // button 9  *9
                    {10, 397, 401}, // button 10  *A
                    {11, 357, 361}, // button 11  *B
                    {12, 336, 340}, // button 12  *C
                    {13, 316, 320}, // button 13  *D
                    {14, 301, 305}, // button 14  *E
                    {15, 292, 296}, // button 15  *F
                    {16, 275, 279}, // button 16  *G
                    {17, 262, 266}, // button 17  *H
                    {18, 250, 254}, // button 18  *I
                    {19, 240, 244}, // button 19  *J
                    {20, 234, 238}, // button 20  *K
                    {21, 227, 231}, // button 21  *L
                    {22, 219, 223}, // button 22  *M
                    {23, 210, 214}, // button 23  *N
                    {24, 203, 207}, // button 24  *O
                    {25, 199, 203}}; // button 25  *P


int analogpin = 0; // analog pin to read the buttons
int label = 0;  // for reporting the button label
int counter = 0; // how many times we have seen new value
long time = 0;  // the last time the output pin was sampled
int debounce_count = 50; // number of millis/samples to consider before declaring a debounced input
int current_state = 0;  // the debounced input value
int ButtonVal;
int analogPin = 0;     // Read serial data connected to analog pin 0
int val = 0;           // variable to store the value read for serial read



boolean b1 = false;
boolean b2 = false;
boolean b3 = false;
boolean b4 = false;
boolean b5 = false;
// code left out


long randNumber;

void setup()
{
  Keyboard.begin();
  
  Serial.begin(9600);          //  setup serial
 
 
  randomSeed(analogRead(1));
  randNumber = random(0,2);
 

}

void loop()
    {
    val = analogRead(analogPin);    // read the input pin

    Serial.println(val);             // debug value. E.g. 878 for button 1 is like this: {1, 876, 880}, // button 1  *1

  static float in = 4.712;
  float out;
   // If we have gone on to the next millisecond
  if (millis() != time)
  {
    // check analog pin for the button value and save it to ButtonVal
    ButtonVal = analogRead(analogpin);
    if(ButtonVal == current_state && counter >0)
    {
      counter--;
    }
    if(ButtonVal != current_state)
    {
      counter++;
    }
    // If ButtonVal has shown the same value for long enough let's switch it
    if (counter >= debounce_count)
    {
      counter = 0;
      current_state = ButtonVal;
      //Checks which button or button combo has been pressed
      if (ButtonVal > 0)
      {
        ButtonCheck();
      }
    }
    time = millis();
  }
 
}

void ButtonCheck()
{
  



  // loop for scanning the button array.
  for(int i = 0; i <= 25; i++)


  {
    // checks the ButtonVal against the high and low vales in the array
    if(ButtonVal >= Button[i][j] && ButtonVal <= Button[i][j+1])
    {
      // stores the button number to a variable
      label = Button[i][0];
      Action();     
    }
  }
}

void Action()
{
  if(label == 1)
  {
   b1=true;
   b2=false;
   b3=false;
   b4=false;
   b5=false;
   b6=false;
   b7=false;
   b8=false;
   b9=false;
   b10=false;
   b11=false;
   b12=false;
   b13=false;
   b14=false;
   b15=false;
   b16=false;
   b17=false;
   b18=false;
   b19=false;
   b20=false;
   b21=false;
   b22=false;
   b23=false;
   b24=false;
   b25=false;
   Keyboard.print('1');
   }
  if(label == 2)
  {
   b1=false;
   b2=true;
   b3=false;
   b4=false;
   b5=false;
   b6=false;
   b7=false;
   b8=false;
   b9=false;
   b10=false;
   b11=false;
   b12=false;
   b13=false;
   b14=false;
   b15=false;
   b16=false;
   b17=false;
   b18=false;
   b19=false;
   b20=false;
   b21=false;
   b22=false;
   b23=false;
   b24=false;
   b25=false;
   Keyboard.print('2');
  }
  if(label == 3)
  {
   b1=false;
   b2=false;
   b3=true;
   b4=false;
   b5=false;
   b6=false;
   b7=false;
   b8=false;
   b9=false;
   b10=false;
   b11=false;
   b12=false;
   b13=false;
   b14=false;
   b15=false;
   b16=false;
   b17=false;
   b18=false;
   b19=false;
   b20=false;
   b21=false;
   b22=false;
   b23=false;
   b24=false;
   b25=false;
   Keyboard.print('3');
  }
  if(label == 4)
  {
   b1=false;
   b2=false;
   b3=false;
   b4=true;
   b5=false;
   b6=false;
   b7=false;
   b8=false;
   b9=false;
   b10=false;
   b11=false;
   b12=false;
   b13=false;
   b14=false;
   b15=false;
   b16=false;
   b17=false;
   b18=false;
   b19=false;
   b20=false;
   b21=false;
   b22=false;
   b23=false;
   b24=false;
   b25=false;
   Keyboard.print('4');
   }
  // Code left out!!





}