Saving keypad input and displaying it

Hello,

I'm trying to make a big project where a user needs to input a 12 digit number using a keypad and then save that number into a variable for later use.

For now, i managed to write a code that takes the input from the user and then display it on LCD screen.
The code worked to be showing the number while inputing 10 digits and then when the user clicks on * or #, the LCD will show a message declaring the number

My problem is that whenever i enter more than 10 digits something happens and a totally different number appears,

I would really appreciate it if someone can help me figure out this problem

Here is my Code

#include <SoftwareSerial.h> 
#include <String.h> 
#include <LiquidCrystal.h>
#include <Keypad.h> 



const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns

char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3}; //connect to the column pinouts of the keypad

LiquidCrystal lcd(A0, A1, A2, A3, A4, A5); //connecting the lcd
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );  


void setup() {
  // Setup size of LCD 20 characters and 4 lines
  lcd.begin(20, 4);
  lcd.setCursor(1,2);
  lcd.setCursor(4,3);
  lcd.setCursor(0,0);
  Serial.begin(9600);
}


////////////////////////

unsigned long getKeypadIntegerMulti()
{
  unsigned long IC = 0;                                // the number accumulator
  unsigned long keyvalue;                              // the key pressed at current moment
  int isnum;
  do
  {
    keyvalue = kpd.getKey();                              // input the key
    isnum = (keyvalue >= '0' && keyvalue <= '9');        // is it a digit?
    if (isnum)                                          // if it is a digit then do this          
    {
      lcd.print(keyvalue - '0');
      IC = (IC * 10) + keyvalue - '0';               // accumulate the input number
    }
  } while (isnum || !keyvalue);                  // until not a digit or while no key pressed
 
  lcd.clear();
  lcd.print("Returning from funtion: "); 
  lcd.println(IC);
  return IC;

}

void loop() 
{
   int val= getKeypadIntegerMulti(); 
    Serial.println("Value is");
    Serial.println(val);
   delay(2500);
}  
1 Like

Your function, getKeypadIntegerMulti() returns an 'unsigned long' value, but you try to assign that to an 'int' within loop().

Mind your variable types and the sizes they can hold.

Arduino data types.

i did check this and Long is the one with largest storage limit

so long is not enough to store the whole 12 digits,
I just couldn't do it within loop(), can you give an example on how to do that?

The 32-bit 'unsigned long' can store a little more than 4.2 billion (4,200,000,000, so about 9.5 digits).

You can use a 64-bit 'long long' for about 18 digits but the .print() function isn't set up to print 'long long' numbers. You would have to pull the number apart digit-by-digit to print it:

  unsigned long long IC;
.
.
.
  char digits[22];
  int index = 21;
  digits[index--] = '\0'; // Null terminator

  // Take the rightmost digit, even if it's 0;
  digits[index--] = (IC % 10) + '0';
  IC /= 10;

  // Take all the remaining digits
  while (IC != 0)
  {
    digits[index--] = (IC % 10) + '0';
    IC /= 10;
  }

  // Print the string from the buffer.
  Serial.print(&digits[index+1]);
1 Like

Thank you it worked, it can be displayed now

This is going to display the 12 digits, but how can i save these 12 digits as a variable for later use
If it is saved in the IC variable then i cannot use it in the void loop() because the IC is just a part of the big function which is the getKeypadIntegerMulti()

Here is the code looks like now

#include <SoftwareSerial.h> 
#include <String.h> 
#include <LiquidCrystal.h>
#include <Keypad.h> 



const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns

char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3}; //connect to the column pinouts of the keypad

LiquidCrystal lcd(A0, A1, A2, A3, A4, A5); //connecting the lcd
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );  


void setup() {
  // Setup size of LCD 20 characters and 4 lines
  lcd.begin(20, 4);
  lcd.setCursor(1,2);
  lcd.setCursor(4,3);
  lcd.setCursor(0,0);
  Serial.begin(9600);
}


////////////////////////

long long getKeypadIntegerMulti()
{
  long long IC = 0;                                // the number accumulator
  long keyvalue;                              // the key pressed at current moment
  int isnum;
  do
  {
    keyvalue = kpd.getKey();                              // input the key
    isnum = (keyvalue >= '0' && keyvalue <= '9');        // is it a digit?
    if (isnum)                                          // if it is a digit then do this          
    {
      lcd.print(keyvalue - '0');
      IC = (IC * 10) + keyvalue - '0';               // accumulate the input number
    }
  } while (isnum || !keyvalue);                  // until not a digit or while no key pressed
  char digits[22];
  int index = 21;
  digits[index--] = '\0'; // Null terminator

  // Take the rightmost digit, even if it's 0;
  digits[index--] = (IC % 10) + '0';
  IC /= 10;

  // Take all the remaining digits
  while (IC != 0)
  {
    digits[index--] = (IC % 10) + '0';
    IC /= 10;
  }
  // Print the string from the buffer.
  Serial.print(&digits[index+1]); 
  lcd.clear();
  lcd.print("The value is: ");
  lcd.print(&digits[index+1]);
  return IC;
}

void loop() 
{
   int val= getKeypadIntegerMulti(); 
    Serial.println(" Value is");
    Serial.println(val);
   delay(2500);
}  

the 12 digits are displayed but in the loop the val is displayed as 0
the serial.print in the void loop() here is just my way to know that this variable is saved as i want it to be. am i doing this wrong ?
In fact, my project aims to take this 12 digit and upload it to a php file later (this is not the issue for now)

You are trying to store a 64 bit integer into a 16 bit integer. It will not work very well. Try to change

int val= getKeypadIntegerMulti(); 

to

long long int val= getKeypadIntegerMulti(); 

I did use the long long and modified the code to print accourdingly, it is still 0

He has already explained.

