Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 2 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
Hand tools and fabrication machines | ||||||
| ||||||
|
Wiring diagram:
What does the project do so far?
The keypad outputs three inputs depending on what the user typed: two one-digit numbers and an operator; from there the Arduino does the calculations and displays it on the LCD.
How does it do this?
On the software side, I have explained this in-depth in the annotations of the code, but quite simply using a combination of for statements, while statements and some arrays the Arduino will go through and store inputs. If some people, after reading the code annotations, are still confused I will be happy to explain it further in the comments.
On the hardware side, there is more than enough documentation on how matrix keypads and LCD's work, soooo..... use google. However, I'd like to add when researching for the project, I found, for some odd reason, many beginners trying to do this project and failing to even install the library: please if you are a beginner and cannot yet program to debounce buttons etc, donotdo this project unless you already have experience in coding, this is not a beginner friendly project.
What are the goals for the future?
The aim is for the circuit to one day accept two-digit or more figured numbers and perform operations using multiple operators as well as other operations like root or power. Unfortunately, I barely was able to code parts of this project, so I had to turn to my friend or more commonly known super-genius, who was able to do so: now I understand how it works but need a break from this project, maybe in the coming months of 2021 I will revist the project and with greater knowledge be able to do so.
Why did I make this?
Essentially to consolidate knowledge learnt about matrix keypads, LCD's and for a bit of fun to pass this lockdown we are experiencing currently all over the world. Also, I am relatively new to this world of engineering and Arduino(forgive me if this is a poorly written project, I am new, any constructive criticism is appreciated) so I though this would be fun to try and prove myself.
Image of Math calculator
C/C++#include <LiquidCrystal.h>//including the LCD libary for the project
#include <Keypad.h> //including the keypad libary for the project
LiquidCrystal lcd(A0, A1, A2, A3, A4, A5);
const byte ROWS = 4; //setting the amount of rows on the keypad
const byte COLM = 4; //setting the amount of columns on the keypad
char keys[ROWS][COLM] = //setting the keys depending on the number of rows and colums
{
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {13, 12, 11, 10}; //defining the letters to GPIO pins of Arduino
byte colmPins[COLM] = {9, 8, 7, 6};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colmPins, ROWS, COLM); //compiles all the arrays to create a keypad object
float inputs[2]; //array used to store inputs entered by user for two numbers
bool inputs_entered[2]; //array used for Arduino to see whether two inputs have been entered
bool inputs_displayed[2]; //array used to inform Arduino whether the typed information has been printed
char arithmetic_op; //character datatype used to store input entered by user for operation
bool arithmetic_op_entered = false; //boolean datatype used for Arduino to see whether the input has been entered
bool arithmetic_op_displayed = false; //boolean datatype used to inform Arduino whether the typed information has been printed
void setup() {
Serial.begin(9600); //opening the serial communication channel at baud rate 9600(9600 bits)
lcd.begin(16,2); //setting up the LCD's number of columns and rows
lcd.setCursor(0,0);
lcd.print("Math calculator");
delay(1000);
lcd.clear();
ResetValues(); //function for resetting value
Calculator(); //function for calculating answer and displaying the result
}
void loop() {} //void loop is not being used but has to be kept in sketch for....well reasons
void ResetValues() //function for resetting value
{
for (int i = 0; i < 2; i++) //for statement that runs whatever in the curly brackets twice; creates integer variable iteration(i), if (i) is less than 2[do whatever], add 1 to i
{
inputs_entered[i] = false; //inside the array, depending on the iteration, change the value(true) to false(as the iteraton increments so does the value being checked so both values are made false for resetting everything
inputs_displayed[i] = false; //once again(look above) resetting the value
inputs[i] = 0; //as this is a float, we cannot say false or true so instead we just set it back to 0 as a way to flush the value
}
arithmetic_op = NULL; // as it is a charcter, we cannot change the value inside to true or 0, instead null(in my opinion a form of saying no value, it's undefined, etc)
arithmetic_op_entered = false; //similar to above we are simply resetting the values and whether they have been entered
arithmetic_op_displayed = false; //resetting value
}
void Calculator()
{
ResetValues();//function for resetting
GetInputs(); //function for getting value from keypad
GetOperator();//function for getting operator value from keypad
switch (arithmetic_op) { //plugging operator from GetOperator function via a switch statement to complete functions
case 'A':
lcd.print(inputs[0] + inputs[1]);
delay(1000);
lcd.clear();
break;
case 'B':
lcd.print(inputs[0] - inputs[1]);
delay(1000);
lcd.clear();
break;
case 'C':
lcd.print(inputs[0] * inputs[1]);
delay(1000);
lcd.clear();
break;
case 'D':
lcd.print(inputs[0] / inputs[1]);
delay(1000);
lcd.clear();
break;
}
delay(100); //delay for 100 miliseconds
Serial.flush(); //flush potentional values from serial monitor
Calculator(); //calling function again, [looping]
}
void GetInputs() //function for getting inputs
{
while (!inputs_entered[0]) { //whilst inputs entered(variable used to store whether two values have been entered) is false
for (int i = 0; i < 2; i++) //looping contents twice as shown before(you may be asking how we are using the same variable again, we are not, this is a local variable not global, so we can use the same name again, further help in comments)
{
if (!inputs_entered[i] && !inputs_displayed[i]) //if inputs entered and inputs displayed are false
{
lcd.print("Input " + String(i) + ": "); //displaying what input it is for the number is via using the iteration from the for loop
inputs_displayed[i] = true; //setting display value to true, we have completed printing a line of input 1 or 2
while (!inputs_entered[i]) // if inputs_entered(from the two values inside) is false, get values
{
char customKey = keypad.getKey(); //getting value from keypad
if (customKey != NO_KEY) // if there is a output which is not a blank space(a keypad outputs responses even if there is no button press, resulting in "empty" values) we get around this via using this "function"
{
customKey = convertValues(customKey); //as the value outputed is a character, in order to do arithmetic calculations, we must convert it to a integer
inputs[i] = customKey; //depending on what iteration we are on add the corrosponding letter to the inputs array
lcd.print(inputs[i]); //printing the value
delay(1000);
lcd.clear();
inputs_entered[i] = true; //in the array depending on what iteration set the value to true as the process has been completed
}
}
}
}
}
}
void GetOperator()//function for getting operator
{
while (!arithmetic_op_entered) { //process is very similar to above in getting two values to perform arithmetic operations(if anyone is confused, don't hesitate to comment)
if (!arithmetic_op_entered && !arithmetic_op_displayed)
{
lcd.print("Operator: ");
arithmetic_op_displayed = true;
while (!arithmetic_op_entered)
{
char customKey = keypad.getKey();
if (customKey != NO_KEY)
{
arithmetic_op = customKey;
lcd.print(keypad.getKey());
delay(1000);
lcd.clear();
arithmetic_op_entered = true;
}
}
}
}
}
int convertValues(int x) //function used above to convert character value into integer
{
return x - '0'; //returning changed character value now to integer value
}
Image of Math calculator
C/C++#include <LiquidCrystal.h>//including the LCD libary for the project
#include <Keypad.h> //including the keypad libary for the project
LiquidCrystal lcd(A0, A1, A2, A3, A4, A5);
const byte ROWS = 4; //setting the amount of rows on the keypad
const byte COLM = 4; //setting the amount of columns on the keypad
char keys[ROWS][COLM] = //setting the keys depending on the number of rows and colums
{
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {13, 12, 11, 10}; //defining the letters to GPIO pins of Arduino
byte colmPins[COLM] = {9, 8, 7, 6};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colmPins, ROWS, COLM); //compiles all the arrays to create a keypad object
float inputs[2]; //array used to store inputs entered by user for two numbers
bool inputs_entered[2]; //array used for Arduino to see whether two inputs have been entered
bool inputs_displayed[2]; //array used to inform Arduino whether the typed information has been printed
char arithmetic_op; //character datatype used to store input entered by user for operation
bool arithmetic_op_entered = false; //boolean datatype used for Arduino to see whether the input has been entered
bool arithmetic_op_displayed = false; //boolean datatype used to inform Arduino whether the typed information has been printed
void setup() {
Serial.begin(9600); //opening the serial communication channel at baud rate 9600(9600 bits)
lcd.begin(16,2); //setting up the LCD's number of columns and rows
lcd.setCursor(0,0);
lcd.print("Math calculator");
delay(1000);
lcd.clear();
ResetValues(); //function for resetting value
Calculator(); //function for calculating answer and displaying the result
}
void loop() {} //void loop is not being used but has to be kept in sketch for....well reasons
void ResetValues() //function for resetting value
{
for (int i = 0; i < 2; i++) //for statement that runs whatever in the curly brackets twice; creates integer variable iteration(i), if (i) is less than 2[do whatever], add 1 to i
{
inputs_entered[i] = false; //inside the array, depending on the iteration, change the value(true) to false(as the iteraton increments so does the value being checked so both values are made false for resetting everything
inputs_displayed[i] = false; //once again(look above) resetting the value
inputs[i] = 0; //as this is a float, we cannot say false or true so instead we just set it back to 0 as a way to flush the value
}
arithmetic_op = NULL; // as it is a charcter, we cannot change the value inside to true or 0, instead null(in my opinion a form of saying no value, it's undefined, etc)
arithmetic_op_entered = false; //similar to above we are simply resetting the values and whether they have been entered
arithmetic_op_displayed = false; //resetting value
}
void Calculator()
{
ResetValues();//function for resetting
GetInputs(); //function for getting value from keypad
GetOperator();//function for getting operator value from keypad
switch (arithmetic_op) { //plugging operator from GetOperator function via a switch statement to complete functions
case 'A':
lcd.print(inputs[0] + inputs[1]);
delay(1000);
lcd.clear();
break;
case 'B':
lcd.print(inputs[0] - inputs[1]);
delay(1000);
lcd.clear();
break;
case 'C':
lcd.print(inputs[0] * inputs[1]);
delay(1000);
lcd.clear();
break;
case 'D':
lcd.print(inputs[0] / inputs[1]);
delay(1000);
lcd.clear();
break;
}
delay(100); //delay for 100 miliseconds
Serial.flush(); //flush potentional values from serial monitor
Calculator(); //calling function again, [looping]
}
void GetInputs() //function for getting inputs
{
while (!inputs_entered[0]) { //whilst inputs entered(variable used to store whether two values have been entered) is false
for (int i = 0; i < 2; i++) //looping contents twice as shown before(you may be asking how we are using the same variable again, we are not, this is a local variable not global, so we can use the same name again, further help in comments)
{
if (!inputs_entered[i] && !inputs_displayed[i]) //if inputs entered and inputs displayed are false
{
lcd.print("Input " + String(i) + ": "); //displaying what input it is for the number is via using the iteration from the for loop
inputs_displayed[i] = true; //setting display value to true, we have completed printing a line of input 1 or 2
while (!inputs_entered[i]) // if inputs_entered(from the two values inside) is false, get values
{
char customKey = keypad.getKey(); //getting value from keypad
if (customKey != NO_KEY) // if there is a output which is not a blank space(a keypad outputs responses even if there is no button press, resulting in "empty" values) we get around this via using this "function"
{
customKey = convertValues(customKey); //as the value outputed is a character, in order to do arithmetic calculations, we must convert it to a integer
inputs[i] = customKey; //depending on what iteration we are on add the corrosponding letter to the inputs array
lcd.print(inputs[i]); //printing the value
delay(1000);
lcd.clear();
inputs_entered[i] = true; //in the array depending on what iteration set the value to true as the process has been completed
}
}
}
}
}
}
void GetOperator()//function for getting operator
{
while (!arithmetic_op_entered) { //process is very similar to above in getting two values to perform arithmetic operations(if anyone is confused, don't hesitate to comment)
if (!arithmetic_op_entered && !arithmetic_op_displayed)
{
lcd.print("Operator: ");
arithmetic_op_displayed = true;
while (!arithmetic_op_entered)
{
char customKey = keypad.getKey();
if (customKey != NO_KEY)
{
arithmetic_op = customKey;
lcd.print(keypad.getKey());
delay(1000);
lcd.clear();
arithmetic_op_entered = true;
}
}
}
}
}
int convertValues(int x) //function used above to convert character value into integer
{
return x - '0'; //returning changed character value now to integer value
}
#include <LiquidCrystal.h>//including the LCD libary for the project
#include <Keypad.h> //including the keypad libary for the project
LiquidCrystal lcd(A0, A1, A2, A3, A4, A5);
const byte ROWS = 4; //setting the amount of rows on the keypad
const byte COLM = 4; //setting the amount of columns on the keypad
char keys[ROWS][COLM] = //setting the keys depending on the number of rows and colums
{
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {13, 12, 11, 10}; //defining the letters to GPIO pins of Arduino
byte colmPins[COLM] = {9, 8, 7, 6};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colmPins, ROWS, COLM); //compiles all the arrays to create a keypad object
float inputs[2]; //array used to store inputs entered by user for two numbers
bool inputs_entered[2]; //array used for Arduino to see whether two inputs have been entered
bool inputs_displayed[2]; //array used to inform Arduino whether the typed information has been printed
char arithmetic_op; //character datatype used to store input entered by user for operation
bool arithmetic_op_entered = false; //boolean datatype used for Arduino to see whether the input has been entered
bool arithmetic_op_displayed = false; //boolean datatype used to inform Arduino whether the typed information has been printed
void setup() {
Serial.begin(9600); //opening the serial communication channel at baud rate 9600(9600 bits)
lcd.begin(16,2); //setting up the LCD's number of columns and rows
lcd.setCursor(0,0);
lcd.print("Math calculator");
delay(1000);
lcd.clear();
ResetValues(); //function for resetting value
Calculator(); //function for calculating answer and displaying the result
}
void loop() {} //void loop is not being used but has to be kept in sketch for....well reasons
void ResetValues() //function for resetting value
{
for (int i = 0; i < 2; i++) //for statement that runs whatever in the curly brackets twice; creates integer variable iteration(i), if (i) is less than 2[do whatever], add 1 to i
{
inputs_entered[i] = false; //inside the array, depending on the iteration, change the value(true) to false(as the iteraton increments so does the value being checked so both values are made false for resetting everything
inputs_displayed[i] = false; //once again(look above) resetting the value
inputs[i] = 0; //as this is a float, we cannot say false or true so instead we just set it back to 0 as a way to flush the value
}
arithmetic_op = NULL; // as it is a charcter, we cannot change the value inside to true or 0, instead null(in my opinion a form of saying no value, it's undefined, etc)
arithmetic_op_entered = false; //similar to above we are simply resetting the values and whether they have been entered
arithmetic_op_displayed = false; //resetting value
}
void Calculator()
{
ResetValues();//function for resetting
GetInputs(); //function for getting value from keypad
GetOperator();//function for getting operator value from keypad
switch (arithmetic_op) { //plugging operator from GetOperator function via a switch statement to complete functions
case 'A':
lcd.print(inputs[0] + inputs[1]);
delay(1000);
lcd.clear();
break;
case 'B':
lcd.print(inputs[0] - inputs[1]);
delay(1000);
lcd.clear();
break;
case 'C':
lcd.print(inputs[0] * inputs[1]);
delay(1000);
lcd.clear();
break;
case 'D':
lcd.print(inputs[0] / inputs[1]);
delay(1000);
lcd.clear();
break;
}
delay(100); //delay for 100 miliseconds
Serial.flush(); //flush potentional values from serial monitor
Calculator(); //calling function again, [looping]
}
void GetInputs() //function for getting inputs
{
while (!inputs_entered[0]) { //whilst inputs entered(variable used to store whether two values have been entered) is false
for (int i = 0; i < 2; i++) //looping contents twice as shown before(you may be asking how we are using the same variable again, we are not, this is a local variable not global, so we can use the same name again, further help in comments)
{
if (!inputs_entered[i] && !inputs_displayed[i]) //if inputs entered and inputs displayed are false
{
lcd.print("Input " + String(i) + ": "); //displaying what input it is for the number is via using the iteration from the for loop
inputs_displayed[i] = true; //setting display value to true, we have completed printing a line of input 1 or 2
while (!inputs_entered[i]) // if inputs_entered(from the two values inside) is false, get values
{
char customKey = keypad.getKey(); //getting value from keypad
if (customKey != NO_KEY) // if there is a output which is not a blank space(a keypad outputs responses even if there is no button press, resulting in "empty" values) we get around this via using this "function"
{
customKey = convertValues(customKey); //as the value outputed is a character, in order to do arithmetic calculations, we must convert it to a integer
inputs[i] = customKey; //depending on what iteration we are on add the corrosponding letter to the inputs array
lcd.print(inputs[i]); //printing the value
delay(1000);
lcd.clear();
inputs_entered[i] = true; //in the array depending on what iteration set the value to true as the process has been completed
}
}
}
}
}
}
void GetOperator()//function for getting operator
{
while (!arithmetic_op_entered) { //process is very similar to above in getting two values to perform arithmetic operations(if anyone is confused, don't hesitate to comment)
if (!arithmetic_op_entered && !arithmetic_op_displayed)
{
lcd.print("Operator: ");
arithmetic_op_displayed = true;
while (!arithmetic_op_entered)
{
char customKey = keypad.getKey();
if (customKey != NO_KEY)
{
arithmetic_op = customKey;
lcd.print(keypad.getKey());
delay(1000);
lcd.clear();
arithmetic_op_entered = true;
}
}
}
}
}
int convertValues(int x) //function used above to convert character value into integer
{
return x - '0'; //returning changed character value now to integer value
}
Comments