/*
Arduino | hardware-help
Keypad calculator
Zeruxe — 6/16/24 at 7:25 PM
From this not-so-good example:
https://www.hackster.io/nolimitcircuit/arduinolator-an-arduino-calculator-b544ff
This not so great but working "4 banger" calculator...
*/
#include <Keypad.h>
#include <LiquidCrystal.h>
const byte ROWS = 4;
const byte COLS = 4;
const char keys [ROWS] [COLS] = {
{'1', '2', '3', '+'},
{'4', '5', '6', '-'},
{'7', '8', '9', '*'},
{'.', '0', '=', '/'}
};
const byte rowPins[ROWS] = {23, 25, 27, 29};
const byte colPins[COLS] = {31, 33, 35, 37};
const byte CLEAR_PIN = 39;
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
bool isResult = false;
char opKey;
char operandBuffer[2][8];
char operand1[8];
char operand2[8];
int operatorIdx = 0;
int operandIdx = 0;
void checkClear() {
static int oldState = HIGH;
int state = digitalRead(CLEAR_PIN);
if (state != oldState) {
oldState = state;
if (state == LOW) {
doClear();
}
delay(20); // debounce
}
}
void doClear() {
Serial.println("Clear");
lcd.clear();
operatorIdx = 0;
operandIdx = 0;
memset(operandBuffer[0], 0, sizeof(operandBuffer[0]));
memset(operandBuffer[1], 0, sizeof(operandBuffer[1]));
isResult = false;
}
void charsToLCD(int zone, char* value, int len) {
Serial.println(value);
int row = 0;
int col = 0;
switch (zone) {
case 0: // print op1
row = 0;
col = 17 - len;
//lcd.setCursor(col, row);
break;
case 1: // print op2
row = 1;
col = 17 - len;
//lcd.setCursor(col, row);
//lcd.setCursor(10, 1);
break;
case 2: // print result
lcd.setCursor(10, 2);
lcd.print("--------");
row = 3;
col = 20 - len;
//lcd.setCursor(col, row);
break;
default:
lcd.print("Bad zone!");
break;
}
lcd.setCursor(col, row);
lcd.print(value);
}
void setup() {
Serial.begin(9600);
lcd.begin(20, 4);
pinMode(CLEAR_PIN, INPUT_PULLUP);
lcd.setCursor(6, 1);
lcd.print("Arduino");
lcd.setCursor(5, 2);
lcd.print("Calculator");
delay(1000);
lcd.clear();
}
void loop() {
double result = 0;
char lcdBuff[16];
int buffLen = 0;
char * pch;
int pchLen = 0;
//char fLcdBuff[16];
char key = keypad.getKey();
checkClear();
if (key != NO_KEY) {
if (isResult) doClear();
//Serial.print(key);
//lcd.print(key);
if (key >= '0' && key <= '9' || key == '.') {
//Serial.println(" is a number.");
operandBuffer[operatorIdx][operandIdx] = key;
operandIdx++;
buffLen = strlen(operandBuffer[operatorIdx]);
pch = strstr(operandBuffer[operatorIdx], ".");
if (pch != '\0') pchLen = strlen(pch);
Serial.print("Len decimal ");
Serial.println(pchLen);
//Serial.println(operandBuffer[operatorIdx]);
charsToLCD(operatorIdx, operandBuffer[operatorIdx], buffLen);
} else {
//Serial.println(" is an operator.");
operandBuffer[operatorIdx][operandIdx] = '\0'; // terminate operand string
operandIdx = 0; // reset buffer index
if (operatorIdx == 0) {
strncpy(operand1, operandBuffer[0], 8);
operatorIdx = 1;
} else {
strncpy(operand2, operandBuffer[1], 8);
operatorIdx = 0;
}
double dOp1 = atof(operand1);
double dOp2 = atof(operand2);
//opKey = key; // save operator
if (key != '=') {
opKey = key; // save operator
lcd.setCursor(19, 0);
lcd.print(opKey);
} else if (key == '=') {
Serial.print(opKey);
switch (opKey) {
case '+':
result = dOp1 + dOp2;
break;
case '-':
result = dOp1 - dOp2;
break;
case '*':
result = dOp1 * dOp2;
break;
case '/':
result = dOp1 / dOp2;
break;
default:
result = -9999999;
break;
}
Serial.println(result);
// dtostrf(float_value, min_width, num_digits_after_decimal, where_to_store_string)
dtostrf(result, 3, 2, lcdBuff);
//snprintf(fLcdBuff, 8, "%s", lcdBuff);
//Serial.println(lcdBuff);
buffLen = strlen(lcdBuff);
Serial.print("Buffer size: ");
Serial.println(buffLen);
charsToLCD(2, lcdBuff, buffLen);
isResult = true;
operatorIdx = 0;
}
}
}
}
Clear