i need to use the 12 digits in another function so it must be saved as a variable.
The thing is: i thought i saved these 12 digits into the getKeypadIntegerMulti() and so i can use it later, but when i tried to use it in the loop it turned out to be 0.
That is where i'm being confused. I'm new to programming arduino and i don't have much knowledge

It value has stored correctly.
The implication of his explanation is you can't just use it in .print() or .println().
This is a .print() or .println() specification, not a problem with your code.
In addition, I don't know if another function you say can operate "long long" too.

i used the same function as it was suggested earlier and it is still zero

here is my code until now

#include <SoftwareSerial.h> 
#include <String.h> 
#include <LiquidCrystal.h>
#include <Keypad.h> 



const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns

char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3}; //connect to the column pinouts of the keypad

LiquidCrystal lcd(A0, A1, A2, A3, A4, A5); //connecting the lcd
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );  


void setup() {
  // Setup size of LCD 20 characters and 4 lines
  lcd.begin(20, 4);
  lcd.setCursor(1,2);
  lcd.setCursor(4,3);
  lcd.setCursor(0,0);
  Serial.begin(9600);
}



long long getKeypadIntegerMulti()
{
  long long IC = 0;                                // the number accumulator
  long keyvalue;                              // the key pressed at current moment
  int isnum;
  do
  {
    keyvalue = kpd.getKey();                              // input the key
    isnum = (keyvalue >= '0' && keyvalue <= '9');        // is it a digit?
    if (isnum)                                          // if it is a digit then do this          
    {
      lcd.print(keyvalue - '0');
      IC = (IC * 10) + keyvalue - '0';               // accumulate the input number
    }
  } while (isnum || !keyvalue);                  // until not a digit or while no key pressed
  char digits[22];
  int index = 21;
  digits[index--] = '\0'; // Null terminator

  // Take the rightmost digit, even if it's 0;
  digits[index--] = (IC % 10) + '0';
  IC /= 10;

  // Take all the remaining digits
  while (IC != 0)
  {
    digits[index--] = (IC % 10) + '0';
    IC /= 10;
  }
  // Print the string from the buffer.
  Serial.print("The value inside the function is:");
  Serial.print(&digits[index+1]); 
  lcd.clear();
  lcd.print("The value is: ");
  lcd.print(&digits[index+1]);
  return IC;
}

void loop() 
{
   long long val= getKeypadIntegerMulti(); 
    Serial.println(" Value in the loop is");
    char digits[22];
  int index = 21;
  digits[index--] = '\0'; // Null terminator

  // Take the rightmost digit, even if it's 0;
  digits[index--] = (val % 10) + '0';
  val /= 10;

  // Take all the remaining digits
  while (val != 0)
  {
    digits[index--] = (val % 10) + '0';
    val /= 10;
  }
  // Print the string from the buffer.
  Serial.print(&digits[index+1]); 
   
 
   delay(2500);
}  

and here is a picture that shows the serial monitor and the lcd (i'm simulating it for now), the digits can be printed on the lcd but they are not saved as a variable

You are changing the "IC" value in a function is operating.
At the time of return, the 12-digit number is not left in the contents of the variables "IC".

Since you are destroying the value if IC while printing it, turn the printing into its own function. Same for printing it to the lcd

#include <SoftwareSerial.h>
#include <String.h>
#include <LiquidCrystal.h>
#include <Keypad.h>



const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns

char keys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3}; //connect to the column pinouts of the keypad

LiquidCrystal lcd(A0, A1, A2, A3, A4, A5); //connecting the lcd
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );


void setup() {
  // Setup size of LCD 20 characters and 4 lines
  lcd.begin(20, 4);
  lcd.setCursor(1, 2);
  lcd.setCursor(4, 3);
  lcd.setCursor(0, 0);
  Serial.begin(9600);
}



long long getKeypadIntegerMulti()
{
  long long IC = 0;                                // the number accumulator
  long keyvalue;                              // the key pressed at current moment
  int isnum;
  do
  {
    keyvalue = kpd.getKey();                              // input the key
    isnum = (keyvalue >= '0' && keyvalue <= '9');        // is it a digit?
    if (isnum)                                          // if it is a digit then do this
    {
      lcd.print(keyvalue - '0');
      IC = (IC * 10) + keyvalue - '0';               // accumulate the input number
    }
  } while (isnum || !keyvalue);                  // until not a digit or while no key pressed

  // Print the string from the buffer.
  Serial.print("The value inside the function is:");
  printLL(IC);
  lcd.clear();
  lcd.print("The value is: ");
  LCDPrintLL(IC);
  return IC;
}

void loop()
{
  long long val = getKeypadIntegerMulti();
  Serial.println(" Value in the loop is: ");
  printLL(val);
  delay(2500);
}

void printLL(long long val) {
  char digits[22];
  int index = 21;
  digits[index--] = '\0'; // Null terminator

  // Take the rightmost digit, even if it's 0;
  digits[index--] = (val % 10) + '0';
  val /= 10;

  // Take all the remaining digits
  while (val != 0) {
    digits[index--] = (val % 10) + '0';
    val /= 10;
  }
  // Print the string from the buffer.
  Serial.print(&digits[index + 1]);
}

void LCDPrintLL(long long val) {
  char digits[22];
  int index = 21;
  digits[index--] = '\0'; // Null terminator

  // Take the rightmost digit, even if it's 0;
  digits[index--] = (val % 10) + '0';
  val /= 10;

  // Take all the remaining digits
  while (val != 0) {
    digits[index--] = (val % 10) + '0';
    val /= 10;
  }
  // Print the string from the buffer.
  lcd.print(&digits[index + 1]);
}
3 Likes

That's smart, It worked just as i wanted it to do

Thank you so much and thanks to everyone who helped

1 Like

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.