/* EEE20003 Project Progress - Part 1
Group 39 Project G
Authors: B Horvath, M Mahood, K Rhodes
Program is a calculator that can complete basic operations, being:
- addition, subtraction and multiplication
- taking input of integers or doubles
- can do calculation with previous result (or without)
- can power on and off, clearing when turned off
- can take up to 100 values (+-* count as a value)
*/
#include <LiquidCrystal_I2C.h> //includes library for lcd
#include <EEPROM.h> // include library for EEPROM
//#include <dht.h>
#include <RTClib.h>
LiquidCrystal_I2C lcd(0x27, 20, 4); //Initialises the LCD.
const uint8_t ROWS = 4;
const uint8_t COLS = 7; //gives the keypad 4 rows and 7 columns
char keys[ROWS][COLS] = {
{ '1', '2', '3', '+', 's', 'A', 'B'},
{ '4', '5', '6', '-', 'n', 'C', 'D'},
{ '7', '8', '9', '*', '%', 'E', 'F'},
{ 'P', '0', '.', '/', '=', 'G', 'H'} //specifies the possible 'keys' values, as characters.
};
String userin = ""; //sets userin to be a empty string.
double userinarray[100] = {}; //100 'slot' long array for storing user input.
double hold[100] = {}; //second array for holding user input, when above array is
// being cleared between operations.
int ArraySlot = 0; //array element ('slot') marking variable, used to find specific
// array slots for computation.
bool on = false; //whether or not the LCD is on (serves as a safety).
bool equalsPressed = false; //whether or not the user has pressed equals.
float ans = 0; //the answer for the expression the user has entered; 0 default.
RTC_DS1307 rtc;
int mode = 0;
int mempos = 8; // start position of the memory function
double mem = 0;
void setup() {
Serial.begin(9600);
lcd.begin(16, 2); //specifies width and height of LCD.
lcd.noBacklight(); //turns off the backlight of the LCD.
//set the pins used for interrupts as pullup input pins
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(18, INPUT_PULLUP);
pinMode(19, INPUT_PULLUP);
// iterate through pins used to check button column and set as output and low
for (int pin = 33; pin <= 39 ; pin += 1) {
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
}
// attach interrupts to the row pins to check which row is pressed
attachInterrupt(0, row1, FALLING);
attachInterrupt(1, row2, FALLING);
attachInterrupt(5, row3, FALLING);
attachInterrupt(4, row4, FALLING);
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
abort(); //if the rtc fails to find computer time, the program will crash
}
/*
//check if the memory has already been setup
//if memory unaccessed then will return 255 for first
if (EEPROM.read(mempos) == 255) {
//set default memory to 0
EEPROM.write(mempos, '0');
}
// read in previous memory value
while (EEPROM.read(mempos) != 255) {
mem = EEPROM.read(mempos);
mempos++;
}
Serial.println(mem); */
}
// function for if a button on row 1 is pressed
void row1() {
detachInterrupt(0); // detach the interrupt to prevent multiple inputs
//Serial.print("Row 1 ");
checkbutton(2); // call function to check which column the button is in
attachInterrupt(0, row1, FALLING); // reattach input
}
// same as row1
void row2() {
detachInterrupt(1);
//Serial.print("Row 2 ");
checkbutton(3);
attachInterrupt(1, row2, FALLING);
}
// same as row1
void row3() {
detachInterrupt(5);
//Serial.print("Row 3 ");
checkbutton(18);
attachInterrupt(5, row3, FALLING);
}
//same as row 1
void row4() {
detachInterrupt(4);
//Serial.print("Row 4 ");
checkbutton(19);
attachInterrupt(4, row4, FALLING);
}
void loop() {
if (mode == 1){
Clock();
delay(1000);
}
}
//function for checking which column the button that was pressed is in
// takes current row as input to know which row the button is in
void checkbutton(int currentRow) {
int row = 0;
//for loop that iterates through the columns
for (int pin = 33; pin <= 39 ; pin += 1) {
//sets the current column to high
digitalWrite(pin, HIGH);
// if the current row is high then the button pressed is in the current column and current row
if (digitalRead(currentRow) == HIGH) {
//Serial.print("Column ");
//Serial.println(pin - 32);
//switch statement to change from the row pin to the row number in the array
switch (currentRow)
{
case 2:
row = 0;
break;
case 3:
row = 1;
break;
case 18:
row = 2;
break;
case 19:
row = 3;
break;
default:
row = 0;
break;
}
//call the input function with the corresponding array row and column to the button pressed
input(row, pin - 33);
// set the column back to low
digitalWrite(pin, LOW);
break;
//exit the loop as dont need to check further
}
// set the column to low regardless as a failsafe
digitalWrite(pin, LOW);
}
}
//main function that controls what key is pressed and what it should do
void input(int row, int column) {
char key = keys[row][column]; //sets 'key' equal to the ASCII code equivalent to
// the key being pressed by the user.
//Serial.println(key);
if (on == true) { //if a key is pressed, AND the LCD is on:
if (equalsPressed == true) { //if the equals key is pressed:
userin = ""; //user input string is cleared.
for (int clearSlot = 0; clearSlot < 101; clearSlot++) { //itterates through
// the user input, and second hold array, setting each slot to be blank.
userinarray[clearSlot] = {};
hold[clearSlot] = {};
}
ArraySlot = 0; //goes back to the start of the user input array.
//lcd.clear(); //LCD contents are cleared.
equalsPressed = false; //sets equalsPressed to false, breaking the if statement.
if (key == '+' || key == '-' || key == '*' || key == '/') {
Serial.println(ans); //if an operator is pressed after the equals key, the answer
// previously calculated is displayed, so user knows the value they're operating.
}
}
Serial.print(key); //key entered by user is displayed.
on = true; //bool for LCD power is set 'on' (relevent later).
if (key == '=') { //if equals is pressed:
//lcd.clear(); //LCD screen is cleared.
userinarray[ArraySlot] = userin.toDouble(); //arrayslot outputs of the user in array
// are set to be double datatype numbers (for extra precision).
// for(int i = 0; i< 10; i++){
// Serial.println(userinarray[i]);
// }
for (int ArraySlot = 0; ArraySlot < 101; ArraySlot++) {
if (userinarray[ArraySlot] == 's') {
squarerootFunc(ArraySlot);
ArraySlot = 0;
} else if (userinarray[ArraySlot] == '%') {
percentFunc(ArraySlot);
ArraySlot = 0;
}
}
for (int ArraySlot = 0; ArraySlot < 101; ArraySlot++) {
if (userinarray[ArraySlot] == '*') {
multiplicationFunc(ArraySlot);
ArraySlot = 0; // resets the array slot so that on next run restarts for loop
// so that calculator can handle numerous operations of the same type in
//one equatin and in the correct order of operations
Serial.println("hello");
} else if (userinarray[ArraySlot] == '/') {
divisionFunc(ArraySlot);
ArraySlot = 0;
}
}
for (int ArraySlot = 0; ArraySlot < 101; ArraySlot++) { //identical to the previous
// multiplication section starting on line 72 above, except this one checks for
// and completes addition and subtraction (+ and -).
if (userinarray[ArraySlot] == '+') {
Serial.println("+");
additionFunc(ArraySlot);
ArraySlot = 0;
} else if (userinarray[ArraySlot] == '-') {
Serial.println("-");
subtractionFunc(ArraySlot);
ArraySlot = 0;
}
}
ans = userinarray[0]; //answer is set to the first value of the user input array,
// thus saving this value if the user wants to further operate on it.
Serial.println(ans);
Serial.println(""); //the first slot of the user input array (the answer)
// is displayed to the user.
equalsPressed = true; //sets equals pressed true, thus preparing for the next
// equals press.
}
else if (key == 'P') { //if the power button is pressed (ie not the equals button):
on = false; //LCD on bool is set false
//lcd.clear(); //LCD display is cleared.
//lcd.noBacklight(); //LCD backlight is turned off.
userin = ""; //user input is cleared (set empty).
for (int clearSlot = 0; clearSlot < 101; clearSlot++) {
userinarray[clearSlot] = {};
hold[clearSlot] = {}; //both the storage arrays are cleared.
}
ArraySlot = 0; //user in array slot marker is set back to the beginning of the array,
// making it ready for next use.
equalsPressed = false; //equals pressed is set to false, ensureing the calculator
// cannot continue to be used after it has bee "turned off".
}
else if (key == '+' || key == '-' || key == '*' || key == '/') { //if operation buttons have been
// pressed (ie not the equals or power buttons):
if (userin == "") { //if the user input is empty:
userinarray[ArraySlot] = ans;
ArraySlot++; //the user input array is has it's current slot set to the
// pervious answer, and then moves directly to the next slot for more entries
// (thus allowing the old answer to be saved as a value the user can operate on).
} else { //if the user input isn't empty:
userinarray[ArraySlot] = userin.toDouble();
ArraySlot++; //the user input is saved to the current array slot, and the array
// marker is then moved to the next slot.
}
userinarray[ArraySlot] = key; //the operator is then saved in this new (empty) slot.
ArraySlot++; //moves to next array slot, preventint 2 operators being grouped.
userin = ""; //user input is cleared, ready for more entries.
}
else if (key == 's') {
if (userinarray[ArraySlot - 1] == '+' || userinarray[ArraySlot - 1] == '-') {
userinarray[ArraySlot] = 1.00;
ArraySlot++;
userinarray[ArraySlot] = '*';
ArraySlot++;
} else if (userinarray[ArraySlot - 1] == '*' || userinarray[ArraySlot - 1] == '/') {
} else {
userinarray[ArraySlot] = userin.toDouble();
ArraySlot++;
userinarray[ArraySlot] = '*';
ArraySlot++;
}
userinarray[ArraySlot] = 's';
ArraySlot++;
userin = "";
}
else if (key == '%') {
userinarray[ArraySlot] = userin.toDouble();
ArraySlot++;
userinarray[ArraySlot] = key;
ArraySlot++;
userin = "";
}
else if (userinarray[ArraySlot - 1] == '%') {
userinarray[ArraySlot] = '*';
ArraySlot++;
userin = userin + key;
//allows multiple numbers to be stored in the one array
// slot (meaning double and greater digit numbers can be input).
}
//Memory clear
else if (key == 'A') {
mem = 0;
}
//Memory Recall
else if (key == 'B') {
userin = userin + mem;
Serial.println(mem);
}
//Memory Subtract
else if (key == 'C') {
mem = mem - userin.toDouble();
}
//Memory add
else if (key == 'D') {
mem = mem + userin.toDouble();
}
//clock
else if (key == 'F'){
if (mode == 1){
lcd.clear();
mode = 0;
}
else{
mode = 1;
}
}
else {
userin = userin + key;
}
} else if (key == 'P') { //if the power button is pressed and its not currently on
on = true; //LCD on bool set true.
//lcd.backlight(); //LCD is turned on.
ans = 0; //any previous answer stored is cleared.
}
}
void plusMinusFunc() {
}
void squarerootFunc(int ArraySlot) {
double squareroot = sqrt(userinarray[ArraySlot + 1]);
int HoldSlot = 0;
while (HoldSlot < ArraySlot) {
hold[HoldSlot] = userinarray[HoldSlot];
HoldSlot++;
}
hold[HoldSlot] = squareroot;
HoldSlot++;
while (HoldSlot < 101) {
hold[HoldSlot] = userinarray[HoldSlot + 1];
HoldSlot++;
}
for (int slot = 0; slot < 99; slot++) {
userinarray[slot] = hold[slot];
}
}
void percentFunc(int ArraySlot) {
double percent = userinarray[ArraySlot - 1] / 100;
int HoldSlot = 0;
while (HoldSlot < ArraySlot - 1) {
hold[HoldSlot] = userinarray[HoldSlot];
HoldSlot++;
}
hold[HoldSlot] = percent;
HoldSlot++;
while (HoldSlot < 101) {
hold[HoldSlot] = userinarray[HoldSlot];
HoldSlot++;
}
for (int slot = 0; slot < 99; slot++) {
userinarray[slot] = hold[slot];
}
}
void multiplicationFunc(int ArraySlot) {
double multiply = (userinarray[ArraySlot - 1] * userinarray[ArraySlot + 1]);
//^^once an * is found in some array 'slot', the slots immediately to the left
// and right of the slot with '*' are multiplied; this is saved in the variable
// called 'multiply' (datatype double).^^
int HoldSlot = 0; //second storage array 'slot' marking variable, is set to
// equal 0 (meaning it will start searching through the array from the first
// slot in the array).
while (HoldSlot < ArraySlot - 1) { //while the HoldSlot is less than the current
// Array slot - 1 then the following lines run.
// eg if userinarray = 11 - 5 * 7 + 2, array slot would equal 3 as that is
// determined in the if statement in line 73 therefore loop runs for 0 1 2
hold[HoldSlot] = userinarray[HoldSlot]; //value at slot the loop is up to
// within the user array, set to the value for the hold array at the same slot
HoldSlot++;//increases increment for array slot to continue through the loop
// eg if userinarray = 11 - 5 * 7 + 2
// would set hold = 11 -
}
hold[HoldSlot] = multiply; // sets the next hold value in array to the result of
// the multiplication completed above
// eg if userinarray = 11 - 5 * 7 + 2 would take the 5 * 7 = 35 and add
// 35 to end of hold array, therefore hold = 11 - 35
HoldSlot++; // increases increment of position in hold array
while (HoldSlot < 101) { //while the hold array is not full
hold[HoldSlot] = userinarray[HoldSlot + 2]; // hold value is set to the value
//in user in array that is beyond the section of calculation taking place
//eg if userinarray = 11 - 5 * 7 + 2 and hold already set to 11 - 35 then
//now hold = 11 - 35 - 2
HoldSlot++; // increments hold slot to continue through while loop
}
for (int slot = 0; slot < 99; slot++) { //sets a new variable to increment through slots
userinarray[slot] = hold[slot]; //sets the values in hold array to the user in
// array slot for slot.
}
}
void divisionFunc(int ArraySlot) {
double division = (userinarray[ArraySlot - 1] / userinarray[ArraySlot + 1]);
int HoldSlot = 0;
while (HoldSlot < ArraySlot - 1) {
hold[HoldSlot] = userinarray[HoldSlot];
HoldSlot++;
}
hold[HoldSlot] = division;
HoldSlot++;
while (HoldSlot < 101) {
hold[HoldSlot] = userinarray[HoldSlot + 2];
HoldSlot++;
}
for (int slot = 0; slot < 99; slot++) {
userinarray[slot] = hold[slot];
}
}
void additionFunc(int ArraySlot) {
double addition = (userinarray[ArraySlot - 1] + userinarray[ArraySlot + 1]);
int HoldSlot = 0;
while (HoldSlot < ArraySlot - 1) {
hold[HoldSlot] = userinarray[HoldSlot];
HoldSlot++;
}
hold[HoldSlot] = addition;
HoldSlot++;
while (HoldSlot < 101) {
hold[HoldSlot] = userinarray[HoldSlot + 2];
HoldSlot++;
}
for (int slot = 0; slot < 99; slot++) {
userinarray[slot] = hold[slot];
}
}
void subtractionFunc(int ArraySlot) {
double subtract = (userinarray[ArraySlot - 1] - userinarray[ArraySlot + 1]);
int HoldSlot = 0;
while (HoldSlot < ArraySlot - 1) {
hold[HoldSlot] = userinarray[HoldSlot];
HoldSlot++;
}
hold[HoldSlot] = subtract;
HoldSlot++;
while (HoldSlot < 101) {
hold[HoldSlot] = userinarray[HoldSlot + 2];
HoldSlot++;
}
for (int slot = 0; slot < 99; slot++) {
userinarray[slot] = hold[slot];
}
}
void Clock() { //digital clock function (called above)
lcd.clear();
DateTime now = rtc.now(); //initialises 'now' as the rtc reference variable
char timearray[10]; //initialises array, to hold digital clock info (to be displayed)
sprintf(timearray, "%d : %d : %d", now.hour(), now.minute(), now.second());
//^maps rtc clock info, into timearray array.
lcd.print(timearray);
Serial.println(timearray);
}