lcd+4x4 keypad interfacing with arduino uno

Hi I am interfacing lcd and keypad with arduino uno. The Lcd is working fine but the keypad is not working. It is being stuck in the do while loop. In this loop the microcontroller is checking for a pressed key by checking the value of PortC. Btw i connected the lsb bits of portC to the columns of the keypad whereas the rows are connected to the lsb bits of portD. This is the program so far:

#define COL PORTC
#define ROW PORTD

bool rw = PB1;
bool rs= PB0;
bool en= PB2;
void MSDelay(unsigned int itime);
void lcdcmd(char value);
void lcddata(char value);

const char *string="Enter Password";
unsigned char keypad[4][4]= {'0', '1', '2', '3',
'4', '5', '6', '7',
'B', '9', 'A', 'B',
'C', 'D', 'E', 'F'};

void setup() {

Serial.begin(9600);
DDRB=0x07;
DDRD=0xFF;
DDRC=0x00;

lcdcmd(0x02);
lcdcmd(0x28);
lcdcmd(0x0E);
lcdcmd(0x01);
lcdcmd(0x80);

for (; *string!='\0'; ++string)
{
lcddata(*string);
}
lcdcmd(0xC0);
//ROW=0x00;
PORTC=0x7F;

}

void loop() {
int i=0;
unsigned char password[4];
unsigned char colloc, rowloc, column;
do
{
ROW = 0x00;
colloc=PORTC;
colloc &=0x0F;

}while (colloc != 0x0F);

do
{
do
{
MSDelay(2000);
colloc=COL;
colloc &=0x0F;
}while(colloc==0x0F);

MSDelay(2000);
colloc=COL;
colloc &=0x0F;
}while(colloc==0x0F);

while (1)
{
ROW = 0xFE;
colloc = COL;
colloc &=0x0F;
if (colloc != 0x0F)
{
rowloc=0;
break;
}
ROW = 0xFD;
colloc = COL;
colloc &=0x0F;
if (colloc != 0x0F)
{
rowloc=1;
break;
}
ROW = 0xFB;
colloc = COL;
colloc &=0x0F;
if (colloc != 0x0F)
{
rowloc=2;
break;
}
ROW = 0xF7;
colloc = COL;
colloc &=0x0F;

if (colloc != 0x0F)
{
rowloc=3;
break;
}
}
if (colloc==0x0E)
{
column=0;
lcddata('');
}
else if (colloc==0x0D)
{
column=1;
lcddata('X');
}
else if (colloc==0x0B)
{
column=2;
lcddata('Z');
}
else
{
column=3;
lcddata('P');
}
if (i<=4)
{
password
=keypad[rowloc][column];*

  • i++;*
  • }*

}
void lcdcmd(char value)
{

  • PORTD = (value & 0xF0);*
  • PORTB=0x04;*
  • MSDelay(2000);*
  • PORTB=0x00;*
  • MSDelay(20000);*
  • PORTD = ((value<<4) & 0xF0);*
  • PORTB=0x04;*
  • MSDelay(2000);*
  • PORTB=0x00;*
  • MSDelay(20000);*
  • return;*

}
void lcddata(char value)
{

  • PORTD = (value & 0xF0);*
  • PORTB=0x05;*
  • MSDelay(2000);*
  • PORTB=0x00;*
  • MSDelay(20000);*
  • PORTD = ((value<<4) & 0xF0);*
  • PORTB=0x05;*
  • MSDelay(2000);*
  • PORTB=0x00;*
  • MSDelay(20000);*
  • return;*
    }
    void MSDelay(unsigned int itime)
    {
    unsigned int i=0;
    for(i=0; i<=itime; i++);
    }
    I appreciate any kind of help 10q in advance :slight_smile:

I appreciate any kind of help 10q in advance

Why do you think you need to use direct port manipulation to read a keypad?

Why are you not using the Keypad library?

but the keypad is not working. It is being stuck in the do while loop.

I can assure you that the hardware is not stuck in a do while loop.

Did you use your MSDelay() function instead of a simple delay() hoping that using it would not block program execution ? How long do you think that the for loop will take with an itime of say 20000 ?

