#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
#include <string.h>
//set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);
//KEYPAD SETUP
const uint8_t ROWS = 4;
const uint8_t COLS = 4;
char keys[ROWS][COLS] = {
{ '1', '2', '3', 'O' },
{ '4', '5', '6', '+' },
{ '7', '8', '9', '-' },
{ '.', '0', '=', '*' }
};
uint8_t colPins[COLS] = { 5, 4, 3, 2 }; // C1, C2, C3, C4 pins
uint8_t rowPins[ROWS] = { 9, 8, 7, 6 }; // R1, R2, R3, R4 pins
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
//FUNCTIONS PREINITIALISED
bool isNumber(char);
float executeMaths(String);
void debugPrint(String, String);
void formalise(); //make more local?
void calculate(); //make more local?
//GLOBAL VARIABLES
String tempString; //temporary stored keypresses. Becomes formatted later.
//Formatted string with values. Make local? <><
String numberString = "";
String operandString = "";
bool LCD_on; //State attached to whether screen is on or not
void setup() {
Serial.begin(9600);
lcd.init();
LCD_on = false; //set LCD to be off
}
void LCD_clearRow(String row) {
//clears a row of screen, fills with space char
if (row == "top"){
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
} else if (row == "bottom") {
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
}
return;
}
bool returnResult = false;
void loop() {
char key = keypad.getKey();
if (key != NO_KEY && key != 'O' && LCD_on == true) {
if (returnResult == true){
LCD_clearRow("top");
returnResult = false;
}
lcd.print(key);
lcd.display();
if (key == '=') {
debugPrint(tempString, "tempString");
formalise(); //format tempString raw input
calculate(); //calculate from formatted inputs
returnResult = true;
//Reset all global variables
numberString = "";
operandString = "";
tempString = "";
return;
}
tempString.concat(key);
//concatenate character to end of tempString string
} else if (key == 'O') {
LCD_on = !LCD_on;
if (LCD_on == false) {
lcd.noBacklight();
lcd.noDisplay();
} else {
lcd.backlight();
lcd.display();
}
}
}
bool isNumber(char readChar) {
//Checks if char input is a number or not. 48 represents 0, 57 represents 9.
//46 represents period (.). Returns FALSE if not a number. ASCII code used.
if (readChar >= 48 && readChar <= 57 || readChar == 46) {
return true;
} else {
return false;
}
}
void debugPrint(String printString, String stringName) {
//Prints of a string. Has option to have a custom string as a descriptor for
//readability and clarity
Serial.print(stringName); Serial.print(" is: ");
Serial.println(printString);
return;
}
void formalise() {
bool wasNum = false;
for (int i = 0; i < tempString.length(); i++) {
if (isNumber(tempString[i]) == true) {
//Stores numbers to temporary number string
numberString.concat(tempString[i]);
wasNum = true;
}
else if (isNumber(tempString[i]) == false && wasNum == true) {
//Stores and processes numbers to number string
//Stores and processes operand to operand string
wasNum = false;
operandString.concat(tempString[i]);
numberString.concat('|');
}
else {
Serial.println("Multiple buttons are pressed in a row.");
Serial.println("First operand will be used.");
//Error state when multiple operands are pressed in row.
//Last operand will be used.
}
}
numberString.concat('|'); //Add terminating character
//printing current results
debugPrint(operandString, "operandString");
debugPrint(numberString, "numberString");
}
void calculate() {
float result;
//Result variable - location of calculated result
float numFloat = 0;
//Read float from numberString
int countNum = 0;
//counts how many numbers are being found, used to set first float value
char pastOperand;
//remembers last operand used for operations
String calcNumString = "";
for (int i = 0; i < numberString.length(); i++) {
if (numberString[i] != '|') {
calcNumString.concat(numberString[i]);
} else { //when end of number is reached, format string and do maths.
debugPrint(calcNumString, "calcNumString");
numFloat = calcNumString.toFloat();
calcNumString = "";
//Following code calculates math results.
if (countNum == 0) {
result = numFloat; //first number is saved, skip operand skip
Serial.print("first no: "); Serial.println(result);
pastOperand = operandString[0]; //takes first operand
} else {
switch (pastOperand) {
case '*': // Code for "*" (asterisk)
result = result * numFloat;
break;
case '+': // Code for "+" (plus)
result = result + numFloat;
break;
case '-': // Code for "-" (hyphen)
result = result - numFloat;
break;
}
pastOperand = operandString[countNum];
}
Serial.print("Result is "); Serial.println(result);
countNum++;
}
}
lcd.setCursor(0, 1); //bring cursor down to the bottom
LCD_clearRow("bottom");
lcd.print(result);
lcd.setCursor(0, 0); //reset to origin
}