Help on arduino calculator project

Basically I want to create a serial communication calculator on my arduino that can handle simple addition, subtraction, multiplication and division. The project doesn't seem to work. Can someone explain why?

Code: /* The Arduino serial calculator (rev.1)

  • Main function: Calculate addition (+), subtraction (-),
  • multiplication(*) and division(/)
    */

//defining variables

long number1; // - first number of calculation
// - sent through the Serial Monitor
long number2; // - second number of calculator, same as number1
//long variables are able to store big numbers

char calSignal; //character variable created to store
//calculation signals

long result; //result of calculation
//this is a long variable, so it can result in big numbers

void setup() {
Serial.begin(9600);

Serial.println("Hello!"); //tests serial communication
Serial.println("Please insert your first number."); //for easier debugging
Serial.println(); //leaves a clear row
}

void loop() {
while(Serial.available() > 0) {
number1 = Serial.parseInt(); //parseInt() can store 2 digits (i.e: "23")

Serial.println("Please insert your function");
Serial.println();

while(Serial.available() = "+" = "-" = "*" = "/") {
calSignal = Serial.read();

Serial.println("Please insert your second number");
Serial.println();

while(Serial.available() > 0) {
number2 = Serial.parseInt();

Result(); //a custom function to solve the calculation (see below)

Serial.print("Result = ");
Serial.println(result); //prints out the result
Serial.println(); //leaves a clear row
Serial.println("Please insert your first number");
Serial.println(); //leaves a clear row
}
}
}
}

void Result() {
switch(calSignal) { //a list of functions that the calculator can handle
case '+': //addition function
result = number1 + number2;
break;

case '-': //subtraction function
result = number1 - number2;
break;

case '*': //multiplication function
result = number1 * number2;
break;

case '/': //division function
result = number1 / number2;
break;

default:
Serial.println("Equation is invalid."); //displays an error for the user to see
Serial.println(); //leaves an empty row

result = 0;
}
}

Thank you.

-Keanny

KeannyOoi:
The project doesn't seem to work. Can someone explain why?

