/*
Forum: https://forum.arduino.cc/t/arduino-makes-parts-of-text-disappear-in-serial-println/1396591
Wokwi: https://wokwi.com/projects/436924052037003265
The mathematic functions provided by the TO have not been checked for correctness!
There is still room for improvement ...
2025/07/20
ec2021
*/
enum operations { HELP, PLUS, MINUS, TIMES, DIVIDE, MODULO, POWER, GAMMA,
SQRT, SIN, COS, TAN, CSC, SEC, COT, ARCSIN,
ARCCOS, ARCTAN, ARCCSC, ARCSEC, ARCCOT
};
char operation[][9] = {
"help", "+", "-", "*", "/", "%", "^", "!", "sqrt", "sin", "cos", "tan",
"csc", "sec", "cot", "arcsin", "arccos", "arctan", "arccsc",
"arcsec", "arccot"
};
constexpr int noOfOps = sizeof(operation) / sizeof(operation[0]);
boolean hasOneParameter;
constexpr float e = 2.718281828459045;
constexpr int maxChars = 11;
char cOperation[maxChars] = "";
float a;
float b;
float c;
void setup() {
Serial.begin(115200);
printOps();
Serial.println(F("Input 'help' to print the Operators"));
}
void loop() {
receiveOperation();
evaluateOperation();
delay(3000);
}
void receiveOperation() {
Serial.println(F("Choose Operation"));
getString(cOperation);
}
void getString(char *buff) {
boolean done = false;
int index = 0;
while (!done) {
if (Serial.available()) {
char c = Serial.read();
if (c < ' ') {
done = (index > 0);
} else {
if (!(c == '(' || c == ')')) {
buff[index++] = c;
}
done = (index == maxChars - 2);
}
}
}
buff[index] = 0x00;
clearSerial();
}
void clearSerial() {
while (Serial.available()) {
char c = Serial.read();
}
}
void evaluateOperation() {
int mode = -1;
for (int i = 0; i < noOfOps; i++) {
if (strcmp(cOperation, operation[i]) == 0) {
mode = i;
break;
}
}
if (mode == -1) {
Serial.print(cOperation);
Serial.println(F("\tUnknown or wrong operation"));
return;
}
if (mode == HELP) {
printOps();
return;
}
printOperation(mode);
Serial.println();
a = getParameter(hasBrackets(mode) ? "Single " : "First ");
if (!hasBrackets(mode)) {
b = getParameter("Second");
}
doOperation(mode);
}
float getParameter(char *buf) {
char cFloat[maxChars] = "";
Serial.print(buf);
Serial.print(F(" Parameter = "));
getString(cFloat);
Serial.println(cFloat);
return atof(cFloat);
}
void printOps() {
Serial.println(F("*************************************"));
for (int i = 0; i < noOfOps; i++) {
printOperation(i);
if (i % 5 == 4) {
Serial.println();
}
}
Serial.println(F("\n*************************************"));
}
boolean hasBrackets(int op) {
if (op < 0 || op >= noOfOps) {
return false;
}
return op >= GAMMA;
}
void printOperation(int i) {
Serial.print(operation[i]);
Serial.print( hasBrackets(i) ? "() " : "\t");
}
void doOperation(int opNo) {
switch (opNo) {
case PLUS:
c = a + b;
break;
case MINUS:
c = a + b;
break;
case TIMES:
c = a * b;
break;
case DIVIDE:
if (b == 0) {
Serial.println(F("Division by 0 not allowed!"));
return;
}
c = a / b;
break;
case MODULO:
c = long(a) % long(b);
break;
case POWER:
c = pow(a, b);
break;
case GAMMA:
c = gamma(a);
break;
case SQRT:
c = squareRoot(a);
break;
case SIN:
c = sine(a);
break;
case COS:
c = cosine(a);
break;
case TAN:
c = sine(a) / cosine(a);
break;
case CSC:
c = 1 / sine(a);
break;
case SEC:
c = 1 / cosine(a);
break;
case COT:
c = cosine(a) / sine(a);
break;
case ARCSIN:
c = arcS(a);
break;
case ARCCOS:
c = PI / 2 - arcS(a);
break;
case ARCTAN:
c = arcT(a);
break;
case ARCCSC:
case ARCSEC:
case ARCCOT:
// TBD
notImplemented();
return;
break;
default:
return;
}
printformatted(opNo);
}
void notImplemented() {
Serial.println(F("Not yet implemented ..."));
}
void printformatted(int no) {
if (hasBrackets(no)) {
Serial.print(operation[no]);
Serial.print('(');
Serial.print(a);
Serial.print(')' );
} else {
Serial.print(a);
Serial.print(' ');
Serial.print(operation[no]);
Serial.print(' ');
Serial.print(b);
}
Serial.print(" = ");
Serial.println(c);
}
/******************************************************************/
/* Functions as provided by TO */
/* NOT CHECKED FOR CORRECTNESS */
/******************************************************************/
float squareRoot(float n) {
float i;
while ((i * i) < n) {
if ((i * i) < n) {
i += 0.01;
}
} if ( abs((n - i * i)) < abs((n - (i - 0.01) * (i - 0.01))) ) {
return i;
} else {
return i - 0.01;
}
}
float sine(float n) {
float ans;
float place;
while (n > PI) {
n -= PI;
} while (n < -1 * PI) {
n += PI;
} for (int i = 1; i <= 21; i += 2) {
place = pow(n, i);
for (int j = 1; j <= i; j++) {
place = place / j;
} if (((i + 1) / 2) % 2 == 0) {
ans += place;
} else {
ans -= place;
}
} return ans;
}
float cosine(float n) {
float ans;
float place;
for (int i = 0; i <= 20; i += 2) {
place = pow(n, i);
for (int j = 1; j <= i; j++) {
place = place / j;
} if ((i / 2) % 2 == 1) {
ans += place;
} else {
ans -= place;
}
} return ans;
}
float arcS(float n) {
float ans;
float place;
for (int i = 1; i <= 21; i += 2) {
place = pow(n, i) / i;
for (int j = 1; j <= i - 1; j++) {
if (j % 2 == 1) {
place *= j;
} else {
place /= j;
}
} ans += place;
} return ans;
}
float arcT(float n) {
float ans;
float place;
if (abs(n) < 1) {
return sine(n);
} else {
if (n > 0) {
ans = PI / 2;
} else {
ans = -1 * PI / 2;
} for (int i = 1; i <= 21; i += 2) {
place = 1 / (i * pow(n, i));
if (((i + 1) / 2) % 2 == 1) {
ans += place;
} else {
;
ans -= place;
}
} return ans;
}
}
float gamma(float n) {
n += 1;
int g = 7;
float lanczos[] = {
0.99999999999980993,
676.5203681218851,
-1259.1392167224028,
771.32342877765313,
-176.61502916214059,
12.507343278686905,
-0.13857109526572012,
9.9843695780195716e-6,
1.5056327351493116e-7
};
int maxIndex = sizeof(lanczos) / sizeof(lanczos[0]);
if (n < 0.5) {
return PI / (sine(PI * n) * gamma(1 - n));
} else {
n -= 1;
float place = lanczos[0];
for (int i = 1; i < maxIndex; i++) {
place += lanczos[i] / (n + i);
} float v = n + g + 0.5;
return squareRoot(2 * PI) * pow(v, n + 0.5) * pow(e, -1 * v) * place;
}
}