Setting a 5 digit count using 4x4 matrix keypad & the Arduino Uno

#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header

hd44780_I2Cexp lcd; // declare lcd object: auto locate & config exapander chip

// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;

#include <Keypad.h>

const byte ROWS = 4; // Four rows
const byte COLS = 4; // Three columns


// Define the Keymap
char keys[ROWS][COLS] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'.', '0', '#', 'D'}
};


// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = { 6, 7, 8, 9 };
// Connect keypad COL0, COL1 and COL2 to these Arduino pins.
byte colPins[COLS] = { 5, 4, 12, 11};


// Create the Keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );



void setup()
{
   lcd.begin(LCD_COLS, LCD_ROWS);
}

void loop()
{
  const byte entryMaxSize = 5;
  static char count[entryMaxSize];

  // index
  static byte x = 0;

  char key = kpd.getKey();

  if (key != NO_KEY) // Check for a valid key.
  {
    switch (key)
    {

      case 'A':
      lcd.setCursor(0,0);
        lcd.print("Set Count:");
        // reset the counter
        x = 0;
        break;

      case 'D':
        lcd.setCursor(0,1);
        lcd.print("Count Set:");
        for (byte i = 0; i < x; i++)
        {
          lcd.print(count[i]);
        }
        break;

      default:
        // if not 5 characters yet
        if (x < entryMaxSize)
        {
          // add key to userinput array and increment counter
          count[x++] = key;
        }
        break;
    }
  }
}

Issues:

  1. Even if the key A is not pressed I am able to enter a count and set it by pressing the key D.
  2. How to make sure that unless and until key A is pressed, user must not be allowed to set a count?

Add a boolean variable key_A_was_pressed, set it, check it, clear it.

I have now tried the following:

#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header

hd44780_I2Cexp lcd; // declare lcd object: auto locate & config exapander chip

// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;

#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {6, 7, 8, 9}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 12, 11}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
bool a = true;

void setup()
{
  lcd.begin(LCD_COLS, LCD_ROWS);
  lcd.setCursor(3, 0);
  lcd.print("  PRIYA");
  lcd.setCursor(3, 1);
  lcd.print("ELECTRONICS");
  delay(100);
  for (int positionCounter = 0; positionCounter < 40; positionCounter++)
  {
    lcd.scrollDisplayLeft();
    delay(150);
  }
  delay(800);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Set Count:");
}


void loop()
{
  const byte entryMaxSize = 5;
  static char count[entryMaxSize];

  // index
  static byte x = 0;
  char key = keypad.getKey();

  if (key != NO_KEY) // Check for a valid key.
  {
      switch (key)
    {
      case 'A':
       lcd.clear();
       lcd.setCursor(0,0);
       lcd.print("Set Count:");
        // reset the counter
        x = 0;
        a = true;    
        break;

      case 'D':
      if (a){
        lcd.clear();
        lcd.print("Count Set: ");
        for(byte i=0;i<x;i++) {
        lcd.print(count[i]); 
        } 
      }
       break;

      default:
        // if not 5 characters yet
        if (x < entryMaxSize)
        {
          // add key to userinput array and increment counter
          count[x++] = key;
        }
        break;
    }
  }
  }

In case 'D' add a statement to set "a" to false ( to clear it as aarg said).
In default, add a condition "if ( a == true ) . . . " so that numbers are accepted only after "a" has been set to true ( to check it as aarg said).

Thanks for the explanation, I shall make the corrections.

With corrections:

#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header

hd44780_I2Cexp lcd; // declare lcd object: auto locate & config exapander chip

// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;

#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {6, 7, 8, 9}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 12, 11}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
bool a = true;

void setup()
{
  lcd.begin(LCD_COLS, LCD_ROWS);
  lcd.setCursor(3, 0);
  lcd.print("  PRIYA");
  lcd.setCursor(3, 1);
  lcd.print("ELECTRONICS");
  delay(100);
  for (int positionCounter = 0; positionCounter < 40; positionCounter++)
  {
    lcd.scrollDisplayLeft();
    delay(150);
  }
  delay(800);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Set Count:");
}


void loop()
{
  const byte entryMaxSize = 5;
  static char count[entryMaxSize];

  // index
  static byte x = 0;
  char key = keypad.getKey();

  if (key != NO_KEY) // Check for a valid key.
  {
      switch (key)
    {
      case 'A':
       lcd.clear();
       lcd.setCursor(0,0);
       lcd.print("Set Count:");
        // reset the counter
        x = 0;
        a = true;    
        break;

      case 'D':
      if (a){
        lcd.clear();
        lcd.print("Count Set:");
        for(byte i=0;i<x;i++) {
        lcd.print(count[i]); 
        a = false;
        } 
      }
       break;

      default:
      if (a)
      {
        // if not 5 characters yet
        if (x < entryMaxSize)
        {
          // add key to userinput array and increment counter
          count[x++] = key;
        }
        break;
    }
  }
  }
}

But I am not able to print the digits onto the lcd as I enter them. Only after I press the 'D' key which is the enter key in my case, I am able to see the entire count. Can you suggest something? Thanks.

remove the "if ( a )" condition from the "case 'D' " section of code so it looks like this:

      case 'D':
        lcd.clear();
        lcd.print("Count Set:");
        for(byte i=0;i<x;i++) {
        lcd.print(count[i]);
        a = false;
      }
       break;

and the global variable "a" should be initialised to false, not true as you currently have it.

How do I print the digits as I enter them for setting a count, I've not been able to figure that out?

GautamD:
How do I print the digits as I enter them for setting a count, I've not been able to figure that out?