Because the code does not even compile.

    while (Serial.available() = "+" = "-" = "*" = "/") {
    while(Serial.available() = "+" = "-" = "*" = "/") {

Serial.available() returns the number of bytes in the buffer. Replace that call with a number, and this mess still doesn't make sense.

i just don't know what to do

i am not really good at arduino

KeannyOoi:
i just don't know what to do

1. Try the following structure:

Serial.println("Please insert your first number.");
  while (Serial.available() != 2)
  {
    ;
  }

  {
    number1 = Serial.parseInt(); //parseInt() can store 2 digits (i.e: "23")
    Serial.println();
  }

2. Use the Result() function in more formal way:
Hints:

result = Result(calSignal);

long Result(char x)
{
    switch(x)
    {
       //......................
       return number1+number2;
    }
}

scr-11.png

scr-11.png

I think it is not very clever to prompt for each component.

I would read the line until complete, dropping blanks on the way.
The resulting string can be quite easily analyzed and processed.

const byte maxMsgLen = 64;
const byte cbLF = 10;
const byte cbCR = 13;
const byte cbBlank = ' ';

const char ops[] = "+-*/";

void setup() {
  Serial.begin(250000);
  Serial.println(F("Enter simple expressions like '84 / 2'"));
}

void loop() {
  handleSerial();
}

void oneLineReceived(const char * buffer) {
  int32_t arg1, arg2;
  char op;
  int count = sscanf(buffer, "%ld%c%ld", &arg1, &op, &arg2);
  if (count != 3) {
    Serial.print(buffer);
    Serial.println(F(" - bad expression format"));
  } else {
    char* ptr = strchr(ops, op);
    if (ptr == nullptr) {
      Serial.print(buffer);
      Serial.println(F(" - operator not supported"));
    } else {
      int32_t result = 0;
      switch (op) {
        case '+':
          result = arg1 + arg2;
          break;
        case '-':
          result = arg1 - arg2;
          break;
        case '*':
          result = arg1 * arg2;
          break;
        case '/':
          result = arg1 / arg2;
          break;
      }
      Serial.print(arg1);
      Serial.write(' ');
      Serial.write(op);
      Serial.write(' ');
      Serial.print(arg2);
      Serial.print(F(" = "));
      Serial.print(result);
      Serial.println();
    }
  }
}

void handleSerial() {
  static uint8_t bIndex;
  static uint8_t buffer[maxMsgLen + 1];
  bool lineReady = false;
  if (Serial.available()) {
    uint8_t inChar = Serial.read();
    if (inChar != cbLF && inChar != cbBlank) {
      if (inChar == cbCR) {
        lineReady = true;
      } else {
        buffer[bIndex++] = inChar;
        lineReady = (bIndex == maxMsgLen);
      }
      if (lineReady) {
        buffer[bIndex] = 0;
        oneLineReceived((const char*)buffer);
        bIndex = 0;
      }
    }
  }
}
Enter simple expressions like '84 / 2'
67%3 - operator not supported
34 - bad expression format
56-+ - bad expression format
56 - 6 = 50

GolamMostafa:

  while (Serial.available() != 2)

{
   ;
 }

If already three or more chars are available that will be an endless loop, bad idea.

KeannyOoi:
i just don't know what to do

i am not really good at arduino

Start by learning.

Before you could write a post you had to learn ABC then spelling then grammar. And still you would need a lot of practice before you could write even a short story worth reading.

Whandall:
If already three or more chars are available that will be an endless loop, bad idea.

The system will not accept data less than 2-digit; there is no harm to accept data more than 2-digit.
scr-12.png

scr-12.png

GolamMostafa:
The system will not accept data less than 2-digit; there is no harm to accept data more than 2-digit.

You were just lucky that it did not happen this time,
but can you guarantee that this will always be the case,
especially with a beginner that is attracted by delay?

Wouldn’t it not just be better to change the != into a < ?

But nevermind, I was just giving a hint.

You may hang your or the OPs sketch anytime, no Arduino will complain.

Whandall:
I think it is not very clever to prompt for each component.

I would read the line until complete, dropping blanks on the way.
The resulting string can be quite easily analyzed and processed.

const byte maxMsgLen = 64;

const byte cbLF = 10;
const byte cbCR = 13;
const byte cbBlank = ' ';

const char ops = "+-*/";

void setup() {
  Serial.begin(250000);
  Serial.println(F("Enter simple expressions like '84 / 2'"));
}

void loop() {
  handleSerial();
}

void oneLineReceived(const char * buffer) {
  int32_t arg1, arg2;
  char op;
  int count = sscanf(buffer, "%ld%c%ld", &arg1, &op, &arg2);
  if (count != 3) {
    Serial.print(buffer);
    Serial.println(F(" - bad expression format"));
  } else {
    char* ptr = strchr(ops, op);
    if (ptr == nullptr) {
      Serial.print(buffer);
      Serial.println(F(" - operator not supported"));
    } else {
      int32_t result = 0;
      switch (op) {
        case '+':
          result = arg1 + arg2;
          break;
        case '-':
          result = arg1 - arg2;
          break;
        case '*':
          result = arg1 * arg2;
          break;
        case '/':
          result = arg1 / arg2;
          break;
      }
      Serial.print(arg1);
      Serial.write(' ');
      Serial.write(op);
      Serial.write(' ');
      Serial.print(arg2);
      Serial.print(F(" = "));
      Serial.print(result);
      Serial.println();
    }
  }
}

void handleSerial() {
  static uint8_t bIndex;
  static uint8_t buffer[maxMsgLen + 1];
  bool lineReady = false;
  if (Serial.available()) {
    uint8_t inChar = Serial.read();
    if (inChar != cbLF && inChar != cbBlank) {
      if (inChar == cbCR) {
        lineReady = true;
      } else {
        buffer[bIndex++] = inChar;
        lineReady = (bIndex == maxMsgLen);
      }
      if (lineReady) {
        buffer[bIndex] = 0;
        oneLineReceived((const char*)buffer);
        bIndex = 0;
      }
    }
  }
}





Enter simple expressions like '84 / 2'
67%3 - operator not supported
34 - bad expression format
56-+ - bad expression format
56 - 6 = 50

Hold on a sec, can the code run using the 9600 baud?

The slower the baud rate, the longer it takes to send serial output. The output buffer is 64 chars and if it fills your sketch STOPS until it is no longer full. Your IDE and Serial Monitor if up to date can handle 250000 baud (that's bits per second where default serial needs 10 bits per char == 1 start, 8 data, 1 stop bit). You should run serial at least 115200 when it goes through USB and only use slower when you have to.

GoForSmoke:
The slower the baud rate, the longer it takes to send serial output. The output buffer is 64 chars and if it fills your sketch STOPS until it is no longer full. Your IDE and Serial Monitor if up to date can handle 250000 baud (that’s bits per second where default serial needs 10 bits per char == 1 start, 8 data, 1 stop bit). You should run serial at least 115200 when it goes through USB and only use slower when you have to.

huh, my coach uses the 9600 baud all the time. He is a specialist at that kind of stuff. please explain?

KeannyOoi:
huh, my coach uses the 9600 baud all the time. He is a specialist at that kind of stuff. please explain?

It's just a bad habit of his, there's no benefit to running so slowly unless you're dealing with a very noisy electrical environment.

Consider this: back in the early days of motoring, cars were slow. Poor roads, weak engines and primitive suspension all conspired to keep speeds down.

Would you drive a modern car at 20mph on the highway because of speeds achievable in 1905? Of course not.

KeannyOoi:
huh, my coach uses the 9600 baud all the time. He is a specialist at that kind of stuff. please explain?

I hope you mean please explain more because I gave the explicit facts and you did quote them.

A sketch that isn't blocked can easily overflow the serial output buffer in under 1ms. Good code avoids that. however the faster that buffer does clear the more serial output (like debug trace prints) your sketch can make.

9600 baud = 960 chars per second. When the buffer fills and there are still chars left to print, your sketch has to WAIT over 1 millisecond for each char to get sent until it's not filled. 1 ms is 16000 cpu cycles where a few light tasks might take 200 to 300. Those tasks might include checking pins 40 times in 1 millisecond, waiting for serial overflow to clear means not checking those pins > 40 times per overflow print character and missing events the sketch needs to catch. At high baud rate the same sketch may never reach overflow where at 9600 it'd be tripping over its own feet.

Does your coach write non-blocking code? What is your coach's specialty?