It shouldnt be a problem I used the MSDelay in the LCD display alone and it worked. The problem seems to be that portC (column) is not detecting any key press. The value of PortC is always remaining the same, I checked it with serial interface of arduino uno.

Please I am having a problem with this loop when interfacing the keypad with lcd: The rowloc (row location) is always being assigned to a value 0. I got this code from a book discussing 8051 microcontrollers and decided to implement it on Arduino uno board to see if it works. Please can someone help me.

while(1)
{
PORTD = bptr;
colloc = PINC;
colloc &=0x0F;
if (colloc == 0x0F)
{
rowloc=0;
//PORTD=
(bptr+1);
break;
}

PORTD=*(bptr+1);
colloc = PINC;
colloc &=0x0F;
if (colloc != 0x0F)
{
rowloc=1;
break;
}

PORTD = *(bptr+2);
colloc = PINC;
colloc &=0x0F;

if (colloc != 0x0F)
{

rowloc=2;
break;

}
PORTD = *(bptr+3);
colloc = PINC;
colloc &=0x0F;
if (colloc != 0x0F)
{

rowloc=3;
break;

}

}

What are the break in the If supposed to do ?
How are things wired ?
What is bptr and why do you add 1,2,3 to it ?

Please correct all your post above and add code tags around your code:
[code]`` [color=blue]// your code is here[/color] ``[/code].

It should look like this:// your code is here
(Also press ctrl-T (PC) or cmd-T (Mac) in the IDE before copying to indent your code properly)

int rowval[4]={0xFE, 0xFD, 0xFB, 0xF7};
int *bptr=rowval;

bptr points to rowval array which contains row values for PORTD. In the while loop i ground row 0, row 1 etc.... and each time i check the value of the columns in portC. If the value of PORTC is not equal to 0x0F, the program enters the if condition and assigns the row value to variable rowloc and exits the while loop tghrough break statement.Then it repeats the process all over again in the while loop from the beginning. This is how I wired the keypad: columns: ADC0 -ADC3 (PORTC) and rows : PD0-PD3 (PORTD)

please fix your code posts using the code tags. that's one of the basic netiquette here...

Although not your problem here but....

PORT registers are bytes, not int so you should have

const uint8_t rowval[]={0xFE, 0xFD, 0xFB, 0xF7}; 
uint8_t *bptr=rowval;

if you have an array, why do you mess with pointers? instead of PORTD = *(bptr+2);just do PORTD = rowval[2];

So your rows are on PD0-PD3. PORT D maps to digital pins 0 to 7 so you are aware you are messing with the pins 0 and 1 which are connected to your Serial connection? (that's OK but you can't debug through Serial)

for readability I would use the existing library.. If you want to explore, then I would not use ports at all, you don't need that speed with a keypad... but for the sake of playing around with PORTS, for readability and not messing with other pins, I would have done

PORTD &= B11110000;  // start clean so PORTD = xxxx0000
PORTD |= B00001110; // GROUND row 0
...
PORTD &= B11110000;
PORTD |= B00001101 // GROUND row 1
...
PORTD &= B11110000;
PORTD |= B00001011 // GROUND row 2
...
PORTD &= B11110000;
PORTD |= B00000111 // GROUND row 3
...

or - if you care about instant toggling (1 operation and not 2 as above) as you know nothing is changing the state of your pins - use the fact that writing in PIND actually toggles pins, so

PORTD &= B11110000; // start clean so PORTD = xxxx0000
PIND = B00001110; // GROUND row 0 (toggle bits 1,2,3 so PORTD = xxxx1110)
...
PIND = B00000011; // GROUND row 1 (toggle bits 0,1 so PORTD = xxxx1101)
...
PIND = B00000110; // GROUND row 2 (toggle bits 1,2 so PORTD = xxxx1011)
...
PIND = B00001100; // GROUND row 3 (toggle bits 2,3 so PORTD = xxxx0111)

Now your actual problem is in this lineif (colloc == 0x0F)--> the first one at the start of your while... compare with the others where you doif (colloc != 0x0F)

I tried your suggestions but it is still not working properly. I obtained the code from the 8051 microcontroller by mazidi chapter 12. The rows and columns are not being assigned appropriately i dont know what to do. The code at least in the 8051 microcontroller should work. Btw you can use PINX to read information from the corresponding port correct ?

Clarify

  • exact wiring (pull-ups, etc)
  • exact code you use (full one)

This is the code so far. I don't know why its not working properly. I used ADC0-ADC3 (PORTC) as columns whereas for rows I used (PD0-PD3) (portD). for the lcd I used PB0,PB1,PB2 (portB) as rs,rw and en pins respectively. Moreover I used (PD4-PD7) port D as the lcd data pins.

#define COL PORTC
#define ROW PORTD

bool rw = PB1;
bool rs = PB0;
bool en = PB2;
void MSDelay(unsigned int itime);
void lcdcmd(char value);
void lcddata(char value);
int ledsw = 0;
int counter = 0;
const char *string = "Enter Password";
const char *string2 = "Good";
const char *string3 = "BAD";
unsigned char keypad[4][4] = {'0', '1', '2', '3',
                              '4', '5', '6', '7',
                              'B', '9', 'A', 'B',
                              'C', 'D', 'E', 'F'
                             };
//int rowval[4]={0xFE, 0xFD, 0xFB, 0xF7};
//int *bptr=rowval;
int i = 0;
void setup() {
  //int *b[]={10,12,12,12};
  //Serial.begin(9600);
  DDRB = 0x0F;
  DDRD = 0xFF;
  DDRC = 0x00;


  lcdcmd(0x02);
  lcdcmd(0x28);
  lcdcmd(0x0E);
  lcdcmd(0x01);
  lcdcmd(0x80);



  for (; *string != '\0'; ++string)
  {
    lcddata(*string);
  }
  lcdcmd(0xC0);

  //PORTD=0xF0;

}

void loop() {


  int rep = 0;
  unsigned char password[5] = {"12345"};
  unsigned char copy[5];
  unsigned char colloc, rowloc, column;
  int pass = 0;

  /*DDRD=0xFF;
    DDRC=0x00;
    PINC=0x00;
    /* ledsw=digitalRead(A5);
    if (ledsw == HIGH)
    {
    digitalWrite(11,HIGH);
    }
    else
    {
    digitalWrite(11, LOW);
    }

  */




  do
  {

    PIND = 0x00;
    colloc = PINC;
    colloc &= 0x0F;



  } while (colloc != 0x0F);



  do
  {

    do
    {

      MSDelay(200);
      colloc = PINC;
      colloc &= 0x0F;
    } while (colloc == 0x0F);

    MSDelay(200);
    colloc = PINC;
    colloc &= 0x0F;
  } while (colloc == 0x0F);


  //PORTD&=B11110000;
  while (1)
  {

    PORTD &= B00000000;
    PIND = B00001110;
    colloc = PINC;
    colloc &= 0x0F;
    if (colloc != 0x0F)
    {
      rowloc = 0;

      digitalWrite(11, HIGH);
      colloc = 0x0F;
      break;
    }

    //PORTD&=B11110000;
    PIND = B00000011;
    colloc = PINC;
    colloc &= 0x0F;
    if (colloc != 0x0F)
    {
      rowloc = 1;
      break;
    }

    //PORTD&=B11110000;
    PIND = B00000110;
    colloc = PINC;
    colloc &= 0x0F;

    if (colloc != 0x0F)
    {

      rowloc = 2;
      break;

    }
    //PORTD&=B11110000;
    PIND = B00001100;
    colloc = PINC;
    colloc &= 0x0F;
    if (colloc != 0x0F)
    {

      rowloc = 3;
      break;

    }

  }

  /*if (PORTD==0x0D)
    {
    digitalWrite(11,HIGH);
    }
  */







  if (colloc == 0x0E)
  {
    lcddata(keypad[rowloc][0]);
    //copy[i]=keypad[rowloc][column];
  }

  else if (colloc == 0x0D)
  {

    lcddata(keypad[rowloc][1]);
    //copy[i]=keypad[rowloc][column];
  }

  else if (colloc == 0x0B)
  {
    lcddata(keypad[rowloc][2]);
    //copy[i]=keypad[rowloc][column];
  }
  else if (colloc == 0x07)
  {
    lcddata(keypad[rowloc][3]);
    //copy[i]=keypad[rowloc][column];
  }





  for (rep = 0; rep <= 4; rep++)
  {
    if (password[rep] == copy[rep])
    {
      ++pass;
    }
  }
  if (pass == 3)
  {
    lcdcmd(0x01);
    lcdcmd(0x80);
    for (; *string2 != '\0'; ++string2)
    {
      lcddata(*string2);
    }
  }

  /*else if(i==4)
    {
      lcdcmd(0x01);
      lcdcmd(0x80);
     for (; *string3!='\0'; ++string3)
    {
    lcddata(*string3);
    }
    pass=0;
    }
  */

}



