4x4 keypad

Hi all

im trying to het a 4x4 keypad to work.
somehow when the function Returns a value the first time its OK but the second time i get a differnt value.
and on the serial port i see that it stops the for loops.
but when i use Serial.print then it all works OK! the for loops keep playing like i what it to be.

i know there is a library but that takes away all the fun. and head banging against the wall.

const uint8_t colom[4] = {13, 12, 11, 10};
const uint8_t row[4] = {7, 6, 5, 4};

const char sign[4][4] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
char a;
uint8_t prevstate[4][4];
uint8_t state[4][4];

char test;
void setup() {

  Serial.begin(9600);

  for (uint8_t x = 0; x < 4; x++) {
    pinMode(colom[x], OUTPUT);
  }
  for (uint8_t x = 0; x < 4; x++) {
    pinMode(row[x], INPUT_PULLUP);
  }
}



void loop() {
  //readKeypad(); //<----------"2"
  //Serial.println(); // <---------- "2"
  Serial.println(readKeypad()); // <----------- "1"
  delay(1000);
}

char readKeypad() {
  for (uint8_t a = 0; a < 4; a++) {
    digitalWrite(colom[a], LOW);
    delay(100);
    Serial.print("A: ");
    Serial.print(a);
    Serial.print(" ");
    for (uint8_t b = 0; b < 4; b++) {
      Serial.print("B: ");
      uint8_t state = digitalRead(row[b]);
      if (state == LOW) {
        return sign[a][b]; // <--------- "1"
        Serial.print("X"); // Serial.print(sign[a][b]);  gives the correct value. X is used to make it more clear.
        Serial.print(" ");
      } else {
        Serial.print(b);
        Serial.print(" ");
      }
    }
    digitalWrite(colom[a], HIGH);
    Serial.println();
  }
}

this is the code.
and i have some lines comment and say “1” and “2”
only one of them must be active.

and to give you a idea what i get.

this is wel you uncomment “1”

A: 0 B: 0 B: 1 B: 2 B: 3 
A: 1 B: 0 B: 1 B: 2 B: 3 
A: 2 B: 0 B: 1 B: 2 B: 3 
A: 3 B: 0 B: 1 B: 2 B: 3 

A: 0 B: 1 // i press button 1
A: 0 B: 1 // i press button 1
A: 0 B: 0 B: 1 B: 2 B: 3 
A: 1 B: 0 B: 1 B: 2 B: 3 
A: 2 B: 0 B: 1 B: 2 B: 3 
A: 3 B: 0 B: 1 B: 2 B: 3 

A: 0 B: 0 B: 2 // i press button 2
A: 0 B: 0 B: 2 // i press button 2
A: 0 B: 0 B: 1 B: 2 B: 3 
A: 1 B: 0 B: 1 B: 2 B: 3 
A: 2 B: 0 B: 1 B: 2 B: 3 
A: 3 B: 0 B: 1 B: 2 B: 3 

A: 0 B: 0 B: 1 B: 3 // i press button 3
A: 0 B: 0 B: 1 B: 3 // i press button 3
A: 0 B: 0 B: 1 B: 3
A: 0 B: 0 B: 1 B: 2 B: 3 
A: 1 B: 0 B: 1 B: 2 B: 3 
A: 2 B: 0 B: 1 B: 2 B: 3 
A: 3 B: 0 B: 1 B: 2 B: 3 

A: 0 B: 0 B: 1 B: 2 B: A // i press button 4
A: 0 B: 0 B: 1 B: 2 B: A // i press button 4
A: 0 B: 0 B: 1 B: 2 B: 3 
A: 1 B: 0 B: 1 B: 2 B: 3 
A: 2 B: 0 B: 1 B: 2 B: 3 
A: 3 B: 0 B: 1 B: 2 B: 3 

A: 0 B: 0 B: 1 B: 2 B: 3 
A: 1 B: 4 //  when i press button 5
A: 0 B: 1 // still 5 is pressed but it switch back to 1.
A: 0 B: 1
A: 0 B: 1

and this is what i het when i uncomment “2” or just Serial. w/o return
where the X is that button is pressed

