Arduino nano, 4x4 keypad, 16x2 lcd display

Hi expertsssss!

I am currently working on a school project and I really need some help on my Arduino code.

I am trying to make a money storing system with a keypad, an Arduino nano, an lcd display, and a switch. What I expect is when I press the amount I store, it will add to the total. If I entered something incorrectly, I can minus the amount I just entered. And when I want to restart and save money again, I can press restart to store it again.

#include <LiquidCrystal.h> //Header file for LCD from Arduino - LiquidCrystal
#include <Keypad.h> //Header file for Keypad from https://github.com/Chris--A/Keypad

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

// Define the Keymap
char keys[ROWS][COLS] = {

{‘7’,‘8’,‘9’,‘D’},

{‘4’,‘5’,‘6’,‘C’},

{‘1’,‘2’,‘3’,‘B’},

{’*’,‘0’,’#’,‘A’}

};

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

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

const int rs = 8, en = 9, d4 = 10, d5 = 11, d6 = 12, d7 = 13; //Pins to which LCD is connected
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

long Num1,Num2,Number;
char key,action;
boolean result = false;
int total = 0;

void setup() {
lcd.begin(16, 2); //We are using a 16*2 LCD display
lcd.print(“FAMIBOX”); //Display a intro message
lcd.setCursor(0, 1); // set the cursor to column 0, line 1
lcd.print("~Money for Games!"); //Display a intro message

delay(2000); //Wait for display to show info
lcd.clear(); //Then clean it
}

void loop() {

key = kpd.getKey(); //storing pressed key value in a char

if (key!=NO_KEY)
DetectButtons();

if (result==true)
CalculateResult();

DisplayResult();
}

void DetectButtons()
{
lcd.clear(); //Then clean it

if (key == ‘1’) //If Button 1 is pressed
{Serial.println (“Button 1”);
if (Number==0)
Number=1;
else
Number = (Number*10) + 1; //Pressed twice
}

if (key == ‘4’) //If Button 4 is pressed
{Serial.println (“Button 4”);
if (Number==0)
Number=4;
else
Number = (Number*10) + 4; //Pressed twice
}

if (key == ‘7’) //If Button 7 is pressed
{Serial.println (“Button 7”);
if (Number==0)
Number=7;
else
Number = (Number*10) + 7; //Pressed twice
}

if (key == ‘0’)
{Serial.println (“Button 0”); //Button 0 is Pressed
if (Number==0)
Number=0;
else
Number = (Number*10) + 0; //Pressed twice
}

if (key == ‘2’) //Button 2 is Pressed
{Serial.println (“Button 2”);
if (Number==0)
Number=2;
else
Number = (Number*10) + 2; //Pressed twice
}

if (key == ‘5’)
{Serial.println (“Button 5”);
if (Number==0)
Number=5;
else
Number = (Number*10) + 5; //Pressed twice
}

if (key == ‘8’)
{Serial.println (“Button 8”);
if (Number==0)
Number=8;
else
Number = (Number*10) + 8; //Pressed twice
}

if (key == ‘#’)
{Serial.println (“Subtråction”); action = ‘-’;Num1 = Number;
Number =0; }

if (key==’*’) //
{Serial.println (“Addition”); action = ‘+’; Num1 = Number;
Number =0;}

if (key == ‘3’)
{Serial.println (“Button 3”);
if (Number==0)
Number=3;
else
Number = (Number*10) + 3; //Pressed twice
}

if (key == ‘6’)
{Serial.println (“Button 6”);
if (Number==0)
Number=6;
else
Number = (Number*10) + 6; //Pressed twice
}

if (key == ‘9’)
{Serial.println (“Button 9”);
if (Number==0)
Number=9;
else
Number = (Number*10) + 9; //Pressed twice
}

if (key == ‘A’ || key == ‘B’ || key == ‘C’ || key == ‘D’) //Detecting Buttons on Column 4
{
Num1 = Number;
Number =0;
if (key == ‘D’)
{Serial.println (“Button Equal”); Num2=Number;
result = true;}

if (key == ‘C’)
{Serial.println (“Button Cancel”); Number=Num1=Num2=0; result=false;}

delay(100);
}

}

void CalculateResult()
{
if (action==’+’)
Number = Num1+Num2;

if (action==’-’)
Number = Num1-Num2;

}

void DisplayResult()
{
lcd.setCursor(0, 0); // set the cursor to column 0, line 1
lcd.print(Num1); lcd.print(action); lcd.print(Num2);

if (result==true)
{lcd.print(" ="); lcd.print(Number);} //Display the result

lcd.setCursor(0, 1); // set the cursor to column 0, line 1
lcd.print(Number); //Display the result
}

Above is my code. However, the adding and subtraction action only worked once and I haven’t succeeded adding up the total number. I have no idea where to insert the ‘total’ variable.

Take a look at Keypad data entry for techniques using the Keypad and Read this before posting a programming question on how to post code properly

Code tags look like this…
[​code][​/code]

This sequence…

if (key == '1') //If Button 1 is pressed
    {Serial.println ("Button 1"); 
    if (Number==0)
    Number=1;
    else
    Number = (Number*10) + 1; //Pressed twice
    }
    ....etc for every digit

Can be much simplified…

if (key >= '0' && key <= '9') //If digit Button is pressed
{
     Serial.print("Button "); 
    Serial.println(key);
    Number = Number * 10 + (key - '0');
 }

Variable names like “Number” and “Num1” “Num2” aren’t very helpful.
They’re integers, of course they are numbers.

Try renaming them with meaningful names.
“EnteredAmount” and “TotalAmount” might be a good start.

Then it should be clear that using the same variable, “Number”, for both the “EnteredAmount” and the “TotalAmount” is not very helpful. In fact some may say that way insanity lies...

I would have made my input routine return a negative number in “EnteredAmount”, rather than using the flag ‘action’, but if you really want to do it that way CalculateResult then becomes...

void CalculateResult()
{
  if (action=='+')
    TotalAmount += EnteredAmount;

  if (action=='-')
    TotalAmount -= EnteredAmount;

}

Oh and...

void DisplayResult()
{
  lcd.setCursor(0, 0);   // set the cursor to column 0, line 1
  lcd.print(PreviousTotalAmount); lcd.print(action); lcd.print(EnteredAmount); 
  
  if (result==true)
  {
    lcd.print(" ="); lcd.print(TotalAmount); //Display the result
  }
  
  lcd.setCursor(0, 1);   // set the cursor to column 0, line 1
  lcd.print(TotalAmount); //Display the result
}

I’ll leave it up to you to work out where to set variable PreviousTotalAmount and what to.
The name should give you a clue.

Should the variables be set under "long" ?

meaning I keep this?

long TotalAmount, PreviousTotalAmount, EnteredAmount;
char key,action;
boolean result = false;

Hi, anyone has these three components at home and can do me a flavor to check whether my program is working correctly?

My project is due tomorrow and I have to complete an Arduino program to make sure it works during tomorrow’s presentation. However, my Arduino nano board suddenly stopped function I guess probably due to overheating and I desperately need help from others.

Please find attached my program. I am trying to make a money sorting program which I will input the amount of money stored and have the total amount added up.

Project.ino (4.46 KB)

Please post your code.
In code tags, of course.

  if (result == true)
    CalculateResult();
  DisplayResult();

Which function or functions should be called if result is true ?

Duplicate topics merged

Why did yo start a second one ?

#include <LiquidCrystal.h> //Header file for LCD from https://www.arduino.cc/en/Reference/LiquidCrystal
#include <Keypad.h> //Header file for Keypad from https://github.com/Chris--A/Keypad

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

// Define the Keymap
char keys[ROWS][COLS] = {

  {'7','8','9','D'},

  {'4','5','6','C'},

  {'1','2','3','B'},

  {'*','0','#','A'}

};

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

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

const int rs = 8, en = 9, d4 = 10, d5 = 11, d6 = 12, d7 = 13; //Pins to which LCD is connected
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

 long TotalAmount, PreviousTotalAmount, EnteredAmount;
 char key,action;   
 boolean result = false;
 
void setup() {
  lcd.begin(16, 2); //We are using a 16*2 LCD display
  lcd.print("FAMIBOX"); //Display a intro message
  lcd.setCursor(0, 1);   // set the cursor to column 0, line 1
  lcd.print("~Money for Games!"); //Display a intro message 

   delay(2000); //Wait for display to show info
    lcd.clear(); //Then clean it
}

void loop() {
  
key = kpd.getKey(); //storing pressed key value in a char

if (key!=NO_KEY)
DetectButtons();

if (result==true)
CalculateResult();

DisplayResult();   
}

void DetectButtons()
{ 
     lcd.clear(); //Then clean it
     
       if (key=='*') //
    {Serial.println ("Addition"); action = '+'; PreviousTotalAmount= TotalAmount;}
    
     if (key == '1') //If Button 1 is pressed
    {Serial.println ("Button 1"); 
    if (EnteredAmount==0)
    EnteredAmount=1;
    else
    EnteredAmount = (EnteredAmount*10) + 1; //Pressed twice
    }
    
     if (key == '4') //If Button 4 is pressed
    {Serial.println ("Button 4"); 
    if (EnteredAmount==0)
    EnteredAmount=4;
    else
    EnteredAmount = (EnteredAmount*10) + 4; //Pressed twice
    }
    
     if (key == '7') //If Button 7 is pressed
    {Serial.println ("Button 7");
    if (EnteredAmount==0)
    EnteredAmount=7;
    else
    EnteredAmount = (EnteredAmount*10) + 7; //Pressed twice
    } 
  

    if (key == '0')
    {Serial.println ("Button 0"); //Button 0 is Pressed
    if (EnteredAmount==0)
    EnteredAmount=0;
    else
    EnteredAmount = (EnteredAmount*10) + 0; //Pressed twice
    }
    
     if (key == '2') //Button 2 is Pressed
    {Serial.println ("Button 2"); 
     if (EnteredAmount==0)
    EnteredAmount=2;
    else
    EnteredAmount = (EnteredAmount*10) + 2; //Pressed twice
    }
    
     if (key == '5')
    {Serial.println ("Button 5"); 
     if (EnteredAmount==0)
    EnteredAmount=5;
    else
    EnteredAmount = (EnteredAmount*10) + 5; //Pressed twice
    }
    
     if (key == '8')
    {Serial.println ("Button 8"); 
     if (EnteredAmount==0)
    EnteredAmount=8;
    else
    EnteredAmount = (EnteredAmount*10) + 8; //Pressed twice
    }   

    if (key == '#')
    {Serial.println ("Subtråction");  action = '-'; PreviousTotalAmount= TotalAmount;}
    
     if (key == '3')
    {Serial.println ("Button 3"); 
     if (EnteredAmount==0)
    EnteredAmount=3;
    else
    EnteredAmount = (EnteredAmount*10) + 3; //Pressed twice
    }
    
     if (key == '6')
    {Serial.println ("Button 6"); 
    if (EnteredAmount==0)
    EnteredAmount=6;
    else
    EnteredAmount = (EnteredAmount*10) + 6; //Pressed twice
    }
    
     if (key == '9')
    {Serial.println ("Button 9");
    if (EnteredAmount==0)
    EnteredAmount=9;
    else
    EnteredAmount = (EnteredAmount*10) + 9; //Pressed twice
    }  
    

      if (key == 'A' || key == 'B' || key == 'C' || key == 'D') //Detecting Buttons on Column 4
  {

    if (key == 'C')
     {Serial.println ("Button Cancel"); PreviousTotalAmount= EnteredAmount= TotalAmount= 0; result=false;}

     if (key == 'D')
    {Serial.println ("Button Equal");result = true;}  

    
    delay(100);
  }
  
}

void CalculateResult()
{
  if (action=='+')
    TotalAmount = PreviousTotalAmount+ EnteredAmount;

  if (action=='-')
    TotalAmount = PreviousTotalAmount- EnteredAmount;

}

void DisplayResult()
{
  lcd.setCursor(0, 0);   // set the cursor to column 0, line 1
  lcd.print(PreviousTotalAmount); lcd.print(action); lcd.print(EnteredAmount);
 
  if (result==true)
  {
    lcd.print(" ="); lcd.print(TotalAmount); //Display the result
  }
  
   lcd.setCursor(0, 1);   // set the cursor to column 0, line 1
  lcd.print(TotalAmount); //Display the result
}

UKHeliBob:

  if (result == true)

CalculateResult();
 DisplayResult();



Which function or functions should be called if result is true ?

I think it should be CalculateResult then Display Result.

If you want addition, why test for asterisk?
Why not simply change the asterisk key table entry to be a plus sign?
Ditto # and subtraction

I think it should be CalculateResult then Display Result.

From the names of the functions so do I, but that is not what the code currently does

At the moment CalculateResult () will be called if result is true and DisplayResult() will be called whatever value result has

This, however, would do what you describe

  if (result == true)
  {
      CalculateResult();
      DisplayResult();
  }

Note the addition of { and } to create a block of code

Seems to me…

PreviousTotalAmount = TotalAmount

Really wants to go at the start of function CalcualteResult, and that something then wants to set result=false.

But I’m not entirely sure what the flag “result” is meant to indicate. It seems to be serving dual purpose…

  1. Does it signify that entry of a NumberEntered is complete, and so the number entered needs to be added to TotalAmount (i.e. it triggers a one off call to CalculateResult)?

  2. Or does it indicate some different way the data should be displayed on the LCD by DisplayResult once a value is entered?

If 1, then something needs to reset the flag, otherwise the entered number will be repeatedly added to the total erroneously.
If 2, then the flag needs to remain set, otherwise the display will not be as required once a number is entered.

These two uses of the same flag seem to be in conflict with each other.

Also the whole checking Number == 0 thing. When Number == 0 you are aware that Number = X yields the same result as Number = Number * 10 + X, aren’t you?

pcbbc:
Seems to me....

PreviousTotalAmount = TotalAmount

Really wants to go at the start of function CalcualteResult, and that something then wants to set result=false.

But I’m not entirely sure what the flag “result” is meant to indicate. It seems to be serving dual purpose...

  1. Does it signify that entry of a NumberEntered is complete, and so the number entered needs to be added to TotalAmount (i.e. it triggers a one off call to CalculateResult)?

  2. Or does it indicate some different way the data should be displayed on the LCD by DisplayResult once a value is entered?

If 1, then something needs to reset the flag, otherwise the entered number will be repeatedly added to the total erroneously.
If 2, then the flag needs to remain set, otherwise the display will not be as required once a number is entered.

These two uses of the same flag seem to be in conflict with each other.

Also the whole checking Number == 0 thing. When Number == 0 you are aware that Number = X yields the same result as Number = Number * 10 + X, aren’t you?

Yes so the PreviousTotalAmount indicates the money stored starting from $0. When people start putting money into let say the coin box, they input the amount they store, for example, $5. They press the "add" button and press the "equal" button. Now the program will calculate a TotalAmount. The TotalAmount will stay as long as nothing else is input. However, when you try adding another value, I want the PreviousTotalAmount to appear and the new EnteredAmount added to it.

So the display will look like this:

0+5=5. (press "+" -> press"5" -> press "=")
5+10=10 (press "+" -> press "1" -> press "0" -> press"=")

I guess the Number = Number * 10 + X is for entering two-digit amount.

I also add the subtraction button in order to remedy the wrong entry. For example, if you entered the wrong amount, let say I want to input $56 but I pressed $53, you can fix the balance quickly.

Besides, I wanted the cancel all button so that the amount stored can be reset to zero once the saving is used