void lcdcmd(char value)
{
  PORTD = (value & 0xF0);
  PORTB = 0x04;
  MSDelay(2000);
  PORTB = 0x00;
  MSDelay(20000);
  PORTD = ((value << 4) & 0xF0);
  PORTB = 0x04;
  MSDelay(2000);
  PORTB = 0x00;
  MSDelay(20000);
  return;

}
void lcddata(char value)
{
  PORTD = (value & 0xF0);
  PORTB = 0x05;
  MSDelay(2000);
  PORTB = 0x00;
  MSDelay(20000);
  PORTD = ((value << 4) & 0xF0);
  PORTB = 0x05;
  MSDelay(2000);
  PORTB = 0x00;
  MSDelay(20000);

  return;
}

void MSDelay(unsigned int itime)
{
  unsigned int i = 0;
  for (i = 0; i <= itime; i++);

}

What’s this code ? suddenly different from what you posted before; have you checked the PIN stuff works as expected (typed it here)

Given your basic need I would suggest you stick to the keypad and LCD library, there are tons of examples for password management...

Sorry for bugging you again but I am still stuck with this program because i intend to make it work. This time I reconfigured the lcd and keypad interface in order to debug the program with serial interface. For the lcd i wired it the following way :

rs =PD2(port D pin no: 2), rw= PD3 (portD pin no 3) and en= PC5(portC pin no: analog input 5).
data pins : (PD4-PD7) (portD pins: 4-7)

for the keypad i wired it the following way :

columns: PortC (ADC0-ADC3)
rows: PortB (PB0-PB3) pins 8-11

For sure the while(1) loop is not working correctly, I also debugged this loop with serial interface.

Moreover I wired pull up resistors (value: 10k) for the columns whereas i simply wired the rows directly to the microcontroller.

Please can anyone help me with this issue, I really appreciate your help.

#define COL PORTC
#define ROW PORTB

bool rw = PD3;
bool rs = PD2;
bool en = PC5;
void MSDelay(unsigned int itime);
void lcdcmd(char value);
void lcddata(char value);
int ledsw = 0;
int counter = 0;
const char *string = "Enter Password";
const char *string2 = "Good";
const char *string3 = "BAD";
unsigned char keypad[4][4] = {'0', '1', '2', '3',
                              '4', '5', '6', '7',
                              'B', '9', 'A', 'B',
                              'C', 'D', 'E', 'F'
                             };
//int rowval[4]={0xFE, 0xFD, 0xFB, 0xF7};
//int *bptr=rowval;
int i = 0;
void setup() {
  //int *b[]={10,12,12,12};
  Serial.begin(9600);
  DDRB = 0x0F;
  DDRD = 0xFF;
  DDRC = 0x20;


  lcdcmd(0x02);
  lcdcmd(0x28);
  lcdcmd(0x0E);
  lcdcmd(0x01);
  lcdcmd(0x80);



  for (; *string != '\0'; ++string)
  {
    lcddata(*string);
  }
  lcdcmd(0xC0);

  //PORTD=0xF0;

}