That appears to me to be so obvious that I fear I must have misunderstood something. Anyway, does this solve your problem ?:

      default:
        if (a)
        {
          // if not 5 characters yet
          if (x < entryMaxSize)
          {
            // add key to userinput array and increment counter
            count[x++] = key;
            Serial.println( key ) ;  // new print statement <<<<<<<<<<<<<<<<
          }
          break;
        }

Thanks alot it does work!! I need to implement a few more things could you help me out with that?

Just keep the questions coming and you will surely get help. Of course, it would be good if you also regard this project as a learning experience and demonstrate some attempts to solve the individual problems yourself.

6v6gt:
Of course, it would be good if you also regard this project as a learning experience and demonstrate some attempts to solve the individual problems yourself.

Surely !! :slight_smile:

Things I want to implement:

  1. If the user presses the key 'D' which is the enter key in our case, lcd must blink invalid count and direct him to the set count option where he gets to enter a valid count.

  2. If user tries to enter the 6th digit while entering the 5 digit count lcd must display "5 digits only!!", while also displaying the count he has entered with only 5 digits. The count would be on the first line and the warning message on the second line.

In the first point I mean to say if enter key is pressed without entering any count.

GautamD:
Surely !! :slight_smile:

  1. If user tries to enter the 6th digit while entering the 5 digit count lcd must display "5 digits only!!", while also displaying the count he has entered with only 5 digits. The count would be on the first line and the warning message on the second line.

I have implemented the following, a little modified though.

default:
        if (a)
        {
          // if not 5 characters yet
          if (x < entryMaxSize)
          {
            // add key to userinput array and increment counter
            count[x++] = key;
            lcd.print( key ) ;  // new print statement <<<<<<<<<<<<<<<<
          }
          else {
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("Only 5 Digits!!");
            lcd.setCursor(0, 1);
            lcd.print("Press A");
          }
        }
          break;
        }
    }
  }

That looks OK for the second part on quick inspection. You may also have to set "a" back to false.

For the first part (zero characters entered), the code should be in case 'D'

6v6gt:
That looks OK for the second part on quick inspection.

OK? So is there a way to make it better?

6v6gt:
You may also have to set "a" back to false.

For the first part (zero characters entered), the code should be in case 'D'

I'll set "a" to false and also try the first part and post the code.

I have implemented the first part where invalid count is displayed if user pressed the enter w/o entering the count.

case 'D':
        if (a) {
          if (x == 0)
          {
            lcd.clear();
            lcd.setCursor(0,0);
            lcd.print("Invalid Count!!");
            lcd.setCursor(0, 1);
            lcd.print("Press A"); // suggesting the user to enter the count again
            a = false;
          }
          else {
            lcd.clear();
            lcd.print("Count Set:");
            for (byte i = 0; i < x; i++) {
              lcd.print(count[i]);
              a = false;
            }
          }
        }
        break;

It works well !

Moving on. I am facing a slight problem while entering the count. Characters on the keypad such as A,B,C,D,# are used for performing certain functions like setting count, enter key, setting time, setting a particular mode of operation. The '*' is going to be used as a decimal point. But while entering the 5 digit count not only numbers from 0 to 9 are taken as input but above characters as well. What shall I do prevent them from being taken as input?

GautamD

You should post your latest code since you have made so many changes since first posting it.

In principle, if you want to accept only digits you can do something like this:

if ( key >= '0' && key <= '9' ) {

    // key is of type char and has a value between 0 and 9 so do something with it.

}

After all the corrections/modifications and additions since original post until post 18, following is the code.

#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header

hd44780_I2Cexp lcd; // declare lcd object: auto locate & config exapander chip

// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;

#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {6, 7, 8, 9}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 12, 11}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
bool a = true;

void setup()
{
  lcd.begin(LCD_COLS, LCD_ROWS);
  lcd.setCursor(3, 0);
  lcd.print("  PRIYA");
  lcd.setCursor(3, 1);
  lcd.print("ELECTRONICS");
  delay(100);
  for (int positionCounter = 0; positionCounter < 40; positionCounter++)
  {
    lcd.scrollDisplayLeft();
    delay(150);
  }
  delay(800);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Set Count:");
}


void loop()
{
  const byte entryMaxSize = 5;
  static char count[entryMaxSize];

  // index
  static byte x = 0;
  char key = keypad.getKey();

  if (key != NO_KEY) // Check for a valid key.
  {
    switch (key)
    {
      case 'A':
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Set Count:");
        // reset the counter
        x = 0;
        a = true;
        break;

      case 'D':
        if (a) {
          if (x == 0)
          {
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("Invalid Count!!");
            lcd.setCursor(0, 1);
            lcd.print("Press A"); // suggesting the user to enter the count again
            a = false;
          }
          else {
            lcd.clear();
            lcd.print("Count Set:");
            for (byte i = 0; i < x; i++) {
              lcd.print(count[i]);
              a = false;
            }
          }
        }
        break;

      default:
        if (a)
        {
          // if not 5 characters yet
          if (x < entryMaxSize)
          {
            // add key to userinput array and increment counter
            if ( key >= '0' && key <= '9' ) {
              // key is of type char and has a value between 0 and 9 so do something with it.
              count[x++] = key;
              lcd.print( key ) ;  // new print statement <<<<<<<<<<<<<<<<
            }
          }
          else {
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("5 Digits Only!!"); // warning for the user if more than permitted digits are entered
            lcd.setCursor(0, 1);
            lcd.print("Press A"); // suggesting the user to enter the count again
            a = false;
          }
        }
        break;
    }
  }
}

Thanks for all the help @6v6gt :slight_smile: