Hello everyone, currently building an arduino calculator and i wanted to add a few push buttons for additional operations as parenthesis sin cos and a decimal point.
When i click a button at the moment i get no input on the screen, so i guess its either not connected properly or the code itself is not right.
Any help is appreciated.
#include <StandardCplusplus.h>
#include <system_configuration.h>
#include <unwind-cxx.h>
#include <utility.h>
#include <stack>
#include <cmath>
#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
using namespace std;
// Function to check if a character is an operator
bool isOperator(char c) {
return c == '+' || c == '-' || c == '*' || c == '/' || c == 'c' || c == 's' || c == '=';
}
// Function to check if a string represents a function
bool isFunction(const String& str) {
return str == "cos" || str == "sin";
}
// Define operator precedence using an array
int operatorPrecedence[256] = {};
void initializeOperatorPrecedence() {
operatorPrecedence['+'] = 1;
operatorPrecedence['-'] = 1;
operatorPrecedence['*'] = 2;
operatorPrecedence['/'] = 2;
operatorPrecedence['c'] = 3;
operatorPrecedence['s'] = 3;
operatorPrecedence['='] = 0; // '=' is for evaluating the expression
}
// Function to check if op1 has higher precedence than op2
bool hasHigherPrecedence(char op1, char op2) {
return operatorPrecedence[op1] > operatorPrecedence[op2];
}
// Function to perform the operation based on the operator
double performOperation(double operand1, double operand2, char op) {
switch (op) {
case '+':
return operand1 + operand2;
case '-':
return operand1 - operand2;
case '*':
return operand1 * operand2;
case '/':
return operand1 / operand2;
case 'c':
return cos(operand1);
case 's':
return sin(operand1);
default:
return 0.0; // Handle other cases as needed
}
}
// Function to perform a trigonometric function
double performFunction(const String& func, double arg) {
if (func == "cos") {
return cos(arg * (M_PI / 180));
}
else if (func == "sin") {
return sin(arg * (M_PI / 180));
}
else {
return 0.0; // Handle other functions as needed
}
}
double evaluateExpression(const String& expression) {
stack<double> numStack;
stack<String> opStack;
size_t i = 0;
while (i < expression.length()) {
if (isdigit(expression[i]) || expression[i] == '.') {
// If the character is a digit or a decimal point, extract the entire number
size_t j = i;
while (j < expression.length() && (isdigit(expression[j]) || expression[j] == '.')) {
j++;
}
String numStr = expression.substring(i, j);
double num = numStr.toDouble(); // Convert the string to a double
numStack.push(num);
i = j;
}
else if (isAlpha(expression[i])) {
// If the character is a letter, it might be a function name
size_t j = i;
while (j < expression.length() && isAlpha(expression[j])) {
j++;
}
String funcName = expression.substring(i, j);
if (isFunction(funcName)) {
opStack.push(funcName); // Push the function name onto the operator stack
}
else {
return 0.0; // Handle unrecognized functions
}
i = j;
}
else if (isOperator(expression[i])) {
// If the character is an operator, handle precedence and parentheses
while (!opStack.empty() && opStack.top() != "(" && hasHigherPrecedence(opStack.top()[0], expression[i])) {
String op = opStack.top();
opStack.pop();
if (op == "cos" || op == "sin") {
double arg = numStack.top();
numStack.pop();
double result = performFunction(op, arg);
numStack.push(result);
}
else {
double operand2 = numStack.top();
numStack.pop();
double operand1 = numStack.top();
numStack.pop();
double result = performOperation(operand1, operand2, op[0]);
numStack.push(result);
}
}
opStack.push(String(expression[i]));
i++;
}
else if (expression[i] == '(') {
// If an opening parenthesis is encountered, push it onto the operator stack
opStack.push("(");
i++;
}
else if (expression[i] == ')') {
// If a closing parenthesis is encountered, evaluate the expression inside the parentheses
while (!opStack.empty() && opStack.top() != "(") {
String op = opStack.top();
opStack.pop();
if (op == "cos" || op == "sin") {
double arg = numStack.top();
numStack.pop();
double result = performFunction(op, arg);
numStack.push(result);
}
else {
double operand2 = numStack.top();
numStack.pop();
double operand1 = numStack.top();
numStack.pop();
double result = performOperation(operand1, operand2, op[0]);
numStack.push(result);
}
}
// Pop the opening parenthesis from the operator stack
if (!opStack.empty() && opStack.top() == "(") {
opStack.pop();
}
else {
return 0.0; // Mismatched parentheses
}
i++;
}
else {
return 0.0; // Invalid character
}
}
// Evaluate any remaining operators
while (!opStack.empty()) {
String op = opStack.top();
opStack.pop();
if (op == "cos" || op == "sin") {
double arg = numStack.top();
numStack.pop();
double result = performFunction(op, arg);
numStack.push(result);
}
else {
double operand2 = numStack.top();
numStack.pop();
double operand1 = numStack.top();
numStack.pop();
double result = performOperation(operand1, operand2, op[0]);
numStack.push(result);
}
}
// The final result will be at the top of the number stack
return numStack.top();
}
// Define the I2C address and LCD dimensions
#define I2C_ADDRESS 0x27
#define LCD_COLUMNS 16
#define LCD_ROWS 2
// Create a LiquidCrystal_I2C object
LiquidCrystal_I2C lcd(I2C_ADDRESS, LCD_COLUMNS, LCD_ROWS);
// Define the keypad layout
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] = {
{'1','2','3','+'},
{'4','5','6','-'},
{'7','8','9','*'},
{'c','0','=','/'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad
// Define the additional operation buttons
const int openParenButton = A0;
const int closeParenButton = A1;
const int decimalPointButton = A2;
const int sinButton = A3;
const int cosButton = A4;
const int sqrtButton = A5;
// Create a Keypad object
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
void setup() {
// Initialize the LCD
lcd.init();
lcd.backlight();
lcd.clear();
// Initialize operator precedence
initializeOperatorPrecedence();
// Initialize the serial communication (for debugging)
Serial.begin(9600);
// Set the additional operation buttons as inputs
pinMode(openParenButton, INPUT_PULLUP);
pinMode(closeParenButton, INPUT_PULLUP);
pinMode(decimalPointButton, INPUT_PULLUP);
pinMode(sinButton, INPUT_PULLUP);
pinMode(cosButton, INPUT_PULLUP);
pinMode(sqrtButton, INPUT_PULLUP);
}
void loop() {
String expression;
lcd.clear(); // Clear the LCD screen
// Display a message on the LCD
lcd.setCursor(0, 0);
lcd.print("Enter an expr:");
// Use the keypad for input
char key = keypad.getKey();
while (key != '=') { // '=' key will evaluate the expression
if (key) {
expression += key;
lcd.setCursor(expression.length() - 1, 1);
lcd.print(key);
}
key = keypad.getKey();
}
// Check for additional operation buttons
if (digitalRead(openParenButton) == LOW) {
expression += "(";
lcd.setCursor(expression.length() - 1, 1);
lcd.print("(");
}
if (digitalRead(closeParenButton) == LOW) {
expression += ")";
lcd.setCursor(expression.length() - 1, 1);
lcd.print(")");
}
if (digitalRead(decimalPointButton) == LOW) {
expression += ".";
lcd.setCursor(expression.length() - 1, 1);
lcd.print(".");
}
if (digitalRead(sinButton) == LOW) {
expression += "s";
lcd.setCursor(expression.length() - 1, 1);
lcd.print("s");
}
if (digitalRead(cosButton) == LOW) {
expression += "c";
lcd.setCursor(expression.length() - 1, 1);
lcd.print("c");
}
if (digitalRead(sqrtButton) == LOW) {
expression += "sqrt";
lcd.setCursor(expression.length() - 1, 1);
lcd.print("sqrt");
}
// Evaluate the expression
double result = evaluateExpression(expression);
// Display the result on the LCD
lcd.setCursor(0, 1);
lcd.print("Result: ");
lcd.print(result, 2); // Display result with 2 decimal places
// Print the result to serial for debugging
Serial.print("Result: ");
Serial.println(result);
// Wait for a moment before clearing the LCD
delay(2000);
lcd.clear();
}