void loop() {


  int rep = 0;
  unsigned char password[5] = {"12345"};
  unsigned char copy[5];
  unsigned char colloc, rowloc, column;
  int pass = 0;




  do
  {

    //PORTB = B00000000;
    colloc = PINC;
    colloc &= 0x0F;



  } while (colloc != 0x0F);



  do
  {

    do
    {

      MSDelay(200);
      colloc = PINC;
      colloc &= 0x0F;
    } while (colloc == 0x0F);

    MSDelay(200);
    colloc = PINC;
    colloc &= 0x0F;
  } while (colloc == 0x0F);





  while (1)
  {


    PORTB &= B11110000;
    PORTB |= B00001110;
    colloc = PINC;
    colloc &= 0x0F;
    if (colloc != 0x0F)
    {
      rowloc = 0;
      Serial.print("colloc0: " );
      Serial.println(colloc);
      Serial.print("PORTB0: ");
      Serial.println(PORTB);

      break;
    }

    PORTB &= B11110000;
    PORTB |= B00001101;
    colloc = PINC;
    colloc &= 0x0F;
    if (colloc != 0x0F)
    {
      rowloc = 1;
      Serial.print("colloc1: " );
      Serial.println(colloc);
      Serial.print("PORTB1: ");
      Serial.println(PORTB);
      break;
    }

    PORTB &= B11110000;
    PINB = B00001011;
    colloc = PINC;
    colloc &= 0x0F;

    if (colloc != 0x0F)
    {

      rowloc = 2;
      Serial.print("colloc2: " );
      Serial.println(colloc);
      Serial.print("PORTB2: ");
      Serial.println(PORTB);
      break;
    }

    PORTB &= B11110000;
    PINB = B00000111;
    colloc = PINC;
    colloc &= 0x0F;
    if (colloc != 0x0F)
    {
      Serial.print("colloc3: " );
      Serial.println(colloc);
      Serial.print("PORTB3: ");
      Serial.println(PORTB);
      rowloc = 3;
      break;

    }

  }







  if (colloc == 0x0E)
  {
    lcddata(keypad[rowloc][0]);
    //copy[i]=keypad[rowloc][column];
  }

  else if (colloc == 0x0D)
  {

    lcddata(keypad[rowloc][1]);
    //copy[i]=keypad[rowloc][column];
  }

  else if (colloc == 0x0B)
  {
    lcddata(keypad[rowloc][2]);
    //copy[i]=keypad[rowloc][column];
  }
  else if (colloc == 0x07)
  {
    lcddata(keypad[rowloc][3]);
    //copy[i]=keypad[rowloc][column];
  }





  for (rep = 0; rep <= 4; rep++)
  {
    if (password[rep] == copy[rep])
    {
      ++pass;
    }
  }
  if (pass == 3)
  {
    lcdcmd(0x01);
    lcdcmd(0x80);
    for (; *string2 != '\0'; ++string2)
    {
      lcddata(*string2);
    }
  }

  /*else if(i==4)
    {
      lcdcmd(0x01);
      lcdcmd(0x80);
     for (; *string3!='\0'; ++string3)
    {
    lcddata(*string3);
    }
    pass=0;
    }
  */

}



void lcdcmd(char value)
{
  //PORTD= 0x00;
  PORTD = (value & 0xF0);
  PORTC = 0x2F;
  MSDelay(2000);
  PORTC &= 0x0F;
  MSDelay(20000);
  // PORTD = 0x00;
  PORTD = ((value << 4) & 0xF0);
  PORTC = 0x2F;
  MSDelay(2000);
  PORTC &= 0x0F;
  MSDelay(20000);
  return;

}
void lcddata(char value)
{

  PORTD = (value & 0xF0);
  PORTD |= 0x04;
  PORTC = 0x2F;
  MSDelay(2000);
  PORTC &= 0x0F;
  MSDelay(20000);

  PORTD = ((value << 4) & 0xF0);
  PORTD |= 0x04;
  PORTC = 0x2F;
  MSDelay(2000);
  PORTC &= 0x0F;
  MSDelay(20000);

  return;
}

void MSDelay(unsigned int itime)
{
  unsigned int i = 0;
  for (i = 0; i <= itime

seems you need first to ensure all is wired up correctly and that you are using the right lines for the right job

-> Simplify your problem, get rid of the LCD, get rid of the password management code. Focus on getting the keypad to work « manually » if you don’t want to use the heavily tested keypad library

-> get rid of app the PORT stuff. At user input speed, digitalRead and digitalWrite are way fast enough to handle this. You’ll go to port later on

—> build your keypress wait loop in the simplest way possible and get it to work for one column only, then test column by column that your code works, then all columns together