A: 0 B: X B: 1 B: 2 B: 3 //Button1
A: 1 B: 0 B: 1 B: 2 B: 3 
A: 2 B: 0 B: 1 B: 2 B: 3 
A: 3 B: 0 B: 1 B: 2 B: 3 

A: 0 B: 0 B: X B: 2 B: 3 //Button2
A: 1 B: 0 B: 1 B: 2 B: 3 
A: 2 B: 0 B: 1 B: 2 B: 3 
A: 3 B: 0 B: 1 B: 2 B: 3 

A: 0 B: 0 B: 1 B: X B: 3 //Button3
A: 1 B: 0 B: 1 B: 2 B: 3 
A: 2 B: 0 B: 1 B: 2 B: 3 
A: 3 B: 0 B: 1 B: 2 B: 3 

A: 0 B: 0 B: 1 B: 2 B: X //Button4
A: 1 B: 0 B: 1 B: 2 B: 3 
A: 2 B: 0 B: 1 B: 2 B: 3 
A: 3 B: 0 B: 1 B: 2 B: 3 

A: 0 B: 0 B: 1 B: 2 B: 3 
A: 1 B: X B: 1 B: 2 B: 3 //button5
A: 2 B: 0 B: 1 B: 2 B: 3 
A: 3 B: 0 B: 1 B: 2 B: 3 

A: 0 B: 0 B: 1 B: 2 B: 3 
A: 1 B: X B: 1 B: 2 B: 3 //button5
A: 2 B: 0 B: 1 B: 2 B: 3 
A: 3 B: 0 B: 1 B: 2 B: 3 

A: 0 B: 0 B: 1 B: 2 B: 3 
A: 1 B: 0 B: X B: 2 B: 3 //button6
A: 2 B: 0 B: 1 B: 2 B: 3 
A: 3 B: 0 B: 1 B: 2 B: 3 

A: 0 B: 0 B: 1 B: 2 B: 3 
A: 1 B: 0 B: X B: 2 B: 3 //button6
A: 2 B: 0 B: 1 B: 2 B: 3 
A: 3 B: 0 B: 1 B: 2 B: 3

this seems to work Perfect.

when you return, you forget to set the row HIGH again.

Add this line before the return:

        digitalWrite(colom[a], HIGH); //turn it HIGH again before exiting
        return sign[a][b]; // <--------- "1"

Yeah!!! thanks allot. it works!

still dont know why but i will look at it more.

and still it seems to Stop scanning thru all the other coloms/rows. when as example i press button 1. it seems like when read==LOW, stop scanning/for loop and start from the begin again.

but with the Serial.print it Scans everything. all the time?

oww never mind i allready read a return statement stops execution and returns to the calling function. and i do understand why now.

therefore i also undestand now why i need to put the colom back to high again. before the return statement.

Something the tutorials don’t really stress here is software engineering.

I few simple changes to your code could make it both easier to read, debug and modify.

Have the compiler do some of the work based on your initial software setup.

Examples as follows

#define ENTRY_COUNT(ARRAY)          (size(ARRAY) / size(ARRAY[0]))

const uint8_t   KEY_UP                      = HIGH;
const uint8_t   KEY_DOWN                    = LOW;

const uint8_t   column[]                    = { 13, 12, 11, 10 };
const uint8_t   row[]                       = {  7,  6,  5,  4 };

const size_t    NUM_KEY_COLS                = ENTRY_COUNT(column);
const size_t    NUM_KEY_ROWS                = ENTRY_COUNT(row);

const char sign[NUM_KEY_ROWS][NUM_KEY_COLS] =
{
      { '1', '2', '3', 'A' }
    , { '4', '5', '6', 'B' }
    , { '7', '8', '9', 'C' }
    , { '*', '0', '#', 'D' }
};

uint8_t prevstate[NUM_KEY_ROWS][NUM_KEY_COLS];
uint8_t state[NUM_KEY_ROWS][NUM_KEY_COLS];

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

    for ( size_t i = 0; i < NUM_KEY_COLS; i++)
    {
        pinMode(column[i], OUTPUT);
    }

    for ( size_t i = 0; i < NUM_KEY_ROWS; i++)
    {
        pinMode(row[i], INPUT_PULLUP);
    }
}

    ...

    uint8_t state = digitalRead(row[iRow]);
    if ( KEY_DOWN == state )
    {
        ...
        